Mercurial > templog
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 |