comparison main.c @ 130:66d5e15f40d0

simplify, only use the fridge temp if the wort's busted
author Matt Johnston <matt@ucc.asn.au>
date Sun, 14 Oct 2012 21:46:24 +0800
parents fbb076bf2a59
children 405785632c78
comparison
equal deleted inserted replaced
128:fbb076bf2a59 130:66d5e15f40d0
34 34
35 #define VALUE_NOSENSOR 0x07D0 // 125 degrees 35 #define VALUE_NOSENSOR 0x07D0 // 125 degrees
36 #define VALUE_BROKEN 0x07D1 // 125.0625 36 #define VALUE_BROKEN 0x07D1 // 125.0625
37 37
38 // ranges are in decicelcius 38 // ranges are in decicelcius
39 #define FRIDGE_AIR_MIN_RANGE 30 39 #define OVERSHOOT_DELAY 1800 // 30 mins
40 #define FRIDGE_AIR_MAX_RANGE 30 40 #define OVERSHOOT_FACTOR 1
41 #define OVERSHOOT_SCALE 0.5 41 #define WORT_INVALID_TIME 900 // 15 mins
42 // fridge min/max are only used if the wort sensor is invalid
43 #define FRIDGE_AIR_MIN_RANGE 40 // 4º
44 #define FRIDGE_AIR_MAX_RANGE 40 // 4º
42 45
43 #define BAUD 19200 46 #define BAUD 19200
44 #define UBRR ((F_CPU)/8/(BAUD)-1) 47 #define UBRR ((F_CPU)/8/(BAUD)-1)
45 48
46 #define PORT_LED PORTC 49 #define PORT_LED PORTC
125 128
126 static int16_t last_fridge = DS18X20_INVALID_DECICELSIUS; 129 static int16_t last_fridge = DS18X20_INVALID_DECICELSIUS;
127 static int16_t last_wort = DS18X20_INVALID_DECICELSIUS; 130 static int16_t last_wort = DS18X20_INVALID_DECICELSIUS;
128 static struct epoch_ticks fridge_off_clock = {0}; 131 static struct epoch_ticks fridge_off_clock = {0};
129 static struct epoch_ticks fridge_on_clock = {0}; 132 static struct epoch_ticks fridge_on_clock = {0};
133 static struct epoch_ticks wort_valid_clock = {0};
130 134
131 int uart_putchar(char c, FILE *stream); 135 int uart_putchar(char c, FILE *stream);
132 static void long_delay(int ms); 136 static void long_delay(int ms);
133 static void blink(); 137 static void blink();
134 static uint16_t adc_vcc(); 138 static uint16_t adc_vcc();
832 static void 836 static void
833 do_fridge() 837 do_fridge()
834 { 838 {
835 struct epoch_ticks now; 839 struct epoch_ticks now;
836 get_epoch_ticks(&now); 840 get_epoch_ticks(&now);
837 uint16_t off_time = now.ticks - fridge_off_clock.ticks; 841 uint32_t off_time = now.ticks - fridge_off_clock.ticks;
838 bool wort_valid = last_wort != DS18X20_INVALID_DECICELSIUS; 842 bool wort_valid = last_wort != DS18X20_INVALID_DECICELSIUS;
839 bool fridge_valid = last_fridge != DS18X20_INVALID_DECICELSIUS; 843 bool fridge_valid = last_fridge != DS18X20_INVALID_DECICELSIUS;
840 844
841 int16_t wort_max = fridge_setpoint + fridge_difference; 845 int16_t wort_max = fridge_setpoint + fridge_difference;
842 int16_t wort_min = fridge_setpoint; 846 int16_t wort_min = fridge_setpoint;
843 847
844 // the fridge min only applies when the wort is in the desired range. 848 // the fridge min/max only apply if the wort sensor is broken
845 int16_t fridge_min = fridge_setpoint - FRIDGE_AIR_MIN_RANGE; 849 int16_t fridge_min = fridge_setpoint - FRIDGE_AIR_MIN_RANGE;
846 int16_t fridge_max = fridge_setpoint + FRIDGE_AIR_MAX_RANGE; 850 int16_t fridge_max = fridge_setpoint + FRIDGE_AIR_MAX_RANGE;
847 851
848 uint8_t fridge_on = PORT_FRIDGE & _BV(PIN_FRIDGE); 852 uint8_t fridge_on = PORT_FRIDGE & _BV(PIN_FRIDGE);
849 printf_P(PSTR("last_wort %hd (%hd, %hd), last_fridge %hd (%hd, %hd), setpoint %hd, diff %hd, fridge_on %hu\n"), 853 printf_P(PSTR("last_wort %hd (%hd, %hd), last_fridge %hd (%hd, %hd), setpoint %hd, diff %hd, fridge_on %hhu\n"),
850 last_wort, wort_min, wort_max, 854 last_wort, wort_min, wort_max,
851 fridge_setpoint, fridge_min, fridge_max, 855 last_fridge, fridge_min, fridge_max,
852 fridge_difference, fridge_on); 856 fridge_setpoint, fridge_difference, fridge_on);
853 857
854 if (off_time < fridge_delay) 858 if (off_time < fridge_delay)
855 { 859 {
856 printf_P(PSTR("waiting for fridge delay current %hu, wait %hu\n"), 860 printf_P(PSTR("waiting for fridge delay current %hu, wait %hu\n"),
857 off_time, fridge_delay); 861 off_time, fridge_delay);
858 return; 862 return;
859 } 863 }
860 864
865 // handle failure of the wort sensor. if it is a short (intermittent?)
866 // failure we wait until it has been broken for a period of time
867 // (WORT_INVALID_TIME) before doing anything.
868 if (wort_valid)
869 {
870 wort_valid_clock = now;
871 }
872 else
873 {
874 printf_P(PSTR("wort sensor is invalid\n"));
875 uint32_t invalid_time = now.ticks - wort_valid_clock.ticks;
876 if (invalid_time < WORT_INVALID_TIME)
877 {
878 printf("only been invalid for %ld, waiting\n", invalid_time);
879 return;
880 }
881 }
882
883 if (!fridge_valid)
884 {
885 printf_P(PSTR("fridge sensor is invalid\n"));
886 }
861 887
862 if (fridge_on) 888 if (fridge_on)
863 { 889 {
864 bool turn_off = false; 890 bool turn_off = false;
865 uint16_t on_time = now.ticks - fridge_on_clock.ticks; 891 uint16_t on_time = now.ticks - fridge_on_clock.ticks;
866 892
867 // *10 for decicelcius 893 uint16_t overshoot = 0;
868 uint16_t overshoot = OVERSHOOT_SCALE * 10.0f * MIN(3600, on_time) / 3600.0; 894 if (on_time > 1800)
895 {
896 // *10.0f for decicelcius
897 overshoot = OVERSHOOT_FACTOR * 10.0f * MIN(3600, on_time) / 3600.0;
898 }
869 899
870 printf_P(PSTR("on_time %hu, overshoot %hu\n"), on_time, overshoot); 900 printf_P(PSTR("on_time %hu, overshoot %hu\n"), on_time, overshoot);
871 901
872 // wort has cooled enough. will probably cool a bit more by itself 902 // wort has cooled enough. will probably cool a bit more by itself
873 if (wort_valid && (last_wort-overshoot) <= fridge_setpoint) 903 if (wort_valid)
874 { 904 {
875 printf_P(PSTR("wort has cooled enough, overshoot %hu on_time %hu\n"), overshoot, on_time); 905 if ((last_wort - overshoot) < fridge_setpoint)
876 turn_off = true; 906 {
877 } 907 printf_P(PSTR("wort has cooled enough, overshoot %hu on_time %hu\n"), overshoot, on_time);
878 908 turn_off = true;
879 // fridge is much cooler than wort 909 }
880 if ((last_wort < wort_max || !wort_valid) && 910 }
881 fridge_valid && last_fridge < fridge_min) 911 else
882 { 912 {
883 printf_P(PSTR("fridge is too cold\n")); 913 if (fridge_valid && last_fridge < fridge_min)
884 turn_off = true; 914 {
915 printf_P(PSTR("fridge off fallback\n"));
916 turn_off = true;
917 }
885 } 918 }
886 919
887 if (turn_off) 920 if (turn_off)
888 { 921 {
889 // too cold, turn off 922 // too cold, turn off
894 } 927 }
895 else 928 else
896 { 929 {
897 bool turn_on = false; 930 bool turn_on = false;
898 931
899 if (wort_valid && last_wort >= wort_max) 932 if (wort_valid)
900 { 933 {
901 printf_P(PSTR("wort is too hot\n")); 934 if (last_wort >= wort_max)
902 turn_on = true; 935 {
903 } 936 printf_P(PSTR("wort is too hot\n"));
904 937 turn_on = true;
905 if ((fridge_valid && last_fridge > fridge_max)) 938 }
906 { 939 }
907 printf_P("fridge is max too hot\n"); 940 else
908 turn_on = true; 941 {
909 } 942 if (fridge_valid && last_fridge >= fridge_max)
910 943 {
911 944 printf_P(PSTR("fridge on fallback\n"));
912 if ((last_wort > wort_min || !wort_valid) && 945 turn_on = true;
913 (fridge_valid && last_fridge > fridge_setpoint)) 946 }
914 {
915 printf_P(PSTR("fridge is too hot\n"));
916 turn_on = true;
917 } 947 }
918 948
919 if (turn_on) 949 if (turn_on)
920 { 950 {
921 // too hot, turn on 951 // too hot, turn on