comparison tempctrl.c @ 66:0916bfe3f418

Rename settings to tc_settings as it's global.
author Daniel O'Connor <darius@dons.net.au>
date Sun, 14 Apr 2013 14:28:14 +0930
parents 9c5db7fee912
children aaf0603d7f88
comparison
equal deleted inserted replaced
65:662e7f01c991 66:0916bfe3f418
39 #include "1wire.h" 39 #include "1wire.h"
40 #include "ff.h" 40 #include "ff.h"
41 #include "flash.h" 41 #include "flash.h"
42 #include "tempctrl.h" 42 #include "tempctrl.h"
43 43
44 #define TEMPCTRL_FLASH_ADDRESS 0 /* First sector */
45
44 /* Holds all the settings needed */ 46 /* Holds all the settings needed */
45 typedef struct { 47 typedef struct {
46 uint8_t fermenter_ROM[8]; 48 uint8_t fermenter_ROM[8];
47 uint8_t fridge_ROM[8]; 49 uint8_t fridge_ROM[8];
48 uint8_t ambient_ROM[8]; 50 uint8_t ambient_ROM[8];
81 int16_t stale_factor; 83 int16_t stale_factor;
82 84
83 char logfilefmt[64]; 85 char logfilefmt[64];
84 86
85 uint8_t pad[1]; /* Pad to multiple of 4 bytes */ 87 uint8_t pad[1]; /* Pad to multiple of 4 bytes */
86 } settings_t; 88 } tc_settings_t;
87 89
88 /* Current settings in RAM */ 90 /* Current settings in RAM */
89 static settings_t settings; 91 static tc_settings_t tc_settings;
90 92
91 /* Defaults that are shoved into SPI flash if it isn't inited */ 93 /* Defaults that are shoved into SPI flash if it isn't inited */
92 const settings_t default_settings = { 94 const tc_settings_t default_tc_settings = {
93 .fermenter_ROM = { 0x10, 0x4c, 0x7d, 0x53, 0x01, 0x08, 0x00, 0xff }, 95 .fermenter_ROM = { 0x10, 0x4c, 0x7d, 0x53, 0x01, 0x08, 0x00, 0xff },
94 .fridge_ROM = { 0x10, 0x6d, 0x40, 0x53, 0x01, 0x08, 0x00, 0x16 }, 96 .fridge_ROM = { 0x10, 0x6d, 0x40, 0x53, 0x01, 0x08, 0x00, 0x16 },
95 .ambient_ROM = { 0x10, 0x76, 0x05, 0x53, 0x01, 0x08, 0x00, 0x8e }, 97 .ambient_ROM = { 0x10, 0x76, 0x05, 0x53, 0x01, 0x08, 0x00, 0x8e },
96 .target_temp = 1000, 98 .target_temp = 1000,
97 .hysteresis = 100, 99 .hysteresis = 100,
177 179
178 /* Time to check temperatures? */ 180 /* Time to check temperatures? */
179 if (t < checktime) 181 if (t < checktime)
180 return; 182 return;
181 183
182 checktime = t + settings.check_interval; 184 checktime = t + tc_settings.check_interval;
183 185
184 /* Don't do any logging, just force idle and leave */ 186 /* Don't do any logging, just force idle and leave */
185 if (settings.mode == TC_MODE_NOTHING) { 187 if (tc_settings.mode == TC_MODE_NOTHING) {
186 nextstate = 'i'; 188 nextstate = 'i';
187 goto skip; 189 goto skip;
188 } 190 }
189 191
190 /* Update our temperatures 192 /* Update our temperatures
191 * Can take a while (800ms each!) 193 * Can take a while (800ms each!)
192 */ 194 */
193 tempt = OWGetTemp(settings.fermenter_ROM); 195 tempt = OWGetTemp(tc_settings.fermenter_ROM);
194 fridge_temp = OWGetTemp(settings.fridge_ROM); 196 fridge_temp = OWGetTemp(tc_settings.fridge_ROM);
195 ambient_temp = OWGetTemp(settings.ambient_ROM); 197 ambient_temp = OWGetTemp(tc_settings.ambient_ROM);
196 198
197 /* We only care about this one, only update the value we decide on 199 /* We only care about this one, only update the value we decide on
198 * only if it is valid 200 * only if it is valid
199 */ 201 */
200 if (tempt > OW_TEMP_BADVAL) { 202 if (tempt > OW_TEMP_BADVAL) {
201 fermenter_temp = tempt; 203 fermenter_temp = tempt;
202 lastdata = t; 204 lastdata = t;
203 } 205 }
204 206
205 /* Check for stale data */ 207 /* Check for stale data */
206 if (lastdata + (settings.check_interval * settings.stale_factor) < t) 208 if (lastdata + (tc_settings.check_interval * tc_settings.stale_factor) < t)
207 stale = 1; 209 stale = 1;
208 210
209 /* Default to remaining as we are */ 211 /* Default to remaining as we are */
210 nextstate = '-'; 212 nextstate = '-';
211 213
212 /* Temperature diff, -ve => too cold, +ve => too warm */ 214 /* Temperature diff, -ve => too cold, +ve => too warm */
213 diff = fermenter_temp - settings.target_temp; 215 diff = fermenter_temp - tc_settings.target_temp;
214 216
215 switch (currstate) { 217 switch (currstate) {
216 case 'i': 218 case 'i':
217 /* If we're idle then only heat or cool if the temperate difference is out of the 219 /* If we're idle then only heat or cool if the temperate difference is out of the
218 * hysteresis band and the heater/cooler have been off long enough 220 * hysteresis band and the heater/cooler have been off long enough
219 */ 221 */
220 if (abs(diff) > settings.hysteresis) { 222 if (abs(diff) > tc_settings.hysteresis) {
221 if (diff < 0 && settings.minheatofftime + lastheatoff < t) 223 if (diff < 0 && tc_settings.minheatofftime + lastheatoff < t)
222 nextstate = 'h'; 224 nextstate = 'h';
223 else if (diff > 0 && settings.mincoolofftime + lastcooloff < t) 225 else if (diff > 0 && tc_settings.mincoolofftime + lastcooloff < t)
224 nextstate = 'c'; 226 nextstate = 'c';
225 } 227 }
226 break; 228 break;
227 229
228 case 'c': 230 case 'c':
229 /* Work out if we should go idle (based on min on time & overshoot) */ 231 /* Work out if we should go idle (based on min on time & overshoot) */
230 if (diff + settings.mincoolovershoot < 0 && 232 if (diff + tc_settings.mincoolovershoot < 0 &&
231 settings.mincoolontime + lastcoolon < t) 233 tc_settings.mincoolontime + lastcoolon < t)
232 nextstate = 'i'; 234 nextstate = 'i';
233 break; 235 break;
234 236
235 case 'h': 237 case 'h':
236 if (diff - settings.minheatovershoot > 0 && 238 if (diff - tc_settings.minheatovershoot > 0 &&
237 settings.minheatontime + lastheaton < t) 239 tc_settings.minheatontime + lastheaton < t)
238 nextstate = 'i'; 240 nextstate = 'i';
239 break; 241 break;
240 242
241 default: 243 default:
242 printf("\nUnknown state %c, going to idle\n", currstate); 244 printf("\nUnknown state %c, going to idle\n", currstate);
247 /* Override if we have stale data */ 249 /* Override if we have stale data */
248 if (stale) 250 if (stale)
249 nextstate = 'i'; 251 nextstate = 'i';
250 252
251 /* Handle state forcing */ 253 /* Handle state forcing */
252 if (settings.mode != TC_MODE_AUTO) 254 if (tc_settings.mode != TC_MODE_AUTO)
253 forced = 1; 255 forced = 1;
254 else 256 else
255 forced = 0; 257 forced = 0;
256 258
257 if (settings.mode == TC_MODE_IDLE) 259 if (tc_settings.mode == TC_MODE_IDLE)
258 nextstate = 'i'; 260 nextstate = 'i';
259 else if (settings.mode == TC_MODE_HEAT) 261 else if (tc_settings.mode == TC_MODE_HEAT)
260 nextstate = 'h'; 262 nextstate = 'h';
261 else if (settings.mode == TC_MODE_COOL) 263 else if (tc_settings.mode == TC_MODE_COOL)
262 nextstate = 'c'; 264 nextstate = 'c';
263 265
264 /* Keep track of when we last turned things on or off */ 266 /* Keep track of when we last turned things on or off */
265 skip: 267 skip:
266 switch (nextstate) { 268 switch (nextstate) {
285 287
286 if (nextstate != '-') 288 if (nextstate != '-')
287 currstate = nextstate; 289 currstate = nextstate;
288 290
289 291
290 if (settings.mode != TC_MODE_NOTHING) { 292 if (tc_settings.mode != TC_MODE_NOTHING) {
291 localtime_r(&t, &tm); 293 localtime_r(&t, &tm);
292 p = linebuf; 294 p = linebuf;
293 p += strftime(p, sizeof(linebuf) - 1, "%Y/%m/%d %H:%M:%S: ", &tm); 295 p += strftime(p, sizeof(linebuf) - 1, "%Y/%m/%d %H:%M:%S: ", &tm);
294 p += fmttemp(p, "Tr", settings.target_temp, ", "); 296 p += fmttemp(p, "Tr", tc_settings.target_temp, ", ");
295 p += fmttemp(p, "Fm", tempt, ", "); 297 p += fmttemp(p, "Fm", tempt, ", ");
296 p += fmttemp(p, "Fr", fridge_temp, ", "); 298 p += fmttemp(p, "Fr", fridge_temp, ", ");
297 p += fmttemp(p, "Am", ambient_temp, ", "); 299 p += fmttemp(p, "Am", ambient_temp, ", ");
298 sprintf(p, "St: %s, Fl: %s%s\n", state2long(currstate), 300 sprintf(p, "St: %s, Fl: %s%s\n", state2long(currstate),
299 forced ? "F" : "", 301 forced ? "F" : "",
300 stale ? "S" : ""); 302 stale ? "S" : "");
301 fputs(linebuf, stdout); 303 fputs(linebuf, stdout);
302 if (settings.logfilefmt[0] != '\0') { 304 if (tc_settings.logfilefmt[0] != '\0') {
303 strftime(fbuf, sizeof(fbuf) - 1, settings.logfilefmt, &tm); 305 strftime(fbuf, sizeof(fbuf) - 1, tc_settings.logfilefmt, &tm);
304 306
305 if ((fserr = f_open(&f, fbuf, FA_WRITE | FA_OPEN_ALWAYS)) != FR_OK) { 307 if ((fserr = f_open(&f, fbuf, FA_WRITE | FA_OPEN_ALWAYS)) != FR_OK) {
306 printf("Failed to open file: %d\n", fserr); 308 printf("Failed to open file: %d\n", fserr);
307 goto openerr; 309 goto openerr;
308 } 310 }
335 /* Read the settings from SPI flash 337 /* Read the settings from SPI flash
336 * If the CRC fails then reload from onboard flash 338 * If the CRC fails then reload from onboard flash
337 */ 339 */
338 static void 340 static void
339 tempctrl_load_or_init_settings(void) { 341 tempctrl_load_or_init_settings(void) {
340 /* XXX: todo */ 342 if (!flashreadblock(TEMPCTRL_FLASH_ADDRESS, sizeof(tc_settings), &tc_settings)) {
341 if (!flashreadblock(0, sizeof(settings), &settings)) {
342 fputs("CRC fails, loading defaults\n", stdout); 343 fputs("CRC fails, loading defaults\n", stdout);
343 tempctrl_default_settings(); 344 tempctrl_default_settings();
344 tempctrl_write_settings(); 345 tempctrl_write_settings();
345 } 346 }
346 } 347 }
347 348
348 /* Load in the defaults from flash */ 349 /* Load in the defaults from flash */
349 static void 350 static void
350 tempctrl_default_settings(void) { 351 tempctrl_default_settings(void) {
351 memcpy(&settings, &default_settings, sizeof(settings_t)); 352 memcpy(&tc_settings, &default_tc_settings, sizeof(tc_settings_t));
352 } 353 }
353 354
354 /* Write the current settings out to SPI flash */ 355 /* Write the current settings out to SPI flash */
355 static void 356 static void
356 tempctrl_write_settings(void) { 357 tempctrl_write_settings(void) {
357 flashwriteblock(0, sizeof(settings), &settings); 358 flashwriteblock(TEMPCTRL_FLASH_ADDRESS, sizeof(tc_settings), &tc_settings);
358 } 359 }
359 360
360 /* Set the relays to match the desired state */ 361 /* Set the relays to match the desired state */
361 static void 362 static void
362 setstate(char state) { 363 setstate(char state) {
381 cool = 0; 382 cool = 0;
382 heat = 0; 383 heat = 0;
383 break; 384 break;
384 } 385 }
385 386
386 if (cool ^ settings.coolinv) 387 if (cool ^ tc_settings.coolinv)
387 GPIO_SetBits(char2port(settings.coolport), 1 << settings.coolpin); 388 GPIO_SetBits(char2port(tc_settings.coolport), 1 << tc_settings.coolpin);
388 else 389 else
389 GPIO_ResetBits(char2port(settings.coolport), 1 << settings.coolpin); 390 GPIO_ResetBits(char2port(tc_settings.coolport), 1 << tc_settings.coolpin);
390 391
391 if (heat ^ settings.heatinv) 392 if (heat ^ tc_settings.heatinv)
392 GPIO_SetBits(char2port(settings.heatport), 1 << settings.heatpin); 393 GPIO_SetBits(char2port(tc_settings.heatport), 1 << tc_settings.heatpin);
393 else 394 else
394 GPIO_ResetBits(char2port(settings.heatport), 1 << settings.heatpin); 395 GPIO_ResetBits(char2port(tc_settings.heatport), 1 << tc_settings.heatpin);
395 } 396 }
396 397
397 /* Handle user command 398 /* Handle user command
398 * 399 *
399 */ 400 */
458 "Min heat overshoot - %d, Min cool overshoot - %d\n" 459 "Min heat overshoot - %d, Min cool overshoot - %d\n"
459 "Min cool on time - %d, Min cool off time - %d\n" 460 "Min cool on time - %d, Min cool off time - %d\n"
460 "Min heat on time - %d, Min heat off time - %d\n" 461 "Min heat on time - %d, Min heat off time - %d\n"
461 "Cool: Port %c Pin %d Inv %d, Heat: Port %c Pin %d Inv %d\n" 462 "Cool: Port %c Pin %d Inv %d, Heat: Port %c Pin %d Inv %d\n"
462 "Log format: %s\n", 463 "Log format: %s\n",
463 settings.fermenter_ROM[0], settings.fermenter_ROM[1], settings.fermenter_ROM[2], settings.fermenter_ROM[3], 464 tc_settings.fermenter_ROM[0], tc_settings.fermenter_ROM[1], tc_settings.fermenter_ROM[2], tc_settings.fermenter_ROM[3],
464 settings.fermenter_ROM[4], settings.fermenter_ROM[5], settings.fermenter_ROM[6], settings.fermenter_ROM[7], 465 tc_settings.fermenter_ROM[4], tc_settings.fermenter_ROM[5], tc_settings.fermenter_ROM[6], tc_settings.fermenter_ROM[7],
465 settings.fridge_ROM[0], settings.fridge_ROM[1], settings.fridge_ROM[2], settings.fridge_ROM[3], 466 tc_settings.fridge_ROM[0], tc_settings.fridge_ROM[1], tc_settings.fridge_ROM[2], tc_settings.fridge_ROM[3],
466 settings.fridge_ROM[4], settings.fridge_ROM[5], settings.fridge_ROM[6], settings.fridge_ROM[7], 467 tc_settings.fridge_ROM[4], tc_settings.fridge_ROM[5], tc_settings.fridge_ROM[6], tc_settings.fridge_ROM[7],
467 settings.ambient_ROM[0], settings.ambient_ROM[1], settings.ambient_ROM[2], settings.ambient_ROM[3], 468 tc_settings.ambient_ROM[0], tc_settings.ambient_ROM[1], tc_settings.ambient_ROM[2], tc_settings.ambient_ROM[3],
468 settings.ambient_ROM[4], settings.ambient_ROM[5], settings.ambient_ROM[6], settings.ambient_ROM[7], 469 tc_settings.ambient_ROM[4], tc_settings.ambient_ROM[5], tc_settings.ambient_ROM[6], tc_settings.ambient_ROM[7],
469 settings.mode, settings.target_temp, settings.hysteresis, 470 tc_settings.mode, tc_settings.target_temp, tc_settings.hysteresis,
470 settings.minheatovershoot, settings.mincoolovershoot, 471 tc_settings.minheatovershoot, tc_settings.mincoolovershoot,
471 settings.mincoolontime, settings.minheatontime, 472 tc_settings.mincoolontime, tc_settings.minheatontime,
472 settings.minheatontime, settings.minheatofftime, 473 tc_settings.minheatontime, tc_settings.minheatofftime,
473 settings.coolport, settings.coolpin, settings.coolinv, 474 tc_settings.coolport, tc_settings.coolpin, tc_settings.coolinv,
474 settings.heatport, settings.heatpin, settings.heatinv, 475 tc_settings.heatport, tc_settings.heatpin, tc_settings.heatinv,
475 settings.logfilefmt[0] == '\0' ? "none" : settings.logfilefmt 476 tc_settings.logfilefmt[0] == '\0' ? "none" : tc_settings.logfilefmt
476 ); 477 );
477 return; 478 return;
478 } 479 }
479 if (!strcasecmp(argv[0], "mode")) { 480 if (!strcasecmp(argv[0], "mode")) {
480 if (argc < 2) { 481 if (argc < 2) {
486 case TC_MODE_AUTO: 487 case TC_MODE_AUTO:
487 case TC_MODE_HEAT: 488 case TC_MODE_HEAT:
488 case TC_MODE_COOL: 489 case TC_MODE_COOL:
489 case TC_MODE_IDLE: 490 case TC_MODE_IDLE:
490 case TC_MODE_NOTHING: 491 case TC_MODE_NOTHING:
491 settings.mode = argv[1][0]; 492 tc_settings.mode = argv[1][0];
492 break; 493 break;
493 494
494 default: 495 default:
495 printf("Unknown mode character '%c'\n", argv[1][0]); 496 printf("Unknown mode character '%c'\n", argv[1][0]);
496 break; 497 break;
509 &ROM[0], &ROM[1], &ROM[2], &ROM[3], 510 &ROM[0], &ROM[1], &ROM[2], &ROM[3],
510 &ROM[4], &ROM[5], &ROM[6], &ROM[7]) != 8) { 511 &ROM[4], &ROM[5], &ROM[6], &ROM[7]) != 8) {
511 printf("Unable to parse ROM ID\n"); 512 printf("Unable to parse ROM ID\n");
512 } else { 513 } else {
513 if (!strcasecmp(argv[0], "ferm")) 514 if (!strcasecmp(argv[0], "ferm"))
514 memcpy(&settings.fermenter_ROM, ROM, sizeof(ROM)); 515 memcpy(&tc_settings.fermenter_ROM, ROM, sizeof(ROM));
515 if (!strcasecmp(argv[0], "frg")) 516 if (!strcasecmp(argv[0], "frg"))
516 memcpy(&settings.fridge_ROM, ROM, sizeof(ROM)); 517 memcpy(&tc_settings.fridge_ROM, ROM, sizeof(ROM));
517 if (!strcasecmp(argv[0], "amb")) 518 if (!strcasecmp(argv[0], "amb"))
518 memcpy(&settings.ambient_ROM, ROM, sizeof(ROM)); 519 memcpy(&tc_settings.ambient_ROM, ROM, sizeof(ROM));
519 } 520 }
520 return; 521 return;
521 } 522 }
522 if (!strcasecmp(argv[0], "log")) { 523 if (!strcasecmp(argv[0], "log")) {
523 if (argc == 1) 524 if (argc == 1)
524 bzero(settings.logfilefmt, sizeof(settings.logfilefmt)); 525 bzero(tc_settings.logfilefmt, sizeof(tc_settings.logfilefmt));
525 else { 526 else {
526 if (strlen(argv[1]) > sizeof(settings.logfilefmt) - 1) 527 if (strlen(argv[1]) > sizeof(tc_settings.logfilefmt) - 1)
527 printf("New path too log (%d > %d)\n", strlen(argv[1]), sizeof(settings.logfilefmt)); 528 printf("New path too log (%d > %d)\n", strlen(argv[1]), sizeof(tc_settings.logfilefmt));
528 else 529 else
529 strcpy(settings.logfilefmt, argv[1]); 530 strcpy(tc_settings.logfilefmt, argv[1]);
530 } 531 }
531 return; 532 return;
532 } 533 }
533 534
534 /* Handle setting the multitude of variables 535 /* Handle setting the multitude of variables
542 printf("Unable to parse value for variable\n"); 543 printf("Unable to parse value for variable\n");
543 return; 544 return;
544 } 545 }
545 546
546 if (!strcasecmp(argv[1], "targ")) { 547 if (!strcasecmp(argv[1], "targ")) {
547 settings.target_temp = data; 548 tc_settings.target_temp = data;
548 } else if (!strcasecmp(argv[1], "hys")) { 549 } else if (!strcasecmp(argv[1], "hys")) {
549 settings.hysteresis = data; 550 tc_settings.hysteresis = data;
550 } else if (!strcasecmp(argv[1], "mhov")) { 551 } else if (!strcasecmp(argv[1], "mhov")) {
551 settings.minheatovershoot = data; 552 tc_settings.minheatovershoot = data;
552 } else if (!strcasecmp(argv[1], "mcov")) { 553 } else if (!strcasecmp(argv[1], "mcov")) {
553 settings.mincoolovershoot = data; 554 tc_settings.mincoolovershoot = data;
554 } else if (!strcasecmp(argv[1], "mcon")) { 555 } else if (!strcasecmp(argv[1], "mcon")) {
555 settings.mincoolontime = data; 556 tc_settings.mincoolontime = data;
556 } else if (!strcasecmp(argv[1], "mcoff")) { 557 } else if (!strcasecmp(argv[1], "mcoff")) {
557 settings.mincoolofftime = data; 558 tc_settings.mincoolofftime = data;
558 } else if (!strcasecmp(argv[1], "mhon")) { 559 } else if (!strcasecmp(argv[1], "mhon")) {
559 settings.minheatontime = data; 560 tc_settings.minheatontime = data;
560 } else if (!strcasecmp(argv[1], "mhoff")) { 561 } else if (!strcasecmp(argv[1], "mhoff")) {
561 settings.minheatofftime = data; 562 tc_settings.minheatofftime = data;
562 } else { 563 } else {
563 printf("Unknown setting\n"); 564 printf("Unknown setting\n");
564 } 565 }
565 } 566 }
566 567