Marc Bax
/
PoopCooker_070
Firmware for sample prep heater device
main.cpp@0:06f27dbfa599, 2011-09-04 (annotated)
- Committer:
- marcbax
- Date:
- Sun Sep 04 18:35:09 2011 +0000
- Revision:
- 0:06f27dbfa599
Version 0.70
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
marcbax | 0:06f27dbfa599 | 1 | //Firmware for P173_PoopCooker sample preparation heater block |
marcbax | 0:06f27dbfa599 | 2 | |
marcbax | 0:06f27dbfa599 | 3 | #include "mbed.h" |
marcbax | 0:06f27dbfa599 | 4 | char* fwversion="0.70"; //this version published 5/9/2011 |
marcbax | 0:06f27dbfa599 | 5 | |
marcbax | 0:06f27dbfa599 | 6 | //Pin and object assignments |
marcbax | 0:06f27dbfa599 | 7 | DigitalOut led1(LED1), led2(LED2), led3(LED3), led4(LED4); |
marcbax | 0:06f27dbfa599 | 8 | DigitalOut buzzer(p30); |
marcbax | 0:06f27dbfa599 | 9 | AnalogIn ntc(p19); |
marcbax | 0:06f27dbfa599 | 10 | DigitalOut heater(p18); |
marcbax | 0:06f27dbfa599 | 11 | Serial display(p13, p14); |
marcbax | 0:06f27dbfa599 | 12 | InterruptIn keyup(p7), keyright(p5), keydown(p6); |
marcbax | 0:06f27dbfa599 | 13 | InterruptIn keyleft(p9), keyOK(p8); |
marcbax | 0:06f27dbfa599 | 14 | DigitalOut fan(p24); |
marcbax | 0:06f27dbfa599 | 15 | PwmOut rled(p21), gled(p22), bled(p23); |
marcbax | 0:06f27dbfa599 | 16 | Timer kitchentimer; |
marcbax | 0:06f27dbfa599 | 17 | Timeout kitchenalarm; |
marcbax | 0:06f27dbfa599 | 18 | Timeout heateroff; |
marcbax | 0:06f27dbfa599 | 19 | Ticker showtime; |
marcbax | 0:06f27dbfa599 | 20 | Ticker heatercontrol; |
marcbax | 0:06f27dbfa599 | 21 | |
marcbax | 0:06f27dbfa599 | 22 | // Global constants definitions |
marcbax | 0:06f27dbfa599 | 23 | |
marcbax | 0:06f27dbfa599 | 24 | float heaterperiod = 5; //cycle time for heater control |
marcbax | 0:06f27dbfa599 | 25 | float propterm = 0.1; //proportional term in PID algorithm |
marcbax | 0:06f27dbfa599 | 26 | float intterm = 0.001; //integral term in PID algorithm |
marcbax | 0:06f27dbfa599 | 27 | float difterm = 0; //differential term in PID algorithm |
marcbax | 0:06f27dbfa599 | 28 | |
marcbax | 0:06f27dbfa599 | 29 | float ntcB = 3988; //beta value for exponential NTC calculation |
marcbax | 0:06f27dbfa599 | 30 | float ntcR25 = 10000; //resistance value of NTC at 25 degC |
marcbax | 0:06f27dbfa599 | 31 | float rdivntc = 3300; //resistance value of upper ladder resistor for NTC |
marcbax | 0:06f27dbfa599 | 32 | |
marcbax | 0:06f27dbfa599 | 33 | float maxblocktemp = 115; //block temperature cutout |
marcbax | 0:06f27dbfa599 | 34 | float minblocktemp = 25; //25 degC minimal setpoint temp |
marcbax | 0:06f27dbfa599 | 35 | float defaultblocktemp = 60; //this needs to be changed to the standard extraction temperature |
marcbax | 0:06f27dbfa599 | 36 | int maxcountdown = 6540; //99 minutes max countdown |
marcbax | 0:06f27dbfa599 | 37 | int defaultcountdown = 600; //10 minutes default countdown |
marcbax | 0:06f27dbfa599 | 38 | |
marcbax | 0:06f27dbfa599 | 39 | // Global variable definitions |
marcbax | 0:06f27dbfa599 | 40 | |
marcbax | 0:06f27dbfa599 | 41 | float btemp; //current hot block temperature in degC |
marcbax | 0:06f27dbfa599 | 42 | float blocksettemp; //hot block setpoint temperature |
marcbax | 0:06f27dbfa599 | 43 | float acterror, interror, diferror; //error terms for the PID algorithm |
marcbax | 0:06f27dbfa599 | 44 | float ntcA; //calculated from ntcB and ntcR25 |
marcbax | 0:06f27dbfa599 | 45 | int countdownset; //kitchen timer setting in seconds |
marcbax | 0:06f27dbfa599 | 46 | int remainingtime; //kitchen timer current remaining time |
marcbax | 0:06f27dbfa599 | 47 | char ntcerror; //0 = no error, 1 = open circuit, 2 = short circuit |
marcbax | 0:06f27dbfa599 | 48 | float LedRGB[3] = {0, 0, 0}; // PWM dutycycle red, green, blue |
marcbax | 0:06f27dbfa599 | 49 | bool kitchentimerset; // true if kitchen countdown timer is set |
marcbax | 0:06f27dbfa599 | 50 | char lastkeypressed; // 1=up, 2=right, 3=down, 4=left, 5=OK |
marcbax | 0:06f27dbfa599 | 51 | bool beepsdone; |
marcbax | 0:06f27dbfa599 | 52 | |
marcbax | 0:06f27dbfa599 | 53 | |
marcbax | 0:06f27dbfa599 | 54 | // Function definitions |
marcbax | 0:06f27dbfa599 | 55 | |
marcbax | 0:06f27dbfa599 | 56 | // Clears and homes the display |
marcbax | 0:06f27dbfa599 | 57 | void cleardisplay() { |
marcbax | 0:06f27dbfa599 | 58 | display.printf("\e[2J\e[H"); |
marcbax | 0:06f27dbfa599 | 59 | } |
marcbax | 0:06f27dbfa599 | 60 | |
marcbax | 0:06f27dbfa599 | 61 | // Short beep |
marcbax | 0:06f27dbfa599 | 62 | void beeponce() { |
marcbax | 0:06f27dbfa599 | 63 | buzzer = 1; |
marcbax | 0:06f27dbfa599 | 64 | wait(0.1); |
marcbax | 0:06f27dbfa599 | 65 | buzzer = 0; |
marcbax | 0:06f27dbfa599 | 66 | } |
marcbax | 0:06f27dbfa599 | 67 | |
marcbax | 0:06f27dbfa599 | 68 | // beep beep beep |
marcbax | 0:06f27dbfa599 | 69 | void multibeeps(int number, float interval) { |
marcbax | 0:06f27dbfa599 | 70 | for(int i=0;i<number;i++){ |
marcbax | 0:06f27dbfa599 | 71 | beeponce(); |
marcbax | 0:06f27dbfa599 | 72 | wait(interval); |
marcbax | 0:06f27dbfa599 | 73 | } |
marcbax | 0:06f27dbfa599 | 74 | } |
marcbax | 0:06f27dbfa599 | 75 | |
marcbax | 0:06f27dbfa599 | 76 | // Device power up routine |
marcbax | 0:06f27dbfa599 | 77 | void initdevice() { |
marcbax | 0:06f27dbfa599 | 78 | |
marcbax | 0:06f27dbfa599 | 79 | //set all outputs to "off" |
marcbax | 0:06f27dbfa599 | 80 | led1=led2=led3=led4=0; |
marcbax | 0:06f27dbfa599 | 81 | buzzer=0; |
marcbax | 0:06f27dbfa599 | 82 | heater=0; |
marcbax | 0:06f27dbfa599 | 83 | fan=0; |
marcbax | 0:06f27dbfa599 | 84 | bled=0; |
marcbax | 0:06f27dbfa599 | 85 | rled=0; |
marcbax | 0:06f27dbfa599 | 86 | gled=0; |
marcbax | 0:06f27dbfa599 | 87 | rled.period_us(100); //PWM frequency set to 10kHz |
marcbax | 0:06f27dbfa599 | 88 | ntcerror=0; |
marcbax | 0:06f27dbfa599 | 89 | beepsdone=1; |
marcbax | 0:06f27dbfa599 | 90 | |
marcbax | 0:06f27dbfa599 | 91 | //key pull-up modes |
marcbax | 0:06f27dbfa599 | 92 | keyup.mode(PullUp); |
marcbax | 0:06f27dbfa599 | 93 | keyright.mode(PullUp); |
marcbax | 0:06f27dbfa599 | 94 | keydown.mode(PullUp); |
marcbax | 0:06f27dbfa599 | 95 | keyleft.mode(PullUp); |
marcbax | 0:06f27dbfa599 | 96 | keyOK.mode(PullUp); |
marcbax | 0:06f27dbfa599 | 97 | |
marcbax | 0:06f27dbfa599 | 98 | //calculate ntcA |
marcbax | 0:06f27dbfa599 | 99 | ntcA = ntcR25/exp(ntcB/298); //298K = 25degC |
marcbax | 0:06f27dbfa599 | 100 | |
marcbax | 0:06f27dbfa599 | 101 | //reset error terms |
marcbax | 0:06f27dbfa599 | 102 | acterror = interror = diferror = 0; |
marcbax | 0:06f27dbfa599 | 103 | |
marcbax | 0:06f27dbfa599 | 104 | //default block temp setting |
marcbax | 0:06f27dbfa599 | 105 | blocksettemp = defaultblocktemp; |
marcbax | 0:06f27dbfa599 | 106 | |
marcbax | 0:06f27dbfa599 | 107 | //initialise kitchentimer |
marcbax | 0:06f27dbfa599 | 108 | countdownset = defaultcountdown; |
marcbax | 0:06f27dbfa599 | 109 | kitchentimerset=0; |
marcbax | 0:06f27dbfa599 | 110 | |
marcbax | 0:06f27dbfa599 | 111 | //initialise the display and show splash screen |
marcbax | 0:06f27dbfa599 | 112 | display.baud(19200); //set display baud rate to 19200 |
marcbax | 0:06f27dbfa599 | 113 | wait(0.2); //display power-on delay |
marcbax | 0:06f27dbfa599 | 114 | display.putc(0x0d); //send CR to display - this needs to be first character sent after power-up |
marcbax | 0:06f27dbfa599 | 115 | wait(0.2); //wait for display to adjust to serial baud rate |
marcbax | 0:06f27dbfa599 | 116 | display.printf("\e[4L\e[20C\e[2m"); //set display to 4 lines of 20 characters, cursor off |
marcbax | 0:06f27dbfa599 | 117 | cleardisplay(); //clear screen and home cursor |
marcbax | 0:06f27dbfa599 | 118 | display.printf("\e[2;2HLumora Sample Prep"); //display splash screen |
marcbax | 0:06f27dbfa599 | 119 | display.printf("\e[3;4HFirmware: %s", fwversion); //display firmware version |
marcbax | 0:06f27dbfa599 | 120 | wait(3); //time that splash screen is shown |
marcbax | 0:06f27dbfa599 | 121 | cleardisplay(); |
marcbax | 0:06f27dbfa599 | 122 | beeponce(); |
marcbax | 0:06f27dbfa599 | 123 | |
marcbax | 0:06f27dbfa599 | 124 | } |
marcbax | 0:06f27dbfa599 | 125 | |
marcbax | 0:06f27dbfa599 | 126 | // Functions called by key interrupts |
marcbax | 0:06f27dbfa599 | 127 | void nothing() { //this is a no-operation function, used to detach an InterruptIn |
marcbax | 0:06f27dbfa599 | 128 | } |
marcbax | 0:06f27dbfa599 | 129 | |
marcbax | 0:06f27dbfa599 | 130 | void int_keyup() { |
marcbax | 0:06f27dbfa599 | 131 | lastkeypressed = 1; |
marcbax | 0:06f27dbfa599 | 132 | beeponce(); |
marcbax | 0:06f27dbfa599 | 133 | } |
marcbax | 0:06f27dbfa599 | 134 | |
marcbax | 0:06f27dbfa599 | 135 | void int_keyright() { |
marcbax | 0:06f27dbfa599 | 136 | lastkeypressed = 2; |
marcbax | 0:06f27dbfa599 | 137 | beeponce(); |
marcbax | 0:06f27dbfa599 | 138 | } |
marcbax | 0:06f27dbfa599 | 139 | |
marcbax | 0:06f27dbfa599 | 140 | void int_keydown() { |
marcbax | 0:06f27dbfa599 | 141 | lastkeypressed = 3; |
marcbax | 0:06f27dbfa599 | 142 | beeponce(); |
marcbax | 0:06f27dbfa599 | 143 | } |
marcbax | 0:06f27dbfa599 | 144 | |
marcbax | 0:06f27dbfa599 | 145 | void int_keyleft() { |
marcbax | 0:06f27dbfa599 | 146 | lastkeypressed = 4; |
marcbax | 0:06f27dbfa599 | 147 | beeponce(); |
marcbax | 0:06f27dbfa599 | 148 | } |
marcbax | 0:06f27dbfa599 | 149 | |
marcbax | 0:06f27dbfa599 | 150 | void int_keyOK() { |
marcbax | 0:06f27dbfa599 | 151 | lastkeypressed = 5; |
marcbax | 0:06f27dbfa599 | 152 | beeponce(); |
marcbax | 0:06f27dbfa599 | 153 | } |
marcbax | 0:06f27dbfa599 | 154 | |
marcbax | 0:06f27dbfa599 | 155 | void incrementsettemp() { |
marcbax | 0:06f27dbfa599 | 156 | if (blocksettemp < maxblocktemp) blocksettemp = blocksettemp + 1; |
marcbax | 0:06f27dbfa599 | 157 | beeponce(); |
marcbax | 0:06f27dbfa599 | 158 | } |
marcbax | 0:06f27dbfa599 | 159 | |
marcbax | 0:06f27dbfa599 | 160 | void decrementsettemp() { |
marcbax | 0:06f27dbfa599 | 161 | if (blocksettemp > minblocktemp) blocksettemp = blocksettemp - 1; |
marcbax | 0:06f27dbfa599 | 162 | beeponce(); |
marcbax | 0:06f27dbfa599 | 163 | } |
marcbax | 0:06f27dbfa599 | 164 | |
marcbax | 0:06f27dbfa599 | 165 | void incrementtimer() { |
marcbax | 0:06f27dbfa599 | 166 | if (countdownset < maxcountdown) countdownset = countdownset + 60; |
marcbax | 0:06f27dbfa599 | 167 | beeponce(); |
marcbax | 0:06f27dbfa599 | 168 | } |
marcbax | 0:06f27dbfa599 | 169 | |
marcbax | 0:06f27dbfa599 | 170 | void decrementtimer() { |
marcbax | 0:06f27dbfa599 | 171 | if (countdownset > 60) countdownset = countdownset - 60; |
marcbax | 0:06f27dbfa599 | 172 | beeponce(); |
marcbax | 0:06f27dbfa599 | 173 | } |
marcbax | 0:06f27dbfa599 | 174 | |
marcbax | 0:06f27dbfa599 | 175 | // Display update routine (also handles alarm) |
marcbax | 0:06f27dbfa599 | 176 | void updatedisplay() { |
marcbax | 0:06f27dbfa599 | 177 | display.printf("\e[2;3HBlock Temp %3.0f%cC", btemp, 223); |
marcbax | 0:06f27dbfa599 | 178 | remainingtime = countdownset - kitchentimer.read(); |
marcbax | 0:06f27dbfa599 | 179 | if (kitchentimerset) { |
marcbax | 0:06f27dbfa599 | 180 | display.printf("\e[3;3HCountdown %02u:%02u", remainingtime/60, remainingtime%60); |
marcbax | 0:06f27dbfa599 | 181 | } |
marcbax | 0:06f27dbfa599 | 182 | else { |
marcbax | 0:06f27dbfa599 | 183 | display.printf("\e[3;3HSet Timer %02u:%02u", remainingtime/60, remainingtime%60); |
marcbax | 0:06f27dbfa599 | 184 | } |
marcbax | 0:06f27dbfa599 | 185 | if (remainingtime <= 0) { //alarm condition |
marcbax | 0:06f27dbfa599 | 186 | kitchentimer.stop(); //stop timer |
marcbax | 0:06f27dbfa599 | 187 | kitchentimerset=0; //clear flag |
marcbax | 0:06f27dbfa599 | 188 | if (!beepsdone) multibeeps(3,0.25); //duration of multibeeps needs to be less then 0.9 seconds |
marcbax | 0:06f27dbfa599 | 189 | beepsdone = 1; //set beepsdone to only sound alarm once |
marcbax | 0:06f27dbfa599 | 190 | } |
marcbax | 0:06f27dbfa599 | 191 | } |
marcbax | 0:06f27dbfa599 | 192 | |
marcbax | 0:06f27dbfa599 | 193 | // Stops the countdown timer |
marcbax | 0:06f27dbfa599 | 194 | void stopkitchentimer() { |
marcbax | 0:06f27dbfa599 | 195 | beeponce(); |
marcbax | 0:06f27dbfa599 | 196 | if (kitchentimerset) { |
marcbax | 0:06f27dbfa599 | 197 | kitchentimer.stop(); |
marcbax | 0:06f27dbfa599 | 198 | } |
marcbax | 0:06f27dbfa599 | 199 | else { |
marcbax | 0:06f27dbfa599 | 200 | kitchentimer.reset(); |
marcbax | 0:06f27dbfa599 | 201 | } |
marcbax | 0:06f27dbfa599 | 202 | kitchentimerset=0; |
marcbax | 0:06f27dbfa599 | 203 | } |
marcbax | 0:06f27dbfa599 | 204 | |
marcbax | 0:06f27dbfa599 | 205 | // Starts the countdown timer |
marcbax | 0:06f27dbfa599 | 206 | void startkitchentimer() { |
marcbax | 0:06f27dbfa599 | 207 | kitchentimer.start(); |
marcbax | 0:06f27dbfa599 | 208 | beeponce(); |
marcbax | 0:06f27dbfa599 | 209 | beepsdone=0; |
marcbax | 0:06f27dbfa599 | 210 | kitchentimerset = 1; |
marcbax | 0:06f27dbfa599 | 211 | } |
marcbax | 0:06f27dbfa599 | 212 | |
marcbax | 0:06f27dbfa599 | 213 | // Returns the current hot block temperature in degrees centigrade as measured by the NTC |
marcbax | 0:06f27dbfa599 | 214 | float blocktemp() { |
marcbax | 0:06f27dbfa599 | 215 | float vntc, rntc; |
marcbax | 0:06f27dbfa599 | 216 | wait(0.03); |
marcbax | 0:06f27dbfa599 | 217 | vntc = ntc.read()*3.3; |
marcbax | 0:06f27dbfa599 | 218 | if (vntc > 3) { //check for NTC open circuit |
marcbax | 0:06f27dbfa599 | 219 | ntcerror=1; |
marcbax | 0:06f27dbfa599 | 220 | return 120; //on error return high temperature |
marcbax | 0:06f27dbfa599 | 221 | } |
marcbax | 0:06f27dbfa599 | 222 | else { |
marcbax | 0:06f27dbfa599 | 223 | if (vntc < 0.3) { //check for NTC open circuit |
marcbax | 0:06f27dbfa599 | 224 | ntcerror = 2; |
marcbax | 0:06f27dbfa599 | 225 | return 120; //on error return high temperature |
marcbax | 0:06f27dbfa599 | 226 | } |
marcbax | 0:06f27dbfa599 | 227 | else { |
marcbax | 0:06f27dbfa599 | 228 | rntc = (vntc * rdivntc)/(3.3 - vntc); //calculate Rntc from Vntc |
marcbax | 0:06f27dbfa599 | 229 | return ntcB/(log(rntc)-log(ntcA))-273; //calculate temperature using exponential approximation curve (beta curve) |
marcbax | 0:06f27dbfa599 | 230 | } |
marcbax | 0:06f27dbfa599 | 231 | } |
marcbax | 0:06f27dbfa599 | 232 | } |
marcbax | 0:06f27dbfa599 | 233 | |
marcbax | 0:06f27dbfa599 | 234 | // Returns the next duty-cycle for the heater using a PID algorithm |
marcbax | 0:06f27dbfa599 | 235 | float getheaterPWM() { |
marcbax | 0:06f27dbfa599 | 236 | float prevtemp, outpt; |
marcbax | 0:06f27dbfa599 | 237 | prevtemp = btemp; //store previous temperature to calculate differential |
marcbax | 0:06f27dbfa599 | 238 | btemp = blocktemp(); //measure current block temperature |
marcbax | 0:06f27dbfa599 | 239 | if (btemp < (blocksettemp - 10)) { //heater constantly on when temperature way too low, no error build-up |
marcbax | 0:06f27dbfa599 | 240 | return 1; |
marcbax | 0:06f27dbfa599 | 241 | } |
marcbax | 0:06f27dbfa599 | 242 | else { //only build up integral error when temperature is within range |
marcbax | 0:06f27dbfa599 | 243 | acterror = blocksettemp - btemp; //calculate current error term |
marcbax | 0:06f27dbfa599 | 244 | interror = interror + acterror; //update integral error term |
marcbax | 0:06f27dbfa599 | 245 | diferror = btemp - prevtemp; //calculate differential error term |
marcbax | 0:06f27dbfa599 | 246 | outpt = (propterm * acterror); //calculate and set proportional contribution |
marcbax | 0:06f27dbfa599 | 247 | outpt = outpt + (intterm * interror); //calculate and add integral contribution |
marcbax | 0:06f27dbfa599 | 248 | outpt = outpt + (difterm * diferror); //calculate and add differential contribution |
marcbax | 0:06f27dbfa599 | 249 | if (outpt <0) outpt=0; //minimum output is "off" |
marcbax | 0:06f27dbfa599 | 250 | if (outpt >1) outpt=1; //maximum output is "on" |
marcbax | 0:06f27dbfa599 | 251 | } |
marcbax | 0:06f27dbfa599 | 252 | if (btemp > maxblocktemp) outpt=0; //software overtemperature cutout |
marcbax | 0:06f27dbfa599 | 253 | return outpt; |
marcbax | 0:06f27dbfa599 | 254 | } |
marcbax | 0:06f27dbfa599 | 255 | |
marcbax | 0:06f27dbfa599 | 256 | //Translates block temperature to RGB value of indication LEDs |
marcbax | 0:06f27dbfa599 | 257 | void temp2RGB (float temp) { |
marcbax | 0:06f27dbfa599 | 258 | if (temp < 40) { //LEDs show pure blue for low temperature |
marcbax | 0:06f27dbfa599 | 259 | LedRGB[0] = 0; |
marcbax | 0:06f27dbfa599 | 260 | LedRGB[1] = 0; |
marcbax | 0:06f27dbfa599 | 261 | LedRGB[2] = 0.5; |
marcbax | 0:06f27dbfa599 | 262 | } |
marcbax | 0:06f27dbfa599 | 263 | else { |
marcbax | 0:06f27dbfa599 | 264 | if (temp > 60) { //LEDs show pure red for high temperatures |
marcbax | 0:06f27dbfa599 | 265 | LedRGB[0] = 1; |
marcbax | 0:06f27dbfa599 | 266 | LedRGB[1] = 0; |
marcbax | 0:06f27dbfa599 | 267 | LedRGB[2] = 0; |
marcbax | 0:06f27dbfa599 | 268 | } |
marcbax | 0:06f27dbfa599 | 269 | else { //LEDs mix red and blue |
marcbax | 0:06f27dbfa599 | 270 | LedRGB[0] = (temp-40)/20; |
marcbax | 0:06f27dbfa599 | 271 | LedRGB[1] = 0; |
marcbax | 0:06f27dbfa599 | 272 | LedRGB[2] = (60-temp)/20; |
marcbax | 0:06f27dbfa599 | 273 | } |
marcbax | 0:06f27dbfa599 | 274 | } |
marcbax | 0:06f27dbfa599 | 275 | } |
marcbax | 0:06f27dbfa599 | 276 | |
marcbax | 0:06f27dbfa599 | 277 | // Drives the temperature indication LEDs in the top plate |
marcbax | 0:06f27dbfa599 | 278 | void driveRGBled() { //uses global array, as functions cannot pass array variables |
marcbax | 0:06f27dbfa599 | 279 | rled = LedRGB[0]; |
marcbax | 0:06f27dbfa599 | 280 | gled = LedRGB[1]; |
marcbax | 0:06f27dbfa599 | 281 | bled = LedRGB[2]; |
marcbax | 0:06f27dbfa599 | 282 | } |
marcbax | 0:06f27dbfa599 | 283 | |
marcbax | 0:06f27dbfa599 | 284 | // Set or adjust the block setpoint temperature |
marcbax | 0:06f27dbfa599 | 285 | void adjustblocktemp () { |
marcbax | 0:06f27dbfa599 | 286 | keyup.fall(&incrementsettemp); //define "up" key function |
marcbax | 0:06f27dbfa599 | 287 | keydown.fall(&decrementsettemp); //define "down" key function |
marcbax | 0:06f27dbfa599 | 288 | keyOK.fall(&int_keyOK); //define "OK" key function |
marcbax | 0:06f27dbfa599 | 289 | display.printf("\e[2;6HSettings"); |
marcbax | 0:06f27dbfa599 | 290 | while (lastkeypressed != 5) { //loop until OK is pressed |
marcbax | 0:06f27dbfa599 | 291 | display.printf("\e[3;3HSet temp= %3.0f%cC", blocksettemp, 223); |
marcbax | 0:06f27dbfa599 | 292 | wait(0.2); |
marcbax | 0:06f27dbfa599 | 293 | } |
marcbax | 0:06f27dbfa599 | 294 | keyup.fall(¬hing); //detach InteruptIn functions |
marcbax | 0:06f27dbfa599 | 295 | keydown.fall(¬hing); |
marcbax | 0:06f27dbfa599 | 296 | keyOK.fall(¬hing); |
marcbax | 0:06f27dbfa599 | 297 | lastkeypressed = 0; //clear flag |
marcbax | 0:06f27dbfa599 | 298 | } |
marcbax | 0:06f27dbfa599 | 299 | |
marcbax | 0:06f27dbfa599 | 300 | // Warm-up to operating temperature |
marcbax | 0:06f27dbfa599 | 301 | void warmupblock (float settemp) { |
marcbax | 0:06f27dbfa599 | 302 | btemp = blocktemp(); |
marcbax | 0:06f27dbfa599 | 303 | float heaterdutycycle; |
marcbax | 0:06f27dbfa599 | 304 | cleardisplay(); |
marcbax | 0:06f27dbfa599 | 305 | if (settemp < maxblocktemp) { //this test avoids overtemperature due to incorrect function call |
marcbax | 0:06f27dbfa599 | 306 | while (btemp < (settemp -0.5)) { //setpoint reached if temperature within 0.5 degrees |
marcbax | 0:06f27dbfa599 | 307 | btemp = blocktemp(); |
marcbax | 0:06f27dbfa599 | 308 | display.printf("\e[2;2HWarming up: %3.0f%cC", btemp, 223); |
marcbax | 0:06f27dbfa599 | 309 | temp2RGB(btemp); |
marcbax | 0:06f27dbfa599 | 310 | driveRGBled(); |
marcbax | 0:06f27dbfa599 | 311 | heaterdutycycle = getheaterPWM(); //PWM heater with longish period |
marcbax | 0:06f27dbfa599 | 312 | heater = 1; |
marcbax | 0:06f27dbfa599 | 313 | wait (5 * heaterdutycycle); |
marcbax | 0:06f27dbfa599 | 314 | heater = 0; |
marcbax | 0:06f27dbfa599 | 315 | wait (5 * (1 - heaterdutycycle)); |
marcbax | 0:06f27dbfa599 | 316 | } |
marcbax | 0:06f27dbfa599 | 317 | } |
marcbax | 0:06f27dbfa599 | 318 | heater = 0; |
marcbax | 0:06f27dbfa599 | 319 | } |
marcbax | 0:06f27dbfa599 | 320 | |
marcbax | 0:06f27dbfa599 | 321 | // Cooling down |
marcbax | 0:06f27dbfa599 | 322 | void coolblockdown() { |
marcbax | 0:06f27dbfa599 | 323 | showtime.detach(); //avoid showing timer on display |
marcbax | 0:06f27dbfa599 | 324 | cleardisplay(); |
marcbax | 0:06f27dbfa599 | 325 | while (1) { |
marcbax | 0:06f27dbfa599 | 326 | btemp = blocktemp(); |
marcbax | 0:06f27dbfa599 | 327 | fan = (btemp > 40); //fan is on when block temperature above 40 degrees |
marcbax | 0:06f27dbfa599 | 328 | display.printf("\e[2;3HCool down: %3.0f%cC", btemp, 223); |
marcbax | 0:06f27dbfa599 | 329 | temp2RGB(btemp); |
marcbax | 0:06f27dbfa599 | 330 | driveRGBled(); |
marcbax | 0:06f27dbfa599 | 331 | if (!fan) display.printf("\e[3;3HSafe to touch"); |
marcbax | 0:06f27dbfa599 | 332 | wait(5); //one update per 5 seconds is more then enough |
marcbax | 0:06f27dbfa599 | 333 | } |
marcbax | 0:06f27dbfa599 | 334 | } |
marcbax | 0:06f27dbfa599 | 335 | |
marcbax | 0:06f27dbfa599 | 336 | // Regulating to a constant temperature |
marcbax | 0:06f27dbfa599 | 337 | void stayhot() { |
marcbax | 0:06f27dbfa599 | 338 | float heaterdutycycle; |
marcbax | 0:06f27dbfa599 | 339 | cleardisplay(); |
marcbax | 0:06f27dbfa599 | 340 | showtime.attach(&updatedisplay, 1.0); //set ticker for routine that updates display every second |
marcbax | 0:06f27dbfa599 | 341 | keyOK.fall(&int_keyOK); //define key interrupt routines |
marcbax | 0:06f27dbfa599 | 342 | keyright.fall(&startkitchentimer); |
marcbax | 0:06f27dbfa599 | 343 | keyup.fall(&incrementtimer); |
marcbax | 0:06f27dbfa599 | 344 | keydown.fall(&decrementtimer); |
marcbax | 0:06f27dbfa599 | 345 | keyleft.fall(&stopkitchentimer); |
marcbax | 0:06f27dbfa599 | 346 | while (lastkeypressed != 5) { //main program loop until OK key pressed |
marcbax | 0:06f27dbfa599 | 347 | btemp = blocktemp(); |
marcbax | 0:06f27dbfa599 | 348 | temp2RGB(btemp); |
marcbax | 0:06f27dbfa599 | 349 | driveRGBled(); |
marcbax | 0:06f27dbfa599 | 350 | heaterdutycycle = getheaterPWM(); //PWM heater with longish period |
marcbax | 0:06f27dbfa599 | 351 | heater = 1; |
marcbax | 0:06f27dbfa599 | 352 | wait (5 * heaterdutycycle); |
marcbax | 0:06f27dbfa599 | 353 | heater = 0; |
marcbax | 0:06f27dbfa599 | 354 | wait (5 * (1 - heaterdutycycle)); |
marcbax | 0:06f27dbfa599 | 355 | } |
marcbax | 0:06f27dbfa599 | 356 | stopkitchentimer(); //stop timer |
marcbax | 0:06f27dbfa599 | 357 | keyOK.fall(¬hing); //detach key interrupt routines |
marcbax | 0:06f27dbfa599 | 358 | keyright.fall(¬hing); |
marcbax | 0:06f27dbfa599 | 359 | keyup.fall(¬hing); |
marcbax | 0:06f27dbfa599 | 360 | keydown.fall(¬hing); |
marcbax | 0:06f27dbfa599 | 361 | } |
marcbax | 0:06f27dbfa599 | 362 | |
marcbax | 0:06f27dbfa599 | 363 | // Main program |
marcbax | 0:06f27dbfa599 | 364 | int main() { |
marcbax | 0:06f27dbfa599 | 365 | initdevice(); //power-on initialisation |
marcbax | 0:06f27dbfa599 | 366 | btemp = blocktemp(); |
marcbax | 0:06f27dbfa599 | 367 | adjustblocktemp(); |
marcbax | 0:06f27dbfa599 | 368 | beeponce(); |
marcbax | 0:06f27dbfa599 | 369 | warmupblock(blocksettemp); //warming up |
marcbax | 0:06f27dbfa599 | 370 | stayhot(); //this is where to program spends most of its time |
marcbax | 0:06f27dbfa599 | 371 | coolblockdown(); //fan-assisted cool down |
marcbax | 0:06f27dbfa599 | 372 | } |