comparison main.c @ 115:90d1ebb941ab

untested fridge control
author Matt Johnston <matt@ucc.asn.au>
date Wed, 03 Oct 2012 23:40:03 +0800
parents b0ec7b783c0b
children 9afff8f29844
comparison
equal deleted inserted replaced
114:b0ec7b783c0b 115:90d1ebb941ab
39 39
40 #define PORT_SHDN PORTD 40 #define PORT_SHDN PORTD
41 #define DDR_SHDN DDRD 41 #define DDR_SHDN DDRD
42 #define PIN_SHDN PD7 42 #define PIN_SHDN PD7
43 43
44 #define PORT_FRIDGE PORTD
45 #define DDR_FRIDGE DDRD
46 #define PIN_FRIDGE PD6
47
44 // total amount of 16bit values available for measurements. 48 // total amount of 16bit values available for measurements.
45 // adjust emperically, be sure to allow enough stack space too 49 // adjust emperically, be sure to allow enough stack space too
46 #define TOTAL_MEASUREMENTS 840 50 #define TOTAL_MEASUREMENTS 840
47 51
48 // each sensor slot uses 8 bytes 52 // each sensor slot uses 8 bytes
62 uint8_t rem; 66 uint8_t rem;
63 }; 67 };
64 68
65 // eeprom-settable parameters. all timeouts should 69 // eeprom-settable parameters. all timeouts should
66 // be a multiple of TICK (6 seconds probably) 70 // be a multiple of TICK (6 seconds probably)
67 static uint16_t measure_wake = 138; // not a divisor of comms_wake 71 static uint16_t measure_wake = 61; // not a divisor of comms_wake
68 static uint16_t comms_wake = 3600; 72 static uint16_t comms_wake = 600;
69 static uint8_t wake_secs = 30; 73 static uint8_t wake_secs = 30;
70 74 // decidegrees
75 static int16_t fridge_setpoint = 180; // 18.0ºC
76 static int16_t fridge_difference = 5; // 0.5ºC
77 static uint16_t fridge_delay = 600; // seconds
71 78
72 // ---- Atomic guards required accessing these variables 79 // ---- Atomic guards required accessing these variables
73 static uint32_t clock_epoch; 80 static uint32_t clock_epoch;
74 static uint16_t comms_count; 81 static uint16_t comms_count;
75 static uint16_t measure_count; 82 static uint16_t measure_count;
76 // decidegrees
77 static uint16_t fridge_temp = 175;
78 // ---- End atomic guards required 83 // ---- End atomic guards required
79 84
80 static uint16_t n_measurements; 85 static uint16_t n_measurements;
81 86
82 // calculated at startup as TOTAL_MEASUREMENTS/n_sensors 87 // calculated at startup as TOTAL_MEASUREMENTS/n_sensors
105 static uint8_t have_cmd; 110 static uint8_t have_cmd;
106 111
107 static uint8_t n_sensors; 112 static uint8_t n_sensors;
108 static uint8_t sensor_id[MAX_SENSORS][ID_LEN]; 113 static uint8_t sensor_id[MAX_SENSORS][ID_LEN];
109 114
115 static int16_t last_fridge = DS18X20_INVALID_DECICELSIUS;
116 static int16_t last_wort = DS18X20_INVALID_DECICELSIUS;
117 static struct epoch_ticks fridge_off_clock = {0};
110 118
111 int uart_putchar(char c, FILE *stream); 119 int uart_putchar(char c, FILE *stream);
112 static void long_delay(int ms); 120 static void long_delay(int ms);
113 static void blink(); 121 static void blink();
114 static uint16_t adc_vcc(); 122 static uint16_t adc_vcc();
135 uint16_t magic; 143 uint16_t magic;
136 uint16_t measure_wake; 144 uint16_t measure_wake;
137 uint16_t comms_wake; 145 uint16_t comms_wake;
138 uint8_t wake_secs; 146 uint8_t wake_secs;
139 147
140 uint16_t fridge_temp; 148 int16_t fridge_setpoint; // decidegrees
141 149 uint8_t fridge_difference; // decidegrees
142 150 uint16_t fridge_delay;
151
152 #if 0
153 static uint8_t wort_id[ID_LEN];
154 static uint8_t fridge_id[ID_LEN];
155 #endif
143 }; 156 };
157
158 static const uint8_t fridge_id[ID_LEN] =
159 {0x28,0xCE,0xB2,0x1A,0x03,0x00,0x00,0x99};
160 static const uint8_t wort_id[ID_LEN] =
161 {0x28,0x49,0xBC,0x1A,0x03,0x00,0x00,0x54};
144 162
145 static void deep_sleep(); 163 static void deep_sleep();
146 164
147 // Very first setup 165 // Very first setup
148 static void 166 static void
167 PORTC = 0xff; 185 PORTC = 0xff;
168 186
169 // 3.3v power for bluetooth and SD 187 // 3.3v power for bluetooth and SD
170 DDR_LED |= _BV(PIN_LED); 188 DDR_LED |= _BV(PIN_LED);
171 DDR_SHDN |= _BV(PIN_SHDN); 189 DDR_SHDN |= _BV(PIN_SHDN);
190
191 DDR_FRIDGE |= _BV(PIN_FRIDGE);
172 192
173 // set pullup 193 // set pullup
174 PORTD |= _BV(PD2); 194 PORTD |= _BV(PD2);
175 // INT0 setup 195 // INT0 setup
176 EICRA = (1<<ISC01); // falling edge - data sheet says it won't work? 196 EICRA = (1<<ISC01); // falling edge - data sheet says it won't work?
321 fprintf_P(crc_stdout, PSTR("comms_time_rem=%hhu\n"), last_comms_clock.rem); 341 fprintf_P(crc_stdout, PSTR("comms_time_rem=%hhu\n"), last_comms_clock.rem);
322 fprintf_P(crc_stdout, PSTR("voltage=%hu\n"), adc_vcc()); 342 fprintf_P(crc_stdout, PSTR("voltage=%hu\n"), adc_vcc());
323 fprintf_P(crc_stdout, PSTR("measure=%hu\n"), measure_wake); 343 fprintf_P(crc_stdout, PSTR("measure=%hu\n"), measure_wake);
324 fprintf_P(crc_stdout, PSTR("comms=%hu\n"), comms_wake); 344 fprintf_P(crc_stdout, PSTR("comms=%hu\n"), comms_wake);
325 fprintf_P(crc_stdout, PSTR("wake=%hhu\n"), wake_secs); 345 fprintf_P(crc_stdout, PSTR("wake=%hhu\n"), wake_secs);
346 fprintf_P(crc_stdout, PSTR("fridge=%.1f\n"), fridge_setpoint/10.0);
347 fprintf_P(crc_stdout, PSTR("fridge_diff=%.1f\n"), fridge_difference/10.0);
348 fprintf_P(crc_stdout, PSTR("fridge_delay=%hu\n"), fridge_delay);
326 fprintf_P(crc_stdout, PSTR("tick_secs=%d\n"), TICK); 349 fprintf_P(crc_stdout, PSTR("tick_secs=%d\n"), TICK);
327 fprintf_P(crc_stdout, PSTR("tick_wake=%d\n"), SLEEP_COMPARE); 350 fprintf_P(crc_stdout, PSTR("tick_wake=%d\n"), SLEEP_COMPARE);
328 fprintf_P(crc_stdout, PSTR("maxsens=%hhu\n"), MAX_SENSORS); 351 fprintf_P(crc_stdout, PSTR("maxsens=%hhu\n"), MAX_SENSORS);
329 fprintf_P(crc_stdout, PSTR("totalmeas=%hu\n"), TOTAL_MEASUREMENTS); 352 fprintf_P(crc_stdout, PSTR("totalmeas=%hu\n"), TOTAL_MEASUREMENTS);
330 fprintf_P(crc_stdout, PSTR("sensors=%hhu\n"), n_sensors); 353 fprintf_P(crc_stdout, PSTR("sensors=%hhu\n"), n_sensors);
443 if (magic == EXPECT_MAGIC) 466 if (magic == EXPECT_MAGIC)
444 { 467 {
445 eeprom_read(measure_wake, measure_wake); 468 eeprom_read(measure_wake, measure_wake);
446 eeprom_read(comms_wake, comms_wake); 469 eeprom_read(comms_wake, comms_wake);
447 eeprom_read(wake_secs, wake_secs); 470 eeprom_read(wake_secs, wake_secs);
471 eeprom_read(fridge_setpoint, fridge_setpoint);
472 eeprom_read(fridge_difference, fridge_difference);
473 eeprom_read(fridge_delay, fridge_delay);
448 } 474 }
449 } 475 }
450 476
451 static void 477 static void
452 cmd_get_params() 478 cmd_get_params()
453 { 479 {
454 printf_P(PSTR("measure %hu\n"), measure_wake); 480 printf_P(PSTR("measure %hu\n"), measure_wake);
455 printf_P(PSTR("comms %hu\n"), comms_wake); 481 printf_P(PSTR("comms %hu\n"), comms_wake);
456 printf_P(PSTR("wake %hhu\n"), wake_secs); 482 printf_P(PSTR("wake %hhu\n"), wake_secs);
457 printf_P(PSTR("tick %d\n"), TICK); 483 printf_P(PSTR("tick %d\n"), TICK);
484 printf_P(PSTR("fridge %.1fº\n"), fridge_setpoint / 10.0);
485 printf_P(PSTR("fridge difference %.1fº\n"), fridge_difference / 10.0);
486 printf_P(PSTR("fridge_delay %hu\n"), fridge_delay);
458 printf_P(PSTR("sensors %hhu (%hhu)\n"), 487 printf_P(PSTR("sensors %hhu (%hhu)\n"),
459 n_sensors, MAX_SENSORS); 488 n_sensors, MAX_SENSORS);
460 printf_P(PSTR("meas %hu (%hu)\n"), 489 printf_P(PSTR("meas %hu (%hu)\n"),
461 max_measurements, TOTAL_MEASUREMENTS); 490 max_measurements, TOTAL_MEASUREMENTS);
462 } 491 }
465 cmd_set_params(const char *params) 494 cmd_set_params(const char *params)
466 { 495 {
467 uint16_t new_measure_wake; 496 uint16_t new_measure_wake;
468 uint16_t new_comms_wake; 497 uint16_t new_comms_wake;
469 uint8_t new_wake_secs; 498 uint8_t new_wake_secs;
470 int ret = sscanf_P(params, PSTR("%hu %hu %hhu"), 499 int16_t new_fridge_setpoint;
471 &new_measure_wake, &new_comms_wake, &new_wake_secs); 500 int16_t new_fridge_difference;
472 501 uint16_t new_fridge_delay;
473 if (ret != 3) 502 int ret = sscanf_P(params, PSTR("%hu %hu %hhu %hd %hd %hu"),
503 &new_measure_wake, &new_comms_wake, &new_wake_secs,
504 &new_fridge_setpoint, &new_fridge_difference, &new_fridge_delay);
505
506 if (ret != 6)
474 { 507 {
475 printf_P(PSTR("Bad values\n")); 508 printf_P(PSTR("Bad values\n"));
476 } 509 }
477 else 510 else
478 { 511 {
479 cli(); 512 ATOMIC_BLOCK(ATOMIC_RESTORESTATE)
480 eeprom_write(new_measure_wake, measure_wake); 513 {
481 eeprom_write(new_comms_wake, comms_wake); 514 eeprom_write(new_measure_wake, measure_wake);
482 eeprom_write(new_wake_secs, wake_secs); 515 eeprom_write(new_comms_wake, comms_wake);
483 uint16_t magic = EXPECT_MAGIC; 516 eeprom_write(new_wake_secs, wake_secs);
484 eeprom_write(magic, magic); 517 eeprom_write(new_fridge_setpoint, fridge_setpoint);
485 sei(); 518 eeprom_write(new_fridge_difference, fridge_difference);
519 eeprom_write(new_fridge_delay, fridge_delay);
520 uint16_t magic = EXPECT_MAGIC;
521 eeprom_write(magic, magic);
522 }
486 printf_P(PSTR("set_params for next boot\n")); 523 printf_P(PSTR("set_params for next boot\n"));
487 printf_P(PSTR("measure %hu comms %hu wake %hhu\n"), 524 printf_P(PSTR("measure %hu comms %hu wake %hhu fridge %.1fº diff %.1f delay %hu\n"),
488 new_measure_wake, new_comms_wake, new_wake_secs); 525 new_measure_wake, new_comms_wake, new_wake_secs,
489 } 526 new_fridge_setpoint / 10.0, new_fridge_difference / 10.0,
490 }static void 527 new_fridge_delay
491 cmd_set_fridge(const char *params) 528 );
492 { 529
493 uint16_t new_measure_wake; 530 // fridge parameters can safely be updated immediately, and avoids
494 uint16_t new_comms_wake; 531 // resetting the delay with a reset.
495 uint8_t new_wake_secs; 532 fridge_setpoint = new_fridge_setpoint;
496 int ret = sscanf_P(params, PSTR("%hu %hu %hhu"), 533 fridge_difference = new_fridge_difference;
497 &new_measure_wake, &new_comms_wake, &new_wake_secs); 534 fridge_delay = new_fridge_delay;
498 535 }
499 if (ret != 3) 536 }
500 { 537
501 printf_P(PSTR("Bad values\n"));
502 }
503 else
504 {
505 cli();
506 eeprom_write(new_measure_wake, measure_wake);
507 eeprom_write(new_comms_wake, comms_wake);
508 eeprom_write(new_wake_secs, wake_secs);
509 uint16_t magic = EXPECT_MAGIC;
510 eeprom_write(magic, magic);
511 sei();
512 printf_P(PSTR("set_params for next boot\n"));
513 printf_P(PSTR("measure %hu comms %hu wake %hhu\n"),
514 new_measure_wake, new_comms_wake, new_wake_secs);
515 }
516 }
517
518 static void 538 static void
519 cmd_awake() 539 cmd_awake()
520 { 540 {
521 stay_awake = 1; 541 stay_awake = 1;
522 printf_P(PSTR("awake\n")); 542 printf_P(PSTR("awake\n"));
550 cmd_get_params(); 570 cmd_get_params();
551 } 571 }
552 else if (strncmp_P(readbuf, PSTR("set_params "), 11) == 0) 572 else if (strncmp_P(readbuf, PSTR("set_params "), 11) == 0)
553 { 573 {
554 cmd_set_params(&readbuf[11]); 574 cmd_set_params(&readbuf[11]);
555 }
556 else if (strncmp_P(readbuf, PSTR("set_fridge "), 11) == 0)
557 {
558 cmd_set_fridge(&readbuf[11]);
559 } 575 }
560 else if (strcmp_P(readbuf, PSTR("awake")) == 0) 576 else if (strcmp_P(readbuf, PSTR("awake")) == 0)
561 { 577 {
562 cmd_awake(); 578 cmd_awake();
563 } 579 }
685 //return 1000 * res_volts; 701 //return 1000 * res_volts;
686 return ((uint32_t)1100*1024*num) / sum; 702 return ((uint32_t)1100*1024*num) / sum;
687 } 703 }
688 704
689 static void 705 static void
706 do_fridge()
707 {
708 struct epoch_ticks now;
709 get_epoch_ticks(&now);
710 if (now.ticks - fridge_off_clock.ticks < fridge_delay)
711 {
712 return;
713 }
714
715 if (last_wort == DS18X20_INVALID_DECICELSIUS)
716 {
717 // can't really do much sensible.... alert perhaps?
718 need_comms = 1;
719 return;
720 }
721
722 int16_t wort_delta = last_wort - fridge_setpoint;
723 uint8_t fridge_on = PORT_FRIDGE & _BV(PIN_FRIDGE);
724 if (fridge_on)
725 {
726 if (last_wort <= fridge_setpoint)
727 {
728 // too cold, turn off
729 PORT_FRIDGE &= ~_BV(PIN_FRIDGE);
730 fridge_off_clock = now;
731 }
732 }
733 else
734 {
735 if (wort_delta > fridge_difference)
736 {
737 // too hot, turn on
738 PORT_FRIDGE |= _BV(PIN_FRIDGE);
739 }
740 }
741 }
742
743 static void
690 do_measurement() 744 do_measurement()
691 { 745 {
692 blink(); 746 blink();
693 747
694 /* Take the timer here since deep_sleep() below could take 6 seconds */ 748 /* Take the timer here since deep_sleep() below could take 6 seconds */
715 if (ret != DS18X20_OK) 769 if (ret != DS18X20_OK)
716 { 770 {
717 reading = VALUE_BROKEN; 771 reading = VALUE_BROKEN;
718 } 772 }
719 set_measurement(s, n_measurements, reading); 773 set_measurement(s, n_measurements, reading);
774
775 if (memcmp(sensor_id[s], fridge_id, sizeof(fridge_id)) == 0)
776 {
777 last_fridge = ds18b20_raw16_to_decicelsius(reading);;
778 }
779 if (memcmp(sensor_id[s], wort_id, sizeof(wort_id)) == 0)
780 {
781 last_wort = ds18b20_raw16_to_decicelsius(reading);;
782 }
720 } 783 }
721 784
722 n_measurements++; 785 n_measurements++;
723 } 786 }
724 787
741 { 804 {
742 if (need_measurement) 805 if (need_measurement)
743 { 806 {
744 need_measurement = 0; 807 need_measurement = 0;
745 do_measurement(); 808 do_measurement();
809 do_fridge();
746 continue; 810 continue;
747 } 811 }
748 812
749 if (have_cmd) 813 if (have_cmd)
750 { 814 {
837 901
838 if (need_measurement) 902 if (need_measurement)
839 { 903 {
840 need_measurement = 0; 904 need_measurement = 0;
841 do_measurement(); 905 do_measurement();
906 do_fridge();
842 continue; 907 continue;
843 } 908 }
844 909
845 deep_sleep(); 910 deep_sleep();
846 } 911 }