Brew heater controller. Programmed to mash grain and to boil wort

Dependencies:   mbed QEI UniGraphic

Committer:
dswood
Date:
Fri Jan 07 12:08:12 2022 +0000
Revision:
0:c673d397e9dc
First release.  Works but is a little clunky.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
dswood 0:c673d397e9dc 1 /**
dswood 0:c673d397e9dc 2
dswood 0:c673d397e9dc 3 Spice modal
dswood 0:c673d397e9dc 4 .SUBCKT NTCLE203E3103SB0 RN Rp PARAMS: TOLR=0 TOLB=0
dswood 0:c673d397e9dc 5 X64 Rn Rp NTC_BASE Params:
dswood 0:c673d397e9dc 6 + w=-14.6571976
dswood 0:c673d397e9dc 7 + x=4798.842
dswood 0:c673d397e9dc 8 + y=-115334
dswood 0:c673d397e9dc 9 + z=-3730535
dswood 0:c673d397e9dc 10 + gth=0.0032 gth1 = 0.0000167
dswood 0:c673d397e9dc 11 + cth=0.032
dswood 0:c673d397e9dc 12 + a=-14.65719769
dswood 0:c673d397e9dc 13 + r25=10000
dswood 0:c673d397e9dc 14 + b=4798.842
dswood 0:c673d397e9dc 15 + c=-115334
dswood 0:c673d397e9dc 16 + d=-3730535
dswood 0:c673d397e9dc 17 + T0=273.15
dswood 0:c673d397e9dc 18 + TR={1+TOLR/100}
dswood 0:c673d397e9dc 19 + TB={1+TOLB/100}
dswood 0:c673d397e9dc 20 .ENDS
dswood 0:c673d397e9dc 21
dswood 0:c673d397e9dc 22 */
dswood 0:c673d397e9dc 23
dswood 0:c673d397e9dc 24
dswood 0:c673d397e9dc 25 /* Includes ------------------------------------------------------------------*/
dswood 0:c673d397e9dc 26
dswood 0:c673d397e9dc 27 /* mbed specific header files. */
dswood 0:c673d397e9dc 28 /*
dswood 0:c673d397e9dc 29 GPIO_InitTypeDef GPIO_InitStruct;
dswood 0:c673d397e9dc 30 //Configure GPIO pin : PB14
dswood 0:c673d397e9dc 31 GPIO_InitStruct.Pin = GPIO_PIN_14;
dswood 0:c673d397e9dc 32 GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; // digital Output
dswood 0:c673d397e9dc 33 GPIO_InitStruct.Speed = GPIO_SPEED_LOW;
dswood 0:c673d397e9dc 34 HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
dswood 0:c673d397e9dc 35 */
dswood 0:c673d397e9dc 36 #include "mbed.h"
dswood 0:c673d397e9dc 37 #include "SSD1306.h"
dswood 0:c673d397e9dc 38 #include "string"
dswood 0:c673d397e9dc 39
dswood 0:c673d397e9dc 40 #include "MashProfile.h"
dswood 0:c673d397e9dc 41 #include "MashProfileFull.h"
dswood 0:c673d397e9dc 42 #include "Boil1.h"
dswood 0:c673d397e9dc 43 #include "Boil2.h"
dswood 0:c673d397e9dc 44 #include "Boil3.h"
dswood 0:c673d397e9dc 45 #ifndef PROFILES
dswood 0:c673d397e9dc 46 #define PROFILES
dswood 0:c673d397e9dc 47 #include "Profiles.h"
dswood 0:c673d397e9dc 48 #endif //Profiles
dswood 0:c673d397e9dc 49
dswood 0:c673d397e9dc 50 #define Height 32
dswood 0:c673d397e9dc 51 #define Width 132
dswood 0:c673d397e9dc 52
dswood 0:c673d397e9dc 53
dswood 0:c673d397e9dc 54
dswood 0:c673d397e9dc 55 #include "QEI.h"
dswood 0:c673d397e9dc 56
dswood 0:c673d397e9dc 57 //Firing delay in microseconds
dswood 0:c673d397e9dc 58 #define SyncToZeroCrossingDelayRise 115
dswood 0:c673d397e9dc 59 #define SyncToZeroCrossingDelayFall 115
dswood 0:c673d397e9dc 60
dswood 0:c673d397e9dc 61 #define TriacPulseLength 250
dswood 0:c673d397e9dc 62 // Blinking rate in milliseconds
dswood 0:c673d397e9dc 63 #define BLINKING_RATE_MS 500
dswood 0:c673d397e9dc 64 #define Bias_Current 0.261 // Thermistor current in mA
dswood 0:c673d397e9dc 65 /*
dswood 0:c673d397e9dc 66
dswood 0:c673d397e9dc 67 FIR filter designed with
dswood 0:c673d397e9dc 68 http://t-filter.appspot.com
dswood 0:c673d397e9dc 69
dswood 0:c673d397e9dc 70 sampling frequency: 2000 Hz
dswood 0:c673d397e9dc 71
dswood 0:c673d397e9dc 72 * 0 Hz - 100 Hz
dswood 0:c673d397e9dc 73 gain = 1
dswood 0:c673d397e9dc 74 desired ripple = 5 dB
dswood 0:c673d397e9dc 75 actual ripple = 1.0675530446538501 dB
dswood 0:c673d397e9dc 76
dswood 0:c673d397e9dc 77 * 600 Hz - 1000 Hz
dswood 0:c673d397e9dc 78 gain = 0
dswood 0:c673d397e9dc 79 desired attenuation = -60 dB
dswood 0:c673d397e9dc 80 actual attenuation = -71.5928467318133 dB
dswood 0:c673d397e9dc 81
dswood 0:c673d397e9dc 82 */
dswood 0:c673d397e9dc 83
dswood 0:c673d397e9dc 84 #define NumberOfTaps 9
dswood 0:c673d397e9dc 85
dswood 0:c673d397e9dc 86 static double filter_taps[NumberOfTaps] = {
dswood 0:c673d397e9dc 87 0.009246906411528302,
dswood 0:c673d397e9dc 88 0.0484176527692072,
dswood 0:c673d397e9dc 89 0.12764201806827455,
dswood 0:c673d397e9dc 90 0.21665898750162413,
dswood 0:c673d397e9dc 91 0.25663867508629506,
dswood 0:c673d397e9dc 92 0.21665898750162413,
dswood 0:c673d397e9dc 93 0.12764201806827455,
dswood 0:c673d397e9dc 94 0.0484176527692072,
dswood 0:c673d397e9dc 95 0.009246906411528302
dswood 0:c673d397e9dc 96 };
dswood 0:c673d397e9dc 97 //float PotBuf[NumberOfTaps];
dswood 0:c673d397e9dc 98 float TempBuf[NumberOfTaps];
dswood 0:c673d397e9dc 99 int CycleCount=0,StartT=0;
dswood 0:c673d397e9dc 100 bool FireTriac,Boiling,DisplayFlag;
dswood 0:c673d397e9dc 101 /*------- inputs ---------*/
dswood 0:c673d397e9dc 102 InterruptIn FallingEdge(D12);
dswood 0:c673d397e9dc 103 InterruptIn RisingEdge(D13);
dswood 0:c673d397e9dc 104 //AnalogIn Potentiometer(A0);
dswood 0:c673d397e9dc 105 // Thermistor (ntc) with a constant current flowing through it
dswood 0:c673d397e9dc 106 AnalogIn Thermistor(A1);
dswood 0:c673d397e9dc 107 //Rotary Encoder for entering values and navigation
dswood 0:c673d397e9dc 108 QEI wheel (D9, D8, NC, 20);
dswood 0:c673d397e9dc 109 DigitalIn Button(PC_9);
dswood 0:c673d397e9dc 110 InterruptIn ButtonPressed(PC_9);
dswood 0:c673d397e9dc 111 /*------- inputs -end-----*/
dswood 0:c673d397e9dc 112
dswood 0:c673d397e9dc 113 /*------- outputs ---------*/
dswood 0:c673d397e9dc 114 //DigitalOut led(LED1);
dswood 0:c673d397e9dc 115 // Output to switch on the LED in the opto to fire the triac
dswood 0:c673d397e9dc 116 DigitalOut Triac(D10),OledReset(D6);
dswood 0:c673d397e9dc 117 // Test output to see timings and states on a scope
dswood 0:c673d397e9dc 118 DigitalOut Test(D15);
dswood 0:c673d397e9dc 119 // The screen
dswood 0:c673d397e9dc 120 SSD1306 MyOled(SPI_8, 10000000, D4, D5, D3, D2, D6, D7,"MyOled", Width, Height); // Spi 8bit, 10MHz, mosi, miso, sclk, cs, reset, dc
dswood 0:c673d397e9dc 121 // fixme clock may need to be 5MHz
dswood 0:c673d397e9dc 122 // 5000000 gives a clock of 3.125MHz (genius)
dswood 0:c673d397e9dc 123 // 10000000 gives 6.25
dswood 0:c673d397e9dc 124 // 12800000 gives 12.8Mhz still works
dswood 0:c673d397e9dc 125 // 20000000 gives 12.5Mhz
dswood 0:c673d397e9dc 126 // the nearest i can find to 8MHz is 10000000
dswood 0:c673d397e9dc 127
dswood 0:c673d397e9dc 128 /*------- outputs -end-----*/
dswood 0:c673d397e9dc 129
dswood 0:c673d397e9dc 130
dswood 0:c673d397e9dc 131 char Buff[3][20];
dswood 0:c673d397e9dc 132 Timeout SyncDelay,TriacPulseTimeout,ReadTemperature;
dswood 0:c673d397e9dc 133
dswood 0:c673d397e9dc 134 //float Pot;
dswood 0:c673d397e9dc 135 int FireCount;
dswood 0:c673d397e9dc 136 int Demand;
dswood 0:c673d397e9dc 137 float valT,LastTemp=0,LastError=0,Integrated=0;
dswood 0:c673d397e9dc 138 bool Rise,MainsOn;
dswood 0:c673d397e9dc 139 time_t now;
dswood 0:c673d397e9dc 140 Timer ElapsedTime;
dswood 0:c673d397e9dc 141 uint64_t LastTime,TempTime,DebounceTime,StartTime,DemandTime,CheckTime,KnobTime,CycleTime;
dswood 0:c673d397e9dc 142 struct Controls {
dswood 0:c673d397e9dc 143 float Temperature;
dswood 0:c673d397e9dc 144 int8_t PercentPower;
dswood 0:c673d397e9dc 145 int16_t TimeSeconds;
dswood 0:c673d397e9dc 146 int8_t ProfileNumber;
dswood 0:c673d397e9dc 147 int8_t ElementNumber;
dswood 0:c673d397e9dc 148 uint8_t MessageNo;
dswood 0:c673d397e9dc 149 goal Goal;
dswood 0:c673d397e9dc 150 char Message[20];
dswood 0:c673d397e9dc 151
dswood 0:c673d397e9dc 152 };
dswood 0:c673d397e9dc 153 struct Controls MyControls= {25.0,50,0};
dswood 0:c673d397e9dc 154 struct Profile *ProfileArray[5]= { &MashProfile,&MashProfileFull,&Boil1,&Boil2,&Boil3};
dswood 0:c673d397e9dc 155 enum VariableType { Index, TempC, PwrW, TimeS };
dswood 0:c673d397e9dc 156 struct MenuType {
dswood 0:c673d397e9dc 157 int8_t IndexVal; //The current thing pointed to by the cursor
dswood 0:c673d397e9dc 158 int8_t Number;
dswood 0:c673d397e9dc 159 int8_t MaxIndex;
dswood 0:c673d397e9dc 160 int8_t Offset;
dswood 0:c673d397e9dc 161 VariableType CurrentType;
dswood 0:c673d397e9dc 162 void EncoderHandler( bool Increment, VariableType ChangeType);
dswood 0:c673d397e9dc 163 struct Controls *Cntrl; // points to the main loop controls
dswood 0:c673d397e9dc 164 char *MenuText[8]; //8 lines of menus to start with
dswood 0:c673d397e9dc 165 void (*NextMenu[8])();
dswood 0:c673d397e9dc 166 bool Switch;
dswood 0:c673d397e9dc 167 };
dswood 0:c673d397e9dc 168
dswood 0:c673d397e9dc 169 Serial Mypc(USBTX, USBRX, 115200); //for debugging
dswood 0:c673d397e9dc 170 int64_t DebugValue;
dswood 0:c673d397e9dc 171 void FiringCounter(int Power);
dswood 0:c673d397e9dc 172 void PulseTriac();
dswood 0:c673d397e9dc 173 void SyncFall();
dswood 0:c673d397e9dc 174 void SyncRise();
dswood 0:c673d397e9dc 175 //char *Menu[2]={"Manual","Programmed"};
dswood 0:c673d397e9dc 176
dswood 0:c673d397e9dc 177 int string_length(char* given_string)
dswood 0:c673d397e9dc 178 {
dswood 0:c673d397e9dc 179 // variable to store the
dswood 0:c673d397e9dc 180 // length of the string
dswood 0:c673d397e9dc 181 int length = 0;
dswood 0:c673d397e9dc 182 while (*given_string != '\0') {
dswood 0:c673d397e9dc 183 length++;
dswood 0:c673d397e9dc 184 given_string++;
dswood 0:c673d397e9dc 185 }
dswood 0:c673d397e9dc 186
dswood 0:c673d397e9dc 187 return length;
dswood 0:c673d397e9dc 188 }
dswood 0:c673d397e9dc 189 void MenuType::EncoderHandler( bool Increment, VariableType ChangeType)
dswood 0:c673d397e9dc 190 {
dswood 0:c673d397e9dc 191 int Multiplier=1,t;
dswood 0:c673d397e9dc 192 t=ElapsedTime.read_ms()-KnobTime;
dswood 0:c673d397e9dc 193 if (t<50) Multiplier=10;
dswood 0:c673d397e9dc 194 else if (t<100) Multiplier=5;
dswood 0:c673d397e9dc 195 else if (t<150) Multiplier=2;
dswood 0:c673d397e9dc 196 KnobTime=ElapsedTime.read_ms();
dswood 0:c673d397e9dc 197 switch (ChangeType) {
dswood 0:c673d397e9dc 198 case Index:
dswood 0:c673d397e9dc 199 if (Increment) IndexVal++;
dswood 0:c673d397e9dc 200 else IndexVal--;
dswood 0:c673d397e9dc 201 if (IndexVal>MaxIndex) IndexVal=0;
dswood 0:c673d397e9dc 202 if (IndexVal<0) IndexVal=MaxIndex;
dswood 0:c673d397e9dc 203 if ((IndexVal-Offset)>2) Offset=IndexVal-2;
dswood 0:c673d397e9dc 204 if ((IndexVal-Offset)<0) Offset=IndexVal;
dswood 0:c673d397e9dc 205 break;
dswood 0:c673d397e9dc 206 case TempC:
dswood 0:c673d397e9dc 207 if (Increment) Cntrl->Temperature=Cntrl->Temperature+(float)0.1*(float)Multiplier;
dswood 0:c673d397e9dc 208 else Cntrl->Temperature=Cntrl->Temperature-(float)0.1*(float)Multiplier;
dswood 0:c673d397e9dc 209 if (Cntrl->Temperature>120)Cntrl->Temperature=120;
dswood 0:c673d397e9dc 210 if (Cntrl->Temperature<25)Cntrl->Temperature=25;
dswood 0:c673d397e9dc 211 break;
dswood 0:c673d397e9dc 212 case PwrW:
dswood 0:c673d397e9dc 213 if (Increment) Cntrl->PercentPower+=Multiplier;
dswood 0:c673d397e9dc 214 else Cntrl->PercentPower-=Multiplier;
dswood 0:c673d397e9dc 215 if (Cntrl->PercentPower>100)Cntrl->PercentPower=100;
dswood 0:c673d397e9dc 216 if (Cntrl->PercentPower<=0)Cntrl->PercentPower=1;
dswood 0:c673d397e9dc 217 break;
dswood 0:c673d397e9dc 218 case TimeS:
dswood 0:c673d397e9dc 219 Multiplier=Multiplier*Multiplier;
dswood 0:c673d397e9dc 220 if (Increment) Cntrl->TimeSeconds+=Multiplier;
dswood 0:c673d397e9dc 221 else Cntrl->TimeSeconds-=Multiplier;
dswood 0:c673d397e9dc 222 if (Cntrl->TimeSeconds>10800)Cntrl->TimeSeconds=10800;
dswood 0:c673d397e9dc 223 if (Cntrl->TimeSeconds<0)Cntrl->TimeSeconds=0;
dswood 0:c673d397e9dc 224 break;
dswood 0:c673d397e9dc 225 }
dswood 0:c673d397e9dc 226 }
dswood 0:c673d397e9dc 227
dswood 0:c673d397e9dc 228 struct MenuType MainMenu;
dswood 0:c673d397e9dc 229 void SetTopLevelMenu();
dswood 0:c673d397e9dc 230 void SetProgrammedMenu();
dswood 0:c673d397e9dc 231 void SetManualMenu();
dswood 0:c673d397e9dc 232 void ShowProgramMenu();
dswood 0:c673d397e9dc 233 void StartProfileMenu();
dswood 0:c673d397e9dc 234 void DoNothing();
dswood 0:c673d397e9dc 235 void AlterDataMenu();
dswood 0:c673d397e9dc 236 void LoadProfile(int Prof,int Ele);
dswood 0:c673d397e9dc 237 void SetProfile();
dswood 0:c673d397e9dc 238 void ProfileMenu();
dswood 0:c673d397e9dc 239 void GetTemperature();
dswood 0:c673d397e9dc 240 void DisplayNow();
dswood 0:c673d397e9dc 241 void DisplayMenu();
dswood 0:c673d397e9dc 242 void SetOutputSpeed();
dswood 0:c673d397e9dc 243 void PulseTriac()
dswood 0:c673d397e9dc 244 {
dswood 0:c673d397e9dc 245 if (Triac==1) {
dswood 0:c673d397e9dc 246 Triac=0;
dswood 0:c673d397e9dc 247 Test=0; //fixme
dswood 0:c673d397e9dc 248 } else {
dswood 0:c673d397e9dc 249 Triac=1;// Fire the triac
dswood 0:c673d397e9dc 250 Test=1;
dswood 0:c673d397e9dc 251 TriacPulseTimeout.attach_us(&PulseTriac,TriacPulseLength);
dswood 0:c673d397e9dc 252 }
dswood 0:c673d397e9dc 253 }
dswood 0:c673d397e9dc 254 void MenuSetup()
dswood 0:c673d397e9dc 255 {
dswood 0:c673d397e9dc 256 MainMenu.Offset=0;
dswood 0:c673d397e9dc 257 MainMenu.IndexVal=0;
dswood 0:c673d397e9dc 258 MainMenu.Cntrl=&MyControls;
dswood 0:c673d397e9dc 259 SetTopLevelMenu();
dswood 0:c673d397e9dc 260 }
dswood 0:c673d397e9dc 261 void SyncFall()
dswood 0:c673d397e9dc 262 {
dswood 0:c673d397e9dc 263 int64_t t;
dswood 0:c673d397e9dc 264 /* After many attempts to get this right t should be a uint64_t BUT
dswood 0:c673d397e9dc 265 whan you do a comparison if(uint64_t> 99) it all goes to crap.
dswood 0:c673d397e9dc 266 I think you end up with an overflow in the math used to evaluate it.
dswood 0:c673d397e9dc 267 So only do comparicons with signed numbers int or float.
dswood 0:c673d397e9dc 268 */
dswood 0:c673d397e9dc 269 if (!Rise) return;
dswood 0:c673d397e9dc 270 Rise=false;
dswood 0:c673d397e9dc 271 t=ElapsedTime.read_us()-CycleTime;
dswood 0:c673d397e9dc 272 DebugValue=t;
dswood 0:c673d397e9dc 273 CycleTime=ElapsedTime.read_us();
dswood 0:c673d397e9dc 274 if (DisplayFlag) return;
dswood 0:c673d397e9dc 275 if ((t>20400)||(t<19600)) {
dswood 0:c673d397e9dc 276 CycleCount=0;
dswood 0:c673d397e9dc 277 MainsOn=false;
dswood 0:c673d397e9dc 278 }
dswood 0:c673d397e9dc 279 if (CycleCount<10) {
dswood 0:c673d397e9dc 280 CycleCount++;
dswood 0:c673d397e9dc 281 return;
dswood 0:c673d397e9dc 282 }
dswood 0:c673d397e9dc 283 MainsOn=true;
dswood 0:c673d397e9dc 284 if (FireTriac) SyncDelay.attach_us(&PulseTriac,SyncToZeroCrossingDelayFall);
dswood 0:c673d397e9dc 285 FiringCounter(Demand);
dswood 0:c673d397e9dc 286 ReadTemperature.attach_us(&GetTemperature,9000); //read temp if mains on synced
dswood 0:c673d397e9dc 287 // the noise generated on triac firing upsets the temperature measurment
dswood 0:c673d397e9dc 288 }
dswood 0:c673d397e9dc 289 void SyncRise()
dswood 0:c673d397e9dc 290 {
dswood 0:c673d397e9dc 291 int64_t t;
dswood 0:c673d397e9dc 292 Test=1;
dswood 0:c673d397e9dc 293 if (Rise) return;
dswood 0:c673d397e9dc 294 Rise=true;
dswood 0:c673d397e9dc 295 t=ElapsedTime.read_us()-CycleTime;
dswood 0:c673d397e9dc 296 if (DisplayFlag) return;
dswood 0:c673d397e9dc 297 if ((t>10200)||(t<9800)) {
dswood 0:c673d397e9dc 298 CycleCount=0;
dswood 0:c673d397e9dc 299 MainsOn=false;
dswood 0:c673d397e9dc 300 }
dswood 0:c673d397e9dc 301 if (CycleCount<10) {
dswood 0:c673d397e9dc 302 return;
dswood 0:c673d397e9dc 303 }
dswood 0:c673d397e9dc 304 Test=0;
dswood 0:c673d397e9dc 305 if (FireTriac) SyncDelay.attach_us(&PulseTriac,SyncToZeroCrossingDelayRise);
dswood 0:c673d397e9dc 306 }
dswood 0:c673d397e9dc 307
dswood 0:c673d397e9dc 308 float ReadResistance() // Read voltage across thermistor
dswood 0:c673d397e9dc 309 {
dswood 0:c673d397e9dc 310
dswood 0:c673d397e9dc 311 int i,j;
dswood 0:c673d397e9dc 312 float tmp=0;
dswood 0:c673d397e9dc 313 j=StartT;
dswood 0:c673d397e9dc 314 TempBuf[StartT]=Thermistor;
dswood 0:c673d397e9dc 315 for (i=0; i<NumberOfTaps; i++) {
dswood 0:c673d397e9dc 316 if (j<0) j+=NumberOfTaps;
dswood 0:c673d397e9dc 317 tmp+=TempBuf[j]*filter_taps[i];
dswood 0:c673d397e9dc 318 j--;
dswood 0:c673d397e9dc 319 if (j<0) j=NumberOfTaps-1;
dswood 0:c673d397e9dc 320 }
dswood 0:c673d397e9dc 321 StartT--;
dswood 0:c673d397e9dc 322 if (StartT<0) StartT=NumberOfTaps-1;
dswood 0:c673d397e9dc 323 /* tmp is the fraction 3.3V across thermistor.
dswood 0:c673d397e9dc 324 Resistance = V/I
dswood 0:c673d397e9dc 325 Resistance = (tmp*3.3V)/Bias_Current */
dswood 0:c673d397e9dc 326 tmp=(tmp*(float)3.3)/(float)Bias_Current; // Answer is in Kohm because current is in mA
dswood 0:c673d397e9dc 327 return tmp;
dswood 0:c673d397e9dc 328 }
dswood 0:c673d397e9dc 329 float ResistanceToTemp(float Res)
dswood 0:c673d397e9dc 330 {
dswood 0:c673d397e9dc 331 /* T0 = 25C = 298K
dswood 0:c673d397e9dc 332 beta =3977
dswood 0:c673d397e9dc 333 R0=10000 ohm */
dswood 0:c673d397e9dc 334 Res=Res+(float)0.0001; //Res can't be zero
dswood 0:c673d397e9dc 335 float temp; // temp here is both temperary and temperature
dswood 0:c673d397e9dc 336 temp=log(Res/(float)10)/(float)3977.0; //beta from datasheet
dswood 0:c673d397e9dc 337 temp=(float)1/(temp+(float)0.003354); // 1/298.15
dswood 0:c673d397e9dc 338 //temp=temp-(float)273.15 ;//kelvin to c conversion
dswood 0:c673d397e9dc 339 /* ok so the temp is miles off due to things like the sensor being pressed
dswood 0:c673d397e9dc 340 against the outside of the barrel. Loosing heat to ambient etc.
dswood 0:c673d397e9dc 341 So lets compensate for that with an offset and a scale factor. */
dswood 0:c673d397e9dc 342 temp=(temp*(float)1.09)-(float)22;
dswood 0:c673d397e9dc 343 temp=temp-(float)273.15 ;//kelvin to c conversion
dswood 0:c673d397e9dc 344 return temp;
dswood 0:c673d397e9dc 345 }
dswood 0:c673d397e9dc 346 void GetTemperature()
dswood 0:c673d397e9dc 347 {
dswood 0:c673d397e9dc 348 if (DisplayFlag) return; // The noise generated by the comms to the display causes 0.5C error
dswood 0:c673d397e9dc 349 valT=ResistanceToTemp(ReadResistance());
dswood 0:c673d397e9dc 350 }
dswood 0:c673d397e9dc 351 void Pressed()
dswood 0:c673d397e9dc 352 {
dswood 0:c673d397e9dc 353 int t;
dswood 0:c673d397e9dc 354 t=ElapsedTime.read_ms()-DebounceTime;
dswood 0:c673d397e9dc 355 DebounceTime=ElapsedTime.read_ms();
dswood 0:c673d397e9dc 356 if (t<250) return;
dswood 0:c673d397e9dc 357 //Mypc.printf("Index %d \n",MainMenu.IndexVal);
dswood 0:c673d397e9dc 358 MainMenu.Number=MainMenu.IndexVal;
dswood 0:c673d397e9dc 359 MainMenu.NextMenu[MainMenu.IndexVal]();
dswood 0:c673d397e9dc 360 }
dswood 0:c673d397e9dc 361 void setup()
dswood 0:c673d397e9dc 362 {
dswood 0:c673d397e9dc 363 set_time(1256729737); // Set RTC time to Wed, 28 Oct 2009 11:35:37
dswood 0:c673d397e9dc 364 now=time(NULL);
dswood 0:c673d397e9dc 365 // Mypc.printf("Setup");
dswood 0:c673d397e9dc 366 Triac=0; // Low to fire
dswood 0:c673d397e9dc 367 FallingEdge.fall(&SyncFall); //falling mains voltage
dswood 0:c673d397e9dc 368 RisingEdge.fall(&SyncRise); //rising mains voltage
dswood 0:c673d397e9dc 369 FireCount=0;
dswood 0:c673d397e9dc 370 ButtonPressed.fall(&Pressed);
dswood 0:c673d397e9dc 371 //SetOutputSpeed();
dswood 0:c673d397e9dc 372 MyOled.BusEnable(true);//Chip select
dswood 0:c673d397e9dc 373 MyOled.FastWindow(true);
dswood 0:c673d397e9dc 374 MyOled.set_orientation(3);
dswood 0:c673d397e9dc 375 MyOled.locate(0,0);
dswood 0:c673d397e9dc 376 MyOled.set_font((unsigned char*) Terminal6x8,32,127,false);
dswood 0:c673d397e9dc 377 MyOled.cls();
dswood 0:c673d397e9dc 378 MyOled.BusEnable(false);//Chip select
dswood 0:c673d397e9dc 379 ButtonPressed.fall(&Pressed);
dswood 0:c673d397e9dc 380 ElapsedTime.start();
dswood 0:c673d397e9dc 381 LastTime=ElapsedTime.read_ms();
dswood 0:c673d397e9dc 382 DebounceTime=LastTime;
dswood 0:c673d397e9dc 383 CycleTime=ElapsedTime.read_us();
dswood 0:c673d397e9dc 384 TempTime=LastTime;
dswood 0:c673d397e9dc 385 CheckTime=LastTime;
dswood 0:c673d397e9dc 386 DemandTime=LastTime;
dswood 0:c673d397e9dc 387 KnobTime=LastTime;
dswood 0:c673d397e9dc 388 MenuSetup();
dswood 0:c673d397e9dc 389 }
dswood 0:c673d397e9dc 390 void SetOutputSpeed()
dswood 0:c673d397e9dc 391 {
dswood 0:c673d397e9dc 392 GPIO_InitTypeDef GPIO_InitStruct;
dswood 0:c673d397e9dc 393 //Configure GPIO pin : PB_3 D3
dswood 0:c673d397e9dc 394 GPIO_InitStruct.Pin = GPIO_PIN_3;
dswood 0:c673d397e9dc 395 GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; // digital Output
dswood 0:c673d397e9dc 396 GPIO_InitStruct.Speed = GPIO_SPEED_LOW;
dswood 0:c673d397e9dc 397 HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
dswood 0:c673d397e9dc 398 }
dswood 0:c673d397e9dc 399
dswood 0:c673d397e9dc 400 void FiringCounter(int Power)
dswood 0:c673d397e9dc 401 {
dswood 0:c673d397e9dc 402 int x;
dswood 0:c673d397e9dc 403 x=Power;
dswood 0:c673d397e9dc 404 if (x>100) x=100;
dswood 0:c673d397e9dc 405 if (x<0) x=0;
dswood 0:c673d397e9dc 406 if (FireCount<0) {
dswood 0:c673d397e9dc 407 FireCount+=100-x;
dswood 0:c673d397e9dc 408 FireTriac=true;
dswood 0:c673d397e9dc 409 } else {
dswood 0:c673d397e9dc 410 FireCount-=x;
dswood 0:c673d397e9dc 411 FireTriac=false;
dswood 0:c673d397e9dc 412 }
dswood 0:c673d397e9dc 413
dswood 0:c673d397e9dc 414 }
dswood 0:c673d397e9dc 415 void SetTopLevelMenu()
dswood 0:c673d397e9dc 416 {
dswood 0:c673d397e9dc 417
dswood 0:c673d397e9dc 418 MainMenu.IndexVal=0;
dswood 0:c673d397e9dc 419 MainMenu.MaxIndex=2;
dswood 0:c673d397e9dc 420 MainMenu.Offset=0;
dswood 0:c673d397e9dc 421 MainMenu.MenuText[0]=TopLevelMenu[0];
dswood 0:c673d397e9dc 422 MainMenu.MenuText[1]=TopLevelMenu[1];
dswood 0:c673d397e9dc 423 MainMenu.MenuText[2]=TopLevelMenu[2];
dswood 0:c673d397e9dc 424 MainMenu.CurrentType=Index;
dswood 0:c673d397e9dc 425 MainMenu.NextMenu[0]=&SetTopLevelMenu;
dswood 0:c673d397e9dc 426 MainMenu.NextMenu[1]=&SetManualMenu;
dswood 0:c673d397e9dc 427 MainMenu.NextMenu[2]=&SetProgrammedMenu;
dswood 0:c673d397e9dc 428 MainMenu.NextMenu[3]=&SetTopLevelMenu;//Set it to something that is valid
dswood 0:c673d397e9dc 429 MainMenu.NextMenu[4]=&SetTopLevelMenu;
dswood 0:c673d397e9dc 430 MainMenu.NextMenu[5]=&SetTopLevelMenu;
dswood 0:c673d397e9dc 431 MyControls.Temperature= 25.0;
dswood 0:c673d397e9dc 432 MyControls.PercentPower=1;
dswood 0:c673d397e9dc 433 MyControls.TimeSeconds=0;
dswood 0:c673d397e9dc 434 MainMenu.Switch=true;
dswood 0:c673d397e9dc 435 }
dswood 0:c673d397e9dc 436 void SetProgrammedMenu()
dswood 0:c673d397e9dc 437 {
dswood 0:c673d397e9dc 438 MainMenu.Offset=0;
dswood 0:c673d397e9dc 439 MainMenu.IndexVal=0;
dswood 0:c673d397e9dc 440 MainMenu.MaxIndex=5;//12345678901234567890
dswood 0:c673d397e9dc 441 MainMenu.MenuText[0]="Previous Menu ";
dswood 0:c673d397e9dc 442 MainMenu.MenuText[1]=MashProfile.Name;
dswood 0:c673d397e9dc 443 MainMenu.MenuText[2]=MashProfileFull.Name;
dswood 0:c673d397e9dc 444 MainMenu.MenuText[3]=Boil1.Name;
dswood 0:c673d397e9dc 445 MainMenu.MenuText[4]=Boil2.Name;
dswood 0:c673d397e9dc 446 MainMenu.MenuText[5]=Boil3.Name;
dswood 0:c673d397e9dc 447
dswood 0:c673d397e9dc 448 MainMenu.NextMenu[0]=&SetTopLevelMenu;
dswood 0:c673d397e9dc 449 MainMenu.NextMenu[1]=&SetProfile;
dswood 0:c673d397e9dc 450 MainMenu.NextMenu[2]=&SetProfile;
dswood 0:c673d397e9dc 451 MainMenu.NextMenu[3]=&SetProfile;
dswood 0:c673d397e9dc 452 MainMenu.NextMenu[4]=&SetProfile;
dswood 0:c673d397e9dc 453 MainMenu.NextMenu[5]=&SetProfile;
dswood 0:c673d397e9dc 454
dswood 0:c673d397e9dc 455 MainMenu.CurrentType=Index;
dswood 0:c673d397e9dc 456 MainMenu.Switch=true;
dswood 0:c673d397e9dc 457 }
dswood 0:c673d397e9dc 458 void SetManualMenu()
dswood 0:c673d397e9dc 459 {
dswood 0:c673d397e9dc 460 MainMenu.IndexVal=0;
dswood 0:c673d397e9dc 461 MainMenu.MaxIndex=3;
dswood 0:c673d397e9dc 462 MainMenu.Offset=0; // 1234567890123456789
dswood 0:c673d397e9dc 463 MainMenu.MenuText[0]="Manual Menu ";
dswood 0:c673d397e9dc 464 MainMenu.MenuText[1]="Temperature";
dswood 0:c673d397e9dc 465 MainMenu.MenuText[2]="Power Level";
dswood 0:c673d397e9dc 466 MainMenu.MenuText[3]="Time ";
dswood 0:c673d397e9dc 467 MainMenu.NextMenu[0]=&SetTopLevelMenu;
dswood 0:c673d397e9dc 468 MainMenu.NextMenu[1]=&AlterDataMenu;
dswood 0:c673d397e9dc 469 MainMenu.NextMenu[2]=&AlterDataMenu;
dswood 0:c673d397e9dc 470 MainMenu.NextMenu[3]=&AlterDataMenu;
dswood 0:c673d397e9dc 471 MainMenu.NextMenu[4]=&DoNothing;
dswood 0:c673d397e9dc 472 MainMenu.Switch=false;
dswood 0:c673d397e9dc 473 }
dswood 0:c673d397e9dc 474 void ShowProgramMenu()
dswood 0:c673d397e9dc 475 {
dswood 0:c673d397e9dc 476 MainMenu.Offset=0;
dswood 0:c673d397e9dc 477 MainMenu.IndexVal=0;
dswood 0:c673d397e9dc 478 MainMenu.MaxIndex=2;
dswood 0:c673d397e9dc 479 MainMenu.MenuText[0]="Previous Menu ";
dswood 0:c673d397e9dc 480 MainMenu.MenuText[1]=ProfileArray[MyControls.ProfileNumber]->Name;
dswood 0:c673d397e9dc 481 MainMenu.MenuText[2]="Start ";
dswood 0:c673d397e9dc 482
dswood 0:c673d397e9dc 483 if (MyControls.Goal==Null) {
dswood 0:c673d397e9dc 484 MainMenu.MenuText[3]="";
dswood 0:c673d397e9dc 485 MainMenu.NextMenu[3]=&SetProgrammedMenu;
dswood 0:c673d397e9dc 486 } else {//profile loaded
dswood 0:c673d397e9dc 487 MainMenu.MenuText[3]="Current Profile ";
dswood 0:c673d397e9dc 488 // 1234567890123456789
dswood 0:c673d397e9dc 489 MainMenu.NextMenu[3]=&ProfileMenu;
dswood 0:c673d397e9dc 490 MainMenu.MaxIndex=3;
dswood 0:c673d397e9dc 491 }
dswood 0:c673d397e9dc 492 MainMenu.MenuText[4]="";
dswood 0:c673d397e9dc 493 MainMenu.MenuText[5]="";
dswood 0:c673d397e9dc 494 MainMenu.NextMenu[0]=&SetProgrammedMenu;
dswood 0:c673d397e9dc 495 MainMenu.NextMenu[1]=&DoNothing;
dswood 0:c673d397e9dc 496 MainMenu.NextMenu[2]=&StartProfileMenu;
dswood 0:c673d397e9dc 497
dswood 0:c673d397e9dc 498 MainMenu.NextMenu[4]=&SetProgrammedMenu;
dswood 0:c673d397e9dc 499 MainMenu.NextMenu[5]=&SetProgrammedMenu;
dswood 0:c673d397e9dc 500 MainMenu.CurrentType=Index;
dswood 0:c673d397e9dc 501 MainMenu.Switch=true;
dswood 0:c673d397e9dc 502
dswood 0:c673d397e9dc 503 }
dswood 0:c673d397e9dc 504 void StartProfileMenu()
dswood 0:c673d397e9dc 505 {
dswood 0:c673d397e9dc 506 LoadProfile(MyControls.ProfileNumber,0); //load the first element of the selected profile
dswood 0:c673d397e9dc 507 ProfileMenu();
dswood 0:c673d397e9dc 508 }
dswood 0:c673d397e9dc 509 void ProfileMenu()
dswood 0:c673d397e9dc 510 {
dswood 0:c673d397e9dc 511 MainMenu.IndexVal=0;
dswood 0:c673d397e9dc 512 MainMenu.MaxIndex=3;
dswood 0:c673d397e9dc 513 MainMenu.Offset=0; //
dswood 0:c673d397e9dc 514 MainMenu.MenuText[0]=MyControls.Message;
dswood 0:c673d397e9dc 515 MainMenu.MenuText[1]="Temperature";
dswood 0:c673d397e9dc 516 MainMenu.MenuText[2]="Power Level";
dswood 0:c673d397e9dc 517 MainMenu.MenuText[3]="Time ";
dswood 0:c673d397e9dc 518 MainMenu.NextMenu[0]=&ShowProgramMenu;
dswood 0:c673d397e9dc 519 MainMenu.NextMenu[1]=&AlterDataMenu;
dswood 0:c673d397e9dc 520 MainMenu.NextMenu[2]=&AlterDataMenu;
dswood 0:c673d397e9dc 521 MainMenu.NextMenu[3]=&AlterDataMenu;
dswood 0:c673d397e9dc 522 MainMenu.NextMenu[4]=&DoNothing;
dswood 0:c673d397e9dc 523 MainMenu.Switch=false;
dswood 0:c673d397e9dc 524 }
dswood 0:c673d397e9dc 525 void AlterDataMenu()
dswood 0:c673d397e9dc 526 {
dswood 0:c673d397e9dc 527 if (MainMenu.CurrentType==Index) switch (MainMenu.IndexVal) {
dswood 0:c673d397e9dc 528 case 1:
dswood 0:c673d397e9dc 529 MainMenu.CurrentType=TempC;
dswood 0:c673d397e9dc 530 break;
dswood 0:c673d397e9dc 531 case 2:
dswood 0:c673d397e9dc 532 MainMenu.CurrentType=PwrW;
dswood 0:c673d397e9dc 533 break;
dswood 0:c673d397e9dc 534 case 3:
dswood 0:c673d397e9dc 535 MainMenu.CurrentType=TimeS;
dswood 0:c673d397e9dc 536 break;
dswood 0:c673d397e9dc 537 default:
dswood 0:c673d397e9dc 538 MainMenu.CurrentType=Index;
dswood 0:c673d397e9dc 539 } else MainMenu.CurrentType=Index;
dswood 0:c673d397e9dc 540 }
dswood 0:c673d397e9dc 541 void DoNothing() //The purpose of this function is assign a function pointer to it rather than something wrong or a crash
dswood 0:c673d397e9dc 542 {
dswood 0:c673d397e9dc 543 }
dswood 0:c673d397e9dc 544 void SetProfile()
dswood 0:c673d397e9dc 545 {
dswood 0:c673d397e9dc 546 int i=MainMenu.Number-1;
dswood 0:c673d397e9dc 547 if (i<0)i=0;
dswood 0:c673d397e9dc 548 if (i>4)i=4;//sanitize
dswood 0:c673d397e9dc 549 MyControls.ProfileNumber=i;
dswood 0:c673d397e9dc 550 strncpy(MyControls.Message,ProfileArray[i]->Name,20);
dswood 0:c673d397e9dc 551 MyControls.Goal=Null;
dswood 0:c673d397e9dc 552 ShowProgramMenu();
dswood 0:c673d397e9dc 553
dswood 0:c673d397e9dc 554
dswood 0:c673d397e9dc 555 }
dswood 0:c673d397e9dc 556 void LoadProfile(int Prof,int Ele)
dswood 0:c673d397e9dc 557 {
dswood 0:c673d397e9dc 558 MyControls.Temperature= ProfileArray[Prof]->Element[Ele].Temp;
dswood 0:c673d397e9dc 559 MyControls.PercentPower=ProfileArray[Prof]->Element[Ele].Power;
dswood 0:c673d397e9dc 560 MyControls.TimeSeconds=ProfileArray[Prof]->Element[Ele].Seconds;
dswood 0:c673d397e9dc 561 MyControls.Goal=ProfileArray[Prof]->Element[Ele].GoalType;
dswood 0:c673d397e9dc 562 MyControls.ProfileNumber=Prof;
dswood 0:c673d397e9dc 563 MyControls.ElementNumber=Ele;
dswood 0:c673d397e9dc 564 MyControls.MessageNo=ProfileArray[Prof]->Element[Ele].MessageNo;
dswood 0:c673d397e9dc 565 StartTime=ElapsedTime.read();
dswood 0:c673d397e9dc 566 /*Mypc.printf("T %.1f P %d Sec %d Prof %d Ele %d\n",
dswood 0:c673d397e9dc 567 MyControls.Temperature,
dswood 0:c673d397e9dc 568 MyControls.PercentPower,
dswood 0:c673d397e9dc 569 MyControls.TimeSeconds,
dswood 0:c673d397e9dc 570 MyControls.ProfileNumber,
dswood 0:c673d397e9dc 571 MyControls.ElementNumber);
dswood 0:c673d397e9dc 572 */
dswood 0:c673d397e9dc 573 }
dswood 0:c673d397e9dc 574
dswood 0:c673d397e9dc 575 void DisplayMenu()
dswood 0:c673d397e9dc 576 {
dswood 0:c673d397e9dc 577 DisplayFlag=true; //This flag is used to stop generating new interupts
dswood 0:c673d397e9dc 578 wait_us(SyncToZeroCrossingDelayRise+TriacPulseLength+25); //wait for interupts to finish
dswood 0:c673d397e9dc 579 MyOled.BusEnable(true);//Chip select
dswood 0:c673d397e9dc 580 bool Highlight=false;
dswood 0:c673d397e9dc 581 //We have a 32 pixecl height and 9 pixcel font. 3 lines 10 spacing
dswood 0:c673d397e9dc 582 if (MainMenu.Switch) {
dswood 0:c673d397e9dc 583 for (int i=0; i<3 ; i++) {
dswood 0:c673d397e9dc 584 MyOled.locate(6,(i*10)+1);
dswood 0:c673d397e9dc 585 if (MainMenu.IndexVal==(i+MainMenu.Offset)) {
dswood 0:c673d397e9dc 586 MyOled.background(White);
dswood 0:c673d397e9dc 587 MyOled.foreground(Black);
dswood 0:c673d397e9dc 588 } else {
dswood 0:c673d397e9dc 589 MyOled.background(Black);
dswood 0:c673d397e9dc 590 MyOled.foreground(White);
dswood 0:c673d397e9dc 591 }
dswood 0:c673d397e9dc 592 MyOled.printf(MainMenu.MenuText[i+MainMenu.Offset]);
dswood 0:c673d397e9dc 593 MyOled.background(Black);
dswood 0:c673d397e9dc 594 MyOled.foreground(White);
dswood 0:c673d397e9dc 595 }
dswood 0:c673d397e9dc 596 } else {
dswood 0:c673d397e9dc 597 time_t t;
dswood 0:c673d397e9dc 598 if (MainMenu.CurrentType==TempC)sprintf(Buff[0]," %6.1f ",MyControls.Temperature);
dswood 0:c673d397e9dc 599 else sprintf(Buff[0]," %6.1f ",valT);
dswood 0:c673d397e9dc 600 if (MainMenu.CurrentType==PwrW)sprintf(Buff[1]," %5d%c ",MyControls.PercentPower,38);
dswood 0:c673d397e9dc 601 else sprintf(Buff[1]," %5d%c ",Demand,38);
dswood 0:c673d397e9dc 602 if (MainMenu.CurrentType==TimeS) {
dswood 0:c673d397e9dc 603 t=MyControls.TimeSeconds;
dswood 0:c673d397e9dc 604 strftime(Buff[2],10,"%T ",localtime(&t));
dswood 0:c673d397e9dc 605 } else {
dswood 0:c673d397e9dc 606 t=(int)ElapsedTime.read()-StartTime;
dswood 0:c673d397e9dc 607 strftime(Buff[2],10,"%T ",localtime(&t));
dswood 0:c673d397e9dc 608 }
dswood 0:c673d397e9dc 609 for (int i=0; i<3 ; i++) {
dswood 0:c673d397e9dc 610 MyOled.locate(6,(i*10)+1);
dswood 0:c673d397e9dc 611 if (MainMenu.IndexVal==(i+MainMenu.Offset)) {
dswood 0:c673d397e9dc 612 Highlight=true;
dswood 0:c673d397e9dc 613 } else {
dswood 0:c673d397e9dc 614 Highlight=false;
dswood 0:c673d397e9dc 615 }
dswood 0:c673d397e9dc 616 if (Highlight&&MainMenu.CurrentType==Index) {
dswood 0:c673d397e9dc 617 MyOled.background(White);
dswood 0:c673d397e9dc 618 MyOled.foreground(Black);
dswood 0:c673d397e9dc 619 MyOled.printf(MainMenu.MenuText[i+MainMenu.Offset]);
dswood 0:c673d397e9dc 620 } else {
dswood 0:c673d397e9dc 621 MyOled.background(Black);
dswood 0:c673d397e9dc 622 MyOled.foreground(White);
dswood 0:c673d397e9dc 623 MyOled.printf(MainMenu.MenuText[i+MainMenu.Offset]);
dswood 0:c673d397e9dc 624 }
dswood 0:c673d397e9dc 625 if (Highlight&&MainMenu.CurrentType!=Index) {
dswood 0:c673d397e9dc 626 MyOled.background(White);
dswood 0:c673d397e9dc 627 MyOled.foreground(Black);
dswood 0:c673d397e9dc 628 if ((i+MainMenu.Offset>=1)&&(i+MainMenu.Offset<=3))MyOled.printf(Buff[i+MainMenu.Offset-1]);
dswood 0:c673d397e9dc 629 } else {
dswood 0:c673d397e9dc 630 MyOled.background(Black);
dswood 0:c673d397e9dc 631 MyOled.foreground(White);
dswood 0:c673d397e9dc 632 if ((i+MainMenu.Offset>=1)&&(i+MainMenu.Offset<=3))MyOled.printf(Buff[i+MainMenu.Offset-1]);
dswood 0:c673d397e9dc 633 }
dswood 0:c673d397e9dc 634 }
dswood 0:c673d397e9dc 635 }
dswood 0:c673d397e9dc 636 MyOled.BusEnable(false);//Chip select
dswood 0:c673d397e9dc 637 DisplayFlag=false;
dswood 0:c673d397e9dc 638 }
dswood 0:c673d397e9dc 639 int CalcDemand() //return percent power
dswood 0:c673d397e9dc 640 {
dswood 0:c673d397e9dc 641 float ErrorSignal, Differential;
dswood 0:c673d397e9dc 642 int power;
dswood 0:c673d397e9dc 643 ErrorSignal=MyControls.Temperature-valT;
dswood 0:c673d397e9dc 644 if (abs(ErrorSignal)<1)Integrated+=ErrorSignal;
dswood 0:c673d397e9dc 645 else Integrated=0;
dswood 0:c673d397e9dc 646 if (Integrated>20)Integrated=(float)20;
dswood 0:c673d397e9dc 647 if (Integrated<-1)Integrated=(float)-1;
dswood 0:c673d397e9dc 648 Differential=ErrorSignal-LastError;
dswood 0:c673d397e9dc 649 LastError=ErrorSignal;
dswood 0:c673d397e9dc 650 power=(int)(((float)70*ErrorSignal)+((float)0.6*Integrated)+(45*Differential));
dswood 0:c673d397e9dc 651 // Mypc.printf("Error %.2f Int %.2f Dif %.2f\n\r", ErrorSignal,Integrated,Differential);
dswood 0:c673d397e9dc 652 MainsOn ? Mypc.printf("Mains On\n\r") : Mypc.printf("Mains Off\n\r");
dswood 0:c673d397e9dc 653 Mypc.printf("DebugValue %d\n\r",DebugValue);
dswood 0:c673d397e9dc 654 Mypc.printf("Elapsed time %d\n\r",ElapsedTime.read_us());
dswood 0:c673d397e9dc 655
dswood 0:c673d397e9dc 656 if (power<0)power=0;
dswood 0:c673d397e9dc 657 if (power>MyControls.PercentPower)power=MyControls.PercentPower;
dswood 0:c673d397e9dc 658 return power;
dswood 0:c673d397e9dc 659 }
dswood 0:c673d397e9dc 660 void DisplayMessage()
dswood 0:c673d397e9dc 661 {
dswood 0:c673d397e9dc 662 int x,y,z;
dswood 0:c673d397e9dc 663 z=MyControls.MessageNo; //convert to int before compare
dswood 0:c673d397e9dc 664 if (z>7)MyControls.MessageNo=0;
dswood 0:c673d397e9dc 665 if (z==0) {
dswood 0:c673d397e9dc 666 strncpy(MyControls.Message,ProfileArray[MyControls.ProfileNumber]->Name,20);
dswood 0:c673d397e9dc 667 } else {
dswood 0:c673d397e9dc 668 y=string_length(Message[MyControls.MessageNo]) ;
dswood 0:c673d397e9dc 669 for (x=0; x<18; x++) {
dswood 0:c673d397e9dc 670 if (x<y)MainMenu.MenuText[0][x]=Message[MyControls.MessageNo][x];
dswood 0:c673d397e9dc 671 else MainMenu.MenuText[0][x]=' ';
dswood 0:c673d397e9dc 672 }
dswood 0:c673d397e9dc 673 MainMenu.MenuText[0][19]='\0';
dswood 0:c673d397e9dc 674 }
dswood 0:c673d397e9dc 675 }
dswood 0:c673d397e9dc 676 int main()
dswood 0:c673d397e9dc 677 {
dswood 0:c673d397e9dc 678 Mypc.printf("Starting Main\n\r");
dswood 0:c673d397e9dc 679 setup();
dswood 0:c673d397e9dc 680 int Position=wheel.getPulses();
dswood 0:c673d397e9dc 681 int UpdateTime=750;
dswood 0:c673d397e9dc 682 uint64_t TempTime=0;
dswood 0:c673d397e9dc 683 int64_t t;// time is uint64_t but int64_t used for comparison in if statement
dswood 0:c673d397e9dc 684 while (true) { //main loop
dswood 0:c673d397e9dc 685 if (Position!=wheel.getPulses()) {
dswood 0:c673d397e9dc 686 MainMenu.EncoderHandler( Position<wheel.getPulses(), MainMenu.CurrentType);
dswood 0:c673d397e9dc 687 Position=wheel.getPulses();
dswood 0:c673d397e9dc 688 UpdateTime=250; //Quick display refresh when knob moved
dswood 0:c673d397e9dc 689 //Mypc.printf("Pos %d \n",Position);
dswood 0:c673d397e9dc 690 //DisplayMenu();
dswood 0:c673d397e9dc 691 }
dswood 0:c673d397e9dc 692 /*Had a problem where mains detection was dropping out here.
dswood 0:c673d397e9dc 693 The sum ElapsedTime.read_ms()-CycleTime was sometimes =0.
dswood 0:c673d397e9dc 694 But 0>75 is true. eg if ((ElapsedTime.read_ms()-CycleTime)>75) would be true
dswood 0:c673d397e9dc 695 if the sum result was 0. Doing the sum first was ok. Had the same problem with Debounce.
dswood 0:c673d397e9dc 696 */
dswood 0:c673d397e9dc 697 t=ElapsedTime.read_us()-CycleTime;
dswood 0:c673d397e9dc 698 if (t>75000) { //mains not proven. Read temp. When mains is on this is done synced to mains
dswood 0:c673d397e9dc 699 CycleCount=0;
dswood 0:c673d397e9dc 700 MainsOn=false;
dswood 0:c673d397e9dc 701 GetTemperature();
dswood 0:c673d397e9dc 702 }
dswood 0:c673d397e9dc 703 t=ElapsedTime.read_ms()-LastTime;
dswood 0:c673d397e9dc 704 if (t>UpdateTime) {
dswood 0:c673d397e9dc 705 LastTime=ElapsedTime.read_ms();
dswood 0:c673d397e9dc 706 UpdateTime=750;
dswood 0:c673d397e9dc 707 DisplayMenu();
dswood 0:c673d397e9dc 708 }
dswood 0:c673d397e9dc 709 t=ElapsedTime.read_ms()-TempTime;
dswood 0:c673d397e9dc 710 if (t>15000) { //upped to 15s which will give a smaller temp rise by averaging over a longer period
dswood 0:c673d397e9dc 711 if (valT>99.0f) {
dswood 0:c673d397e9dc 712 if (valT-LastTemp<0.15f)Boiling=true;
dswood 0:c673d397e9dc 713 else Boiling=false; // still rising
dswood 0:c673d397e9dc 714 } else Boiling=false; //too cold
dswood 0:c673d397e9dc 715 LastTemp=valT;
dswood 0:c673d397e9dc 716 TempTime=ElapsedTime.read_ms();
dswood 0:c673d397e9dc 717 }
dswood 0:c673d397e9dc 718 t=ElapsedTime.read_ms()-DemandTime;
dswood 0:c673d397e9dc 719 if (t>3000) {
dswood 0:c673d397e9dc 720 Demand=CalcDemand();
dswood 0:c673d397e9dc 721 DemandTime=ElapsedTime.read_ms();
dswood 0:c673d397e9dc 722 }
dswood 0:c673d397e9dc 723 t=ElapsedTime.read_ms()-CheckTime;
dswood 0:c673d397e9dc 724 if (t>3000) {
dswood 0:c673d397e9dc 725 CheckTime=ElapsedTime.read_ms();
dswood 0:c673d397e9dc 726 switch (MyControls.Goal) {
dswood 0:c673d397e9dc 727 //enum goal { Null,Boil, Temp, Time};
dswood 0:c673d397e9dc 728 case Boil:
dswood 0:c673d397e9dc 729 if (Boiling ) {
dswood 0:c673d397e9dc 730 DisplayMessage();
dswood 0:c673d397e9dc 731 if (MyControls.ElementNumber<5) {
dswood 0:c673d397e9dc 732 MyControls.ElementNumber++;
dswood 0:c673d397e9dc 733 LoadProfile(MyControls.ProfileNumber,MyControls.ElementNumber);
dswood 0:c673d397e9dc 734 } else {
dswood 0:c673d397e9dc 735 MyControls.Temperature=25.0;
dswood 0:c673d397e9dc 736 MyControls.PercentPower=0;
dswood 0:c673d397e9dc 737 MyControls.TimeSeconds=0;
dswood 0:c673d397e9dc 738 }
dswood 0:c673d397e9dc 739 }
dswood 0:c673d397e9dc 740 break;
dswood 0:c673d397e9dc 741 case Temp:
dswood 0:c673d397e9dc 742 if (abs(valT-MyControls.Temperature)<(float)0.25) {
dswood 0:c673d397e9dc 743 DisplayMessage();
dswood 0:c673d397e9dc 744 if (MyControls.ElementNumber<5) {
dswood 0:c673d397e9dc 745 MyControls.ElementNumber++;
dswood 0:c673d397e9dc 746 LoadProfile(MyControls.ProfileNumber,MyControls.ElementNumber);
dswood 0:c673d397e9dc 747 } else {
dswood 0:c673d397e9dc 748 MyControls.Temperature=25.0;
dswood 0:c673d397e9dc 749 MyControls.PercentPower=0;
dswood 0:c673d397e9dc 750 MyControls.TimeSeconds=0;
dswood 0:c673d397e9dc 751 }
dswood 0:c673d397e9dc 752 }
dswood 0:c673d397e9dc 753 break;
dswood 0:c673d397e9dc 754 case Time:
dswood 0:c673d397e9dc 755 t=ElapsedTime.read()-StartTime;
dswood 0:c673d397e9dc 756 if (t>MyControls.TimeSeconds) {
dswood 0:c673d397e9dc 757 DisplayMessage();
dswood 0:c673d397e9dc 758 if(MyControls.ElementNumber<5) {
dswood 0:c673d397e9dc 759 MyControls.ElementNumber++;
dswood 0:c673d397e9dc 760 LoadProfile(MyControls.ProfileNumber,MyControls.ElementNumber);
dswood 0:c673d397e9dc 761 } else {
dswood 0:c673d397e9dc 762 MyControls.Temperature=25.0;
dswood 0:c673d397e9dc 763 MyControls.PercentPower=0;
dswood 0:c673d397e9dc 764 MyControls.TimeSeconds=0;
dswood 0:c673d397e9dc 765 }
dswood 0:c673d397e9dc 766 }
dswood 0:c673d397e9dc 767 break;
dswood 0:c673d397e9dc 768 }
dswood 0:c673d397e9dc 769 }//goal test
dswood 0:c673d397e9dc 770 }
dswood 0:c673d397e9dc 771 }