Mercurial > templog
comparison main.c @ 121:45c051a7db82
try and take account of the fridge temperature too
author | Matt Johnston <matt@ucc.asn.au> |
---|---|
date | Wed, 10 Oct 2012 21:04:13 +0800 |
parents | bb0c946460f3 |
children | 30c2c3341a4a |
comparison
equal
deleted
inserted
replaced
120:295a4b875677 | 121:45c051a7db82 |
---|---|
20 // - measurement interval | 20 // - measurement interval |
21 // - transmit interval | 21 // - transmit interval |
22 // - bluetooth params | 22 // - bluetooth params |
23 // - number of sensors (and range?) | 23 // - number of sensors (and range?) |
24 | 24 |
25 #define MIN(X,Y) ((X) < (Y) ? (X) : (Y)) | |
26 #define MAX(X,Y) ((X) > (Y) ? (X) : (Y)) | |
27 | |
25 // TICK should be 8 or less (8 untested). all timers need | 28 // TICK should be 8 or less (8 untested). all timers need |
26 // to be a multiple. | 29 // to be a multiple. |
27 | 30 |
28 #define TICK 6 | 31 #define TICK 6 |
29 // we have 1024 prescaler, 32768 crystal. | 32 // we have 1024 prescaler, 32768 crystal. |
30 #define SLEEP_COMPARE (32*TICK-1) | 33 #define SLEEP_COMPARE (32*TICK-1) |
31 | 34 |
32 #define VALUE_NOSENSOR 0x07D0 // 125 degrees | 35 #define VALUE_NOSENSOR 0x07D0 // 125 degrees |
33 #define VALUE_BROKEN 0x07D1 // 125.0625 | 36 #define VALUE_BROKEN 0x07D1 // 125.0625 |
34 | 37 |
38 #define FRIDGE_AIR_MIN_RANGE 3 | |
39 #define FRIDGE_AIR_MAX_RANGE 3 | |
40 #define OVERSHOOT_SCALE 1 | |
41 | |
35 #define BAUD 19200 | 42 #define BAUD 19200 |
36 #define UBRR ((F_CPU)/8/(BAUD)-1) | 43 #define UBRR ((F_CPU)/8/(BAUD)-1) |
37 | 44 |
38 #define PORT_LED PORTC | 45 #define PORT_LED PORTC |
39 #define DDR_LED DDRC | 46 #define DDR_LED DDRC |
47 #define DDR_FRIDGE DDRD | 54 #define DDR_FRIDGE DDRD |
48 #define PIN_FRIDGE PD6 | 55 #define PIN_FRIDGE PD6 |
49 | 56 |
50 // total amount of 16bit values available for measurements. | 57 // total amount of 16bit values available for measurements. |
51 // adjust emperically, be sure to allow enough stack space too | 58 // adjust emperically, be sure to allow enough stack space too |
52 #define TOTAL_MEASUREMENTS 840 | 59 #define TOTAL_MEASUREMENTS 800 |
53 | 60 |
54 // each sensor slot uses 8 bytes | 61 // each sensor slot uses 8 bytes |
55 #define MAX_SENSORS 6 | 62 #define MAX_SENSORS 6 |
56 | 63 |
57 // fixed at 8, have a shorter name | 64 // fixed at 8, have a shorter name |
73 static uint16_t measure_wake = 61; // not a divisor of comms_wake | 80 static uint16_t measure_wake = 61; // not a divisor of comms_wake |
74 static uint16_t comms_wake = 600; | 81 static uint16_t comms_wake = 600; |
75 static uint8_t wake_secs = 30; | 82 static uint8_t wake_secs = 30; |
76 // decidegrees | 83 // decidegrees |
77 static int16_t fridge_setpoint = 180; // 18.0ºC | 84 static int16_t fridge_setpoint = 180; // 18.0ºC |
78 static int16_t fridge_difference = 5; // 0.5ºC | 85 static int16_t fridge_difference = 3; // 0.3ºC |
79 static uint16_t fridge_delay = 600; // seconds | 86 static uint16_t fridge_delay = 600; // seconds |
80 | 87 |
81 // ---- Atomic guards required accessing these variables | 88 // ---- Atomic guards required accessing these variables |
89 // clock_epoch in seconds | |
82 static uint32_t clock_epoch; | 90 static uint32_t clock_epoch; |
83 static uint16_t comms_count; | 91 static uint16_t comms_count; |
84 static uint16_t measure_count; | 92 static uint16_t measure_count; |
85 // ---- End atomic guards required | 93 // ---- End atomic guards required |
86 | 94 |
115 static uint8_t sensor_id[MAX_SENSORS][ID_LEN]; | 123 static uint8_t sensor_id[MAX_SENSORS][ID_LEN]; |
116 | 124 |
117 static int16_t last_fridge = DS18X20_INVALID_DECICELSIUS; | 125 static int16_t last_fridge = DS18X20_INVALID_DECICELSIUS; |
118 static int16_t last_wort = DS18X20_INVALID_DECICELSIUS; | 126 static int16_t last_wort = DS18X20_INVALID_DECICELSIUS; |
119 static struct epoch_ticks fridge_off_clock = {0}; | 127 static struct epoch_ticks fridge_off_clock = {0}; |
128 static struct epoch_ticks fridge_on_clock = {0}; | |
120 | 129 |
121 int uart_putchar(char c, FILE *stream); | 130 int uart_putchar(char c, FILE *stream); |
122 static void long_delay(int ms); | 131 static void long_delay(int ms); |
123 static void blink(); | 132 static void blink(); |
124 static uint16_t adc_vcc(); | 133 static uint16_t adc_vcc(); |
572 { | 581 { |
573 printf_P(PSTR("Bad fridge value %f\n"), new_f); | 582 printf_P(PSTR("Bad fridge value %f\n"), new_f); |
574 return; | 583 return; |
575 } | 584 } |
576 | 585 |
586 int16_t old_setpoint = fridge_setpoint; | |
587 | |
577 fridge_setpoint = new_f * 10; | 588 fridge_setpoint = new_f * 10; |
578 bool written = set_initial_eeprom(); | 589 bool written = set_initial_eeprom(); |
579 if (!written) | 590 if (!written) |
580 { | 591 { |
581 ATOMIC_BLOCK(ATOMIC_RESTORESTATE) | 592 if (old_setpoint != fridge_setpoint) |
582 { | 593 { |
583 eeprom_write(fridge_setpoint, fridge_setpoint); | 594 ATOMIC_BLOCK(ATOMIC_RESTORESTATE) |
584 } | 595 { |
585 } | 596 eeprom_write(fridge_setpoint, fridge_setpoint); |
586 printf_P(PSTR("new fridge %.1fº\n"), fridge_setpoint / 10.0f); | 597 } |
598 } | |
599 } | |
600 printf_P(PSTR("old fridge %.1fº new fridge %.1fº\n"), | |
601 old_setpoint / 10.0f, fridge_setpoint / 10.0f); | |
587 } | 602 } |
588 | 603 |
589 static void | 604 static void |
590 cmd_set_fridge_difference(char *params) | 605 cmd_set_fridge_difference(char *params) |
591 { | 606 { |
812 static void | 827 static void |
813 do_fridge() | 828 do_fridge() |
814 { | 829 { |
815 struct epoch_ticks now; | 830 struct epoch_ticks now; |
816 get_epoch_ticks(&now); | 831 get_epoch_ticks(&now); |
817 uint16_t delay_delta = now.ticks - fridge_off_clock.ticks; | 832 uint16_t off_time = now.ticks - fridge_off_clock.ticks; |
818 if (delay_delta < fridge_delay) | 833 bool wort_valid = last_wort != DS18X20_INVALID_DECICELSIUS; |
834 bool fridge_valid = last_fridge != DS18X20_INVALID_DECICELSIUS; | |
835 | |
836 int16_t wort_max = fridge_setpoint + fridge_difference; | |
837 int16_t wort_min = fridge_setpoint; | |
838 | |
839 // the fridge min only applies when the wort is in the desired range. | |
840 int16_t fridge_min = fridge_setpoint - FRIDGE_AIR_MIN_RANGE; | |
841 int16_t fridge_max = fridge_setpoint + FRIDGE_AIR_MAX_RANGE; | |
842 | |
843 uint8_t fridge_on = PORT_FRIDGE & _BV(PIN_FRIDGE); | |
844 printf_P(PSTR("last_wort %hd (%hd, %hd), last_fridge %hd (%hd, %hd), setpoint %hd, diff %hd, fridge_on %d\n"), | |
845 last_wort, wort_min, wort_max, | |
846 fridge_setpoint, fridge_min, fridge_max, | |
847 fridge_difference, fridge_on); | |
848 | |
849 if (off_time < fridge_delay) | |
819 { | 850 { |
820 printf_P(PSTR("waiting for fridge delay current %hu, wait %hu\n"), | 851 printf_P(PSTR("waiting for fridge delay current %hu, wait %hu\n"), |
821 delay_delta, fridge_delay); | 852 off_time, fridge_delay); |
822 return; | 853 return; |
823 } | 854 } |
824 | 855 |
825 if (last_wort == DS18X20_INVALID_DECICELSIUS) | 856 |
826 { | |
827 // can't really do much sensible.... alert perhaps? | |
828 printf_P(PSTR("Bad last wort!\n")); | |
829 need_comms = 1; | |
830 return; | |
831 } | |
832 | |
833 int16_t wort_delta = last_wort - fridge_setpoint; | |
834 uint8_t fridge_on = PORT_FRIDGE & _BV(PIN_FRIDGE); | |
835 printf_P(PSTR("last_wort %hd, setpoint %hd, delta %hd, fridge_on %d\n"), | |
836 last_wort, fridge_setpoint, wort_delta, fridge_on); | |
837 if (fridge_on) | 857 if (fridge_on) |
838 { | 858 { |
839 if (last_wort <= fridge_setpoint) | 859 bool turn_off = false; |
860 uint16_t on_time = now.ticks - fridge_on_clock.ticks; | |
861 | |
862 // *10 for decicelcius | |
863 uint16_t overshoot = OVERSHOOT_SCALE * 10.0f * MAX(3600, on_time) / 3600.0; | |
864 | |
865 // wort has cooled enough. will probably cool a bit more by itself | |
866 if (wort_valid && (last_wort-overshoot) <= fridge_setpoint) | |
867 { | |
868 printf_P("wort has cooled enough, overshoot %hu\n", overshoot); | |
869 turn_off = true; | |
870 } | |
871 | |
872 // fridge is much cooler than wort | |
873 if ((last_wort < wort_max || !wort_valid) && | |
874 fridge_valid && last_fridge < fridge_min) | |
875 { | |
876 printf_P("fridge is too cold\n"); | |
877 turn_off = true; | |
878 } | |
879 | |
880 if (turn_off) | |
840 { | 881 { |
841 // too cold, turn off | 882 // too cold, turn off |
842 printf_P(PSTR("Turning fridge off\n")); | 883 printf_P(PSTR("Turning fridge off\n")); |
843 PORT_FRIDGE &= ~_BV(PIN_FRIDGE); | 884 PORT_FRIDGE &= ~_BV(PIN_FRIDGE); |
844 fridge_off_clock = now; | 885 fridge_off_clock = now; |
845 } | 886 } |
846 } | 887 } |
847 else | 888 else |
848 { | 889 { |
849 if (wort_delta > fridge_difference) | 890 bool turn_on = false; |
891 | |
892 if (wort_valid && last_wort >= wort_max) | |
893 { | |
894 printf_P("wort is too hot\n"); | |
895 turn_on = true; | |
896 } | |
897 | |
898 if ((last_wort > wort_min || !wort_valid) && | |
899 (fridge_valid && last_fridge > fridge_setpoint)) | |
900 { | |
901 printf_P("fridge is too hot\n"); | |
902 turn_on = true; | |
903 } | |
904 | |
905 if (turn_on) | |
850 { | 906 { |
851 // too hot, turn on | 907 // too hot, turn on |
852 printf_P(PSTR("Turning fridge on\n")); | 908 printf_P(PSTR("Turning fridge on\n")); |
853 PORT_FRIDGE |= _BV(PIN_FRIDGE); | 909 PORT_FRIDGE |= _BV(PIN_FRIDGE); |
910 fridge_on_clock = now; | |
854 } | 911 } |
855 } | 912 } |
856 } | 913 } |
857 | 914 |
858 static void | 915 static void |
887 } | 944 } |
888 set_measurement(s, n_measurements, reading); | 945 set_measurement(s, n_measurements, reading); |
889 | 946 |
890 if (memcmp(sensor_id[s], fridge_id, sizeof(fridge_id)) == 0) | 947 if (memcmp(sensor_id[s], fridge_id, sizeof(fridge_id)) == 0) |
891 { | 948 { |
892 last_fridge = ds18b20_raw16_to_decicelsius(reading);; | 949 last_fridge = ds18b20_raw16_to_decicelsius(reading); |
893 } | 950 } |
894 if (memcmp(sensor_id[s], wort_id, sizeof(wort_id)) == 0) | 951 if (memcmp(sensor_id[s], wort_id, sizeof(wort_id)) == 0) |
895 { | 952 { |
896 last_wort = ds18b20_raw16_to_decicelsius(reading);; | 953 last_wort = ds18b20_raw16_to_decicelsius(reading); |
897 } | 954 } |
898 } | 955 } |
899 | 956 |
900 n_measurements++; | 957 n_measurements++; |
901 } | 958 } |