comparison tempctrl.c @ 57:adc9b1555f9d

Add the ability to log temperatures to SD card. Fix a few warnings while I am here.
author Daniel O'Connor <darius@dons.net.au>
date Mon, 08 Apr 2013 22:20:40 +0930
parents b4440f9f6d47
children bbdf5642a7b7
comparison
equal deleted inserted replaced
56:f0563086040d 57:adc9b1555f9d
35 #include <sys/time.h> 35 #include <sys/time.h>
36 #include <time.h> 36 #include <time.h>
37 #include "stm32f10x.h" 37 #include "stm32f10x.h"
38 38
39 #include "1wire.h" 39 #include "1wire.h"
40 #include "ff.h"
40 #include "flash.h" 41 #include "flash.h"
41 #include "tempctrl.h" 42 #include "tempctrl.h"
42 43
43 /* Holds all the settings needed */ 44 /* Holds all the settings needed */
44 typedef struct { 45 typedef struct {
76 uint8_t heatinv; 77 uint8_t heatinv;
77 78
78 /* Check/stale times */ 79 /* Check/stale times */
79 int16_t check_interval; 80 int16_t check_interval;
80 int16_t stale_factor; 81 int16_t stale_factor;
82
83 char logfilefmt[64];
81 84
82 uint8_t pad[1]; /* Pad to multiple of 4 bytes */ 85 uint8_t pad[1]; /* Pad to multiple of 4 bytes */
83 } settings_t; 86 } settings_t;
84 87
85 /* Current settings in RAM */ 88 /* Current settings in RAM */
105 .heatport = 'E', 108 .heatport = 'E',
106 .heatpin = 5, 109 .heatpin = 5,
107 .heatinv = 1, 110 .heatinv = 1,
108 .check_interval = 10, 111 .check_interval = 10,
109 .stale_factor = 3, 112 .stale_factor = 3,
113 .logfilefmt = "/%Y%M%D.log"
110 }; 114 };
111 115
112 /* Local variable declarations */ 116 /* Local variable declarations */
113 117
114 /* Local function prototypes */ 118 /* Local function prototypes */
115 static void tempctrl_load_or_init_settings(void); 119 static void tempctrl_load_or_init_settings(void);
116 static void tempctrl_default_settings(void); 120 static void tempctrl_default_settings(void);
117 static void tempctrl_write_settings(void); 121 static void tempctrl_write_settings(void);
118 static void setstate(char state); 122 static void setstate(char state);
119 static const char * state2long(char s); 123 static const char * state2long(char s);
120 static void printtemp(const char *name, int tmp, const char *trailer); 124 static int fmttemp(char *buf, const char *name, int tmp, const char *trailer);
121 static GPIO_TypeDef *char2port(char port); 125 static GPIO_TypeDef *char2port(char port);
122 126
123 /* 127 /*
124 * tempctrl_init 128 * tempctrl_init
125 * 129 *
160 char nextstate; 164 char nextstate;
161 int forced; 165 int forced;
162 int stale; 166 int stale;
163 time_t t; 167 time_t t;
164 struct tm tm; 168 struct tm tm;
165 char buf[23]; 169 char linebuf[90], *p;
170 FRESULT fserr;
171 FIL f;
172 char fbuf[20];
166 173
167 t = time(NULL); 174 t = time(NULL);
175 stale = 0;
176 tempt = 0;
168 177
169 /* Time to check temperatures? */ 178 /* Time to check temperatures? */
170 if (t < checktime) 179 if (t < checktime)
171 return; 180 return;
172 181
194 } 203 }
195 204
196 /* Check for stale data */ 205 /* Check for stale data */
197 if (lastdata + (settings.check_interval * settings.stale_factor) < t) 206 if (lastdata + (settings.check_interval * settings.stale_factor) < t)
198 stale = 1; 207 stale = 1;
199 else
200 stale = 0;
201 208
202 /* Default to remaining as we are */ 209 /* Default to remaining as we are */
203 nextstate = '-'; 210 nextstate = '-';
204 211
205 /* Temperature diff, -ve => too cold, +ve => too warm */ 212 /* Temperature diff, -ve => too cold, +ve => too warm */
280 currstate = nextstate; 287 currstate = nextstate;
281 288
282 289
283 if (settings.mode != TC_MODE_NOTHING) { 290 if (settings.mode != TC_MODE_NOTHING) {
284 localtime_r(&t, &tm); 291 localtime_r(&t, &tm);
285 assert(strftime(buf, sizeof(buf) - 1, "%Y/%m/%d %H:%M:%S: ", &tm) != 0); 292 p = linebuf;
286 fputs(buf, stdout); 293 p += strftime(p, sizeof(linebuf) - 1, "%Y/%m/%d %H:%M:%S: ", &tm);
287 printtemp("Tr", settings.target_temp, ", "); 294 p += fmttemp(p, "Tr", settings.target_temp, ", ");
288 printtemp("Fm", tempt, ", "); // Use actual value from sensor 295 p += fmttemp(p, "Fm", tempt, ", ");
289 printtemp("Fr", fridge_temp, ", "); 296 p += fmttemp(p, "Fr", fridge_temp, ", ");
290 printtemp("Am", ambient_temp, ", "); 297 p += fmttemp(p, "Am", ambient_temp, ", ");
291 printf("St: %s, Fl: %s%s\r\n", state2long(currstate), 298 sprintf(p, "St: %s, Fl: %s%s\r\n", state2long(currstate),
292 forced ? "F" : "", 299 forced ? "F" : "",
293 stale ? "S" : ""); 300 stale ? "S" : "");
294 } 301 fputs(linebuf, stdout);
295 302 if (settings.logfilefmt[0] != '\0') {
303 strftime(fbuf, sizeof(fbuf) - 1, settings.logfilefmt, &tm);
304
305 if ((fserr = f_open(&f, fbuf, FA_WRITE | FA_OPEN_ALWAYS)) != FR_OK) {
306 printf("Failed to open file: %d\n", fserr);
307 goto openerr;
308 }
309
310 if ((fserr = f_lseek(&f, f_size(&f))) != FR_OK) {
311 printf("Failed to seek to end of file: %d\n", fserr);
312 goto openerr;
313 }
314
315 f_puts(linebuf, &f);
316 f_close(&f);
317 }
318 }
319
320 openerr:
296 setstate(currstate); 321 setstate(currstate);
297 } 322 }
298 323
299 /* 324 /*
300 * Print out temperature (or short error code) with specified trailer 325 * Format a temperature (or short error code) with specified trailer
301 */ 326 */
302 static void 327 static int
303 printtemp(const char *name, int tmp, const char *trailer) { 328 fmttemp(char *buf, const char *name, int tmp, const char *trailer) {
304 if (tmp > OW_TEMP_BADVAL) 329 if (tmp > OW_TEMP_BADVAL)
305 printf("%s: %d.%02d%s", name, GETWHOLE(tmp), GETFRAC(tmp), trailer); 330 return sprintf(buf, "%s: %d.%02d%s", name, GETWHOLE(tmp), GETFRAC(tmp), trailer);
306 else 331 else
307 printf("%s: %s%s", name, OWTempStatusStr(tmp, 1), trailer); 332 return sprintf(buf, "%s: %s%s", name, OWTempStatusStr(tmp, 1), trailer);
308 } 333 }
309 334
310 /* Read the settings from SPI flash 335 /* Read the settings from SPI flash
311 * If the CRC fails then reload from onboard flash 336 * If the CRC fails then reload from onboard flash
312 */ 337 */
431 "Ambient ROM ID %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\r\n" 456 "Ambient ROM ID %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\r\n"
432 "Mode - %c, Target - %d, Hystersis - %d\r\n" 457 "Mode - %c, Target - %d, Hystersis - %d\r\n"
433 "Min heat overshoot - %d, Min cool overshoot - %d\r\n" 458 "Min heat overshoot - %d, Min cool overshoot - %d\r\n"
434 "Min cool on time - %d, Min cool off time - %d\r\n" 459 "Min cool on time - %d, Min cool off time - %d\r\n"
435 "Min heat on time - %d, Min heat off time - %d\r\n" 460 "Min heat on time - %d, Min heat off time - %d\r\n"
436 "Cool: Port %c Pin %d Inv %d, Heat: Port %c Pin %d Inv %d\r\n", 461 "Cool: Port %c Pin %d Inv %d, Heat: Port %c Pin %d Inv %d\r\n"
462 "Log format: %s\n",
437 settings.fermenter_ROM[0], settings.fermenter_ROM[1], settings.fermenter_ROM[2], settings.fermenter_ROM[3], 463 settings.fermenter_ROM[0], settings.fermenter_ROM[1], settings.fermenter_ROM[2], settings.fermenter_ROM[3],
438 settings.fermenter_ROM[4], settings.fermenter_ROM[5], settings.fermenter_ROM[6], settings.fermenter_ROM[7], 464 settings.fermenter_ROM[4], settings.fermenter_ROM[5], settings.fermenter_ROM[6], settings.fermenter_ROM[7],
439 settings.fridge_ROM[0], settings.fridge_ROM[1], settings.fridge_ROM[2], settings.fridge_ROM[3], 465 settings.fridge_ROM[0], settings.fridge_ROM[1], settings.fridge_ROM[2], settings.fridge_ROM[3],
440 settings.fridge_ROM[4], settings.fridge_ROM[5], settings.fridge_ROM[6], settings.fridge_ROM[7], 466 settings.fridge_ROM[4], settings.fridge_ROM[5], settings.fridge_ROM[6], settings.fridge_ROM[7],
441 settings.ambient_ROM[0], settings.ambient_ROM[1], settings.ambient_ROM[2], settings.ambient_ROM[3], 467 settings.ambient_ROM[0], settings.ambient_ROM[1], settings.ambient_ROM[2], settings.ambient_ROM[3],
443 settings.mode, settings.target_temp, settings.hysteresis, 469 settings.mode, settings.target_temp, settings.hysteresis,
444 settings.minheatovershoot, settings.mincoolovershoot, 470 settings.minheatovershoot, settings.mincoolovershoot,
445 settings.mincoolontime, settings.minheatontime, 471 settings.mincoolontime, settings.minheatontime,
446 settings.minheatontime, settings.minheatofftime, 472 settings.minheatontime, settings.minheatofftime,
447 settings.coolport, settings.coolpin, settings.coolinv, 473 settings.coolport, settings.coolpin, settings.coolinv,
448 settings.heatport, settings.heatpin, settings.heatinv 474 settings.heatport, settings.heatpin, settings.heatinv,
475 settings.logfilefmt[0] == '\0' ? "none" : settings.logfilefmt
449 ); 476 );
450 return; 477 return;
451 } 478 }
452 if (!strcasecmp(argv[0], "mode")) { 479 if (!strcasecmp(argv[0], "mode")) {
453 if (argc < 2) { 480 if (argc < 2) {
490 if (!strcasecmp(argv[0], "amb")) 517 if (!strcasecmp(argv[0], "amb"))
491 memcpy(&settings.ambient_ROM, ROM, sizeof(ROM)); 518 memcpy(&settings.ambient_ROM, ROM, sizeof(ROM));
492 } 519 }
493 return; 520 return;
494 } 521 }
522 if (!strcasecmp(argv[0], "log")) {
523 if (argc == 1)
524 bzero(settings.logfilefmt, sizeof(settings.logfilefmt));
525 else {
526 if (strlen(argv[1]) > sizeof(settings.logfilefmt) - 1)
527 printf("New path too log (%d > %d)\n", strlen(argv[1]), sizeof(settings.logfilefmt));
528 else
529 strcpy(settings.logfilefmt, argv[1]);
530 return;
531 }
532 }
495 533
496 /* Handle setting the multitude of variables 534 /* Handle setting the multitude of variables
497 * It's last to simplify things */ 535 * It's last to simplify things */
498 if (argc < 3) { 536 if (argc < 3) {
499 fputs("Incorrect number of arguments for variable/value\r\n", stdout); 537 fputs("Incorrect number of arguments for variable/value\r\n", stdout);
568 return GPIOC; 606 return GPIOC;
569 case 'D': 607 case 'D':
570 return GPIOD; 608 return GPIOD;
571 case 'E': 609 case 'E':
572 return GPIOE; 610 return GPIOE;
573 } 611 default:
574 } 612 assert(1 == 0); /* Silence GCC warning */
575 613 }
614 }
615