comparison main.c @ 420:d386bbab85cf

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 b73ea78317dc
children 30c2c3341a4a
comparison
equal deleted inserted replaced
419:a60a015732ea 420:d386bbab85cf
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 }