Guest User

Untitled

a guest
Jul 6th, 2018
66
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 12.93 KB | None | 0 0
  1. #include <DallasTemperature.h>
  2. #include <EEPROM.h>
  3. #include <LiquidCrystal.h>
  4. #include <OneWire.h>
  5.  
  6. const String welcome_line_1 = " Welcome to 3FREAKS";
  7. const String welcome_line_2 = " Freak Responsibily!";
  8. const unsigned int    welcome_delay  = 2; //seconds
  9. const String stats_header   = "   CURRENT  TEMPS";
  10. const String set_header = "      SET MENU";
  11.  
  12. const unsigned int menu_button_pin  = 21;
  13. const unsigned int exit_button_pin  = 20;
  14. const unsigned int left_button_pin  = 19;
  15. const unsigned int right_button_pin = 18;
  16.  
  17. const unsigned int tank_a_sensor_pin = 5;
  18. OneWire one_wire_a(tank_a_sensor_pin);
  19. DallasTemperature sensors_a(&one_wire_a);
  20.  
  21. const unsigned int tank_b_sensor_pin = 4;
  22. OneWire one_wire_b(tank_b_sensor_pin);
  23. DallasTemperature sensors_b(&one_wire_b);
  24.  
  25. const unsigned int tank_c_sensor_pin = 3;
  26. OneWire one_wire_c(tank_c_sensor_pin);
  27. DallasTemperature sensors_c(&one_wire_c);
  28.  
  29. float last_temp_on_screen = 39;
  30.  
  31. const unsigned int valve_a_enable_pin = 0;
  32. const unsigned int valve_b_enable_pin = 0;
  33. const unsigned int valve_c_enable_pin = 0;
  34.  
  35. const unsigned int rs = 38;
  36. const unsigned int en = 37;
  37. const unsigned int d4 = 36;
  38. const unsigned int d5 = 35;
  39. const unsigned int d6 = 34;
  40. const unsigned int d7 = 33;
  41. LiquidCrystal lcd(rs, en, d4, d5, d6, d7);
  42.  
  43. enum Display_states {
  44.   STATS,
  45.   MAIN_MENU,
  46.   HIGHLIGHT_TEMP_A,
  47.   HIGHLIGHT_TEMP_B,
  48.   HIGHLIGHT_TEMP_C,
  49.   SET_TEMP_A,
  50.   SET_TEMP_B,
  51.   SET_TEMP_C
  52. };
  53. Display_states display_state = STATS;
  54.  
  55. const float default_temp = 38.0;
  56. struct config_t {
  57.   float tank_a_set_temp;
  58.   float tank_b_set_temp;
  59.   float tank_c_set_temp;
  60. } program_config;
  61.  
  62. struct temp_state_t {
  63.   long last_temp_time;
  64.   float tank_a;
  65.   float tank_b;
  66.   float tank_c;
  67. } current_temps;
  68.  
  69. /*
  70.  *
  71.  *
  72.  * EEPROM HELPERS
  73.  *
  74.  *
  75. */
  76. template <class T> int eeprom_generic_write(int ee, const T& value) {
  77.   const byte* p = (const byte*)(const void*)&value;
  78.   int i;
  79.   for (i=0; i < sizeof(value); i++) {
  80.      EEPROM.write(ee++, *p++);
  81.   }
  82.   return i; //How much we've written
  83. }
  84.  
  85. template <class T> int eeprom_generic_read(int ee, T& value) {
  86.   byte* p = (byte*)(void*)&value;
  87.   int i;
  88.   for (i=0; i< sizeof(value); i++) {
  89.     *p++ = EEPROM.read(ee++);
  90.   }
  91.   return i; //How much we've read
  92. }
  93.  
  94. /*
  95.  *
  96.  *
  97.  * HELPERS
  98.  *
  99.  *
  100. */
  101.  
  102. // Tricky way to reset through code only
  103. void(*die) (void) = 0;
  104.  
  105. char uppercase (char i) {
  106.  //Assumes ASCII
  107.  return i & ~(0x20);
  108. }
  109.  
  110. //We have to debounce our inputs
  111. //Damn physics...
  112. long last_interrupt_time = millis();
  113. bool is_valid_interrupt() {
  114.   long this_interrupt_time = millis();
  115.   if (this_interrupt_time - last_interrupt_time > 200) {
  116.     last_interrupt_time = millis();
  117.     return true;
  118.   }
  119.   return false;
  120. }
  121.  
  122. /*
  123.  *
  124.  *
  125.  * INIT CODE
  126.  *
  127.  *
  128. */
  129. void setup() {
  130.   Serial.begin(9600);
  131.   lcd.begin(20, 4);
  132.   print_welcome_message();
  133.  
  134.   eeprom_generic_read(0, program_config);
  135.  
  136. /*
  137.  *
  138.  * Aurdino Mega Interupts:
  139.  *    Int | Pin
  140.  *   -----------
  141.  *     0     2
  142.  *     1     3
  143.  *     2     21
  144.  *     3     20
  145.  *     4     19
  146.  *     5     18
  147.  *
  148. */
  149.   attachInterrupt(2, handle_menu_button_ISR,  RISING);
  150.   attachInterrupt(3, handle_exit_button_ISR,  RISING);
  151.   attachInterrupt(4, handle_left_button_ISR,  RISING);
  152.   attachInterrupt(5, handle_right_button_ISR, RISING);
  153.  
  154.   sensors_a.begin();
  155.   sensors_b.begin();
  156.   sensors_c.begin();
  157.  
  158.   pinMode(valve_a_enable_pin, OUTPUT);
  159.   pinMode(valve_b_enable_pin, OUTPUT);
  160.   pinMode(valve_c_enable_pin, OUTPUT);
  161.  
  162.   delay(welcome_delay * 1000);
  163.   lcd.clear();
  164. }
  165.  
  166. /*
  167.  *
  168.  *
  169.  * GLYCOL CONTROL
  170.  *
  171.  *
  172. */
  173.  
  174. void open_valve(char tank) {
  175.   switch (tank) {
  176.     case 'a':
  177.       digitalWrite(valve_a_enable_pin, HIGH);
  178.       break;
  179.     case 'b':
  180.       digitalWrite(valve_b_enable_pin, HIGH);
  181.       break;
  182.     case 'c':
  183.       digitalWrite(valve_c_enable_pin, HIGH);
  184.       break;
  185.   }
  186. }
  187.  
  188. void close_valve(char tank) {
  189.   switch (tank) {
  190.     case 'a':
  191.       digitalWrite(valve_a_enable_pin, LOW);
  192.       break;
  193.     case 'b':
  194.       digitalWrite(valve_b_enable_pin, LOW);
  195.       break;
  196.     case 'c':
  197.       digitalWrite(valve_c_enable_pin, LOW);
  198.       break;
  199.   }
  200. }
  201.  
  202. void open_valves_if_needed() {
  203.   if (current_temps.tank_a < program_config.tank_a_set_temp) {
  204.     open_valve('a');
  205.   }
  206.  
  207.   if (current_temps.tank_b < program_config.tank_b_set_temp) {
  208.     open_valve('b');
  209.   }
  210.  
  211.   if (current_temps.tank_c < program_config.tank_c_set_temp) {
  212.     open_valve('c');
  213.   }
  214. }
  215.  
  216. void close_valves_if_needed() {
  217.   if (current_temps.tank_a > program_config.tank_a_set_temp) {
  218.     close_valve('a');
  219.   }
  220.  
  221.   if (current_temps.tank_b > program_config.tank_b_set_temp) {
  222.     close_valve('b');
  223.   }
  224.  
  225.   if (current_temps.tank_c > program_config.tank_c_set_temp) {
  226.     close_valve('c');
  227.   }
  228. }
  229.  
  230. /*
  231.  *
  232.  *
  233.  * TEMPRATURE LOGIC
  234.  *
  235.  *
  236. */
  237.  
  238. bool take_temps_if_needed() {
  239.   long current_time = millis();
  240.   if (current_time - current_temps.last_temp_time  > 1000) {// 1 second for now
  241.     float tempC;
  242.     float tempF;
  243.  
  244.     sensors_a.requestTemperatures();
  245.     tempC = sensors_a.getTempCByIndex(0);
  246.     tempF = sensors_a.toFahrenheit(tempC);
  247.     current_temps.tank_a = tempF;
  248.  
  249.    
  250.     sensors_b.requestTemperatures();
  251.     tempC = sensors_b.getTempCByIndex(0);
  252.     tempF = sensors_b.toFahrenheit(tempC);
  253.     current_temps.tank_b = tempF;
  254.  
  255.     sensors_c.requestTemperatures();
  256.     tempC = sensors_c.getTempCByIndex(0);
  257.     tempF = sensors_c.toFahrenheit(tempC);
  258.     current_temps.tank_c = tempF;
  259.    
  260.     return true;
  261.   }
  262.   return false;
  263. }
  264.  
  265. double get_tank_temp(char tank) {
  266.   float temp = 0;
  267.  
  268.   switch (tank) {
  269.     case 'a':
  270.       temp = current_temps.tank_a;
  271.       break;
  272.     case 'b':
  273.       temp = current_temps.tank_b;
  274.       break;
  275.     case 'c':
  276.       temp = current_temps.tank_c;
  277.       break;
  278.   }
  279.  
  280.   return temp;
  281. }
  282.  
  283. void set_new_temp(char tank, float new_temp) {
  284.   switch (tank) {
  285.   case 'a':
  286.     program_config.tank_a_set_temp = new_temp;
  287.     eeprom_generic_write(0, program_config);
  288.     break;
  289.   case 'b':
  290.     program_config.tank_b_set_temp = new_temp;
  291.     eeprom_generic_write(0, program_config);
  292.     break;
  293.   case 'c':
  294.     program_config.tank_c_set_temp = new_temp;
  295.     eeprom_generic_write(0, program_config);
  296.     break;
  297.   default:
  298.     // We should never get here
  299.     die();
  300.   }
  301.   return;
  302. }
  303.  
  304. double get_set_temp(char tank){
  305.   double temp = 0;
  306.  
  307.   switch (tank) {
  308.   case 'a':
  309.     temp = program_config.tank_a_set_temp;
  310.     break;
  311.   case 'b':
  312.     temp = program_config.tank_b_set_temp;
  313.     break;
  314.   case 'c':
  315.     temp = program_config.tank_c_set_temp;
  316.     break;
  317.   default:
  318.     // We should never get here
  319.     die();
  320.   }
  321.  
  322.   return temp;
  323. }
  324.  
  325. /*
  326.  *
  327.  *
  328.  * VIEWS
  329.  *
  330.  *
  331. */
  332.  
  333. void print_welcome_message() {
  334.   lcd.clear();
  335.   lcd.setCursor(0,1);
  336.   lcd.print(welcome_line_1);
  337.   lcd.setCursor(0,2);
  338.   lcd.print(welcome_line_2);
  339. }
  340.  
  341. void print_stats() {
  342.   lcd.clear();
  343.   int start_line = 0;
  344.   lcd.setCursor(0, start_line);
  345.   lcd.print(stats_header);
  346.   start_line++;
  347.  
  348.   lcd.setCursor(0, start_line);
  349.   lcd.print("A       B       C");
  350.   start_line++;
  351.  
  352.   lcd.setCursor(0, start_line);
  353.   lcd.print(get_tank_temp('a'), 1);
  354.  
  355.   lcd.setCursor(8, start_line);
  356.   lcd.print(get_tank_temp('b'), 1);
  357.  
  358.   lcd.setCursor(16,start_line);
  359.   lcd.print(get_tank_temp('c'), 1);
  360.  
  361.   lcd.setCursor(16,3);
  362.   lcd.print("Menu");
  363. }
  364.  
  365. void print_main_menu() {
  366.   lcd.clear();
  367.   int start_line = 0;
  368.   lcd.setCursor(0,start_line);
  369.   lcd.print(set_header);
  370.   start_line++;
  371.  
  372.   lcd.setCursor(0, start_line);
  373.   lcd.print("A       B       C");
  374.   start_line++;
  375.  
  376.   lcd.setCursor(0, start_line);
  377.   lcd.print(get_set_temp('a'), 1);
  378.  
  379.   lcd.setCursor(8, start_line);
  380.   lcd.print(get_set_temp('b'), 1);
  381.  
  382.   lcd.setCursor(16,start_line);
  383.   lcd.print(get_set_temp('c'), 1);
  384.  
  385.   lcd.setCursor(0,3);
  386.   lcd.print("Exit");
  387. }
  388.  
  389. void print_highlight_temp(char tank) {
  390.   lcd.clear();
  391.   lcd.setCursor(0,0);
  392.  
  393.   double set_temp = get_set_temp(tank);
  394.   last_temp_on_screen = set_temp;
  395.  
  396.   String output = "Tank ";
  397.   output.concat(uppercase(tank));
  398.   output.concat(" Is Set To: ");
  399.   lcd.print(output);
  400.  
  401.   lcd.setCursor(3,1);
  402.   lcd.print(set_temp, 1);
  403.  
  404.   lcd.setCursor(0,3);
  405.   lcd.print("Exit          Change");
  406.  
  407.   return;
  408. }
  409.  
  410. void print_set_temp(char tank) {
  411.   lcd.clear();
  412.   lcd.setCursor(0,0);
  413.  
  414.   String output = "Set Tank ";
  415.   output.concat(uppercase(tank));
  416.   output.concat(" To: ");
  417.   lcd.print(output);
  418.  
  419.  
  420.   lcd.setCursor(0,1);
  421.   lcd.print("<<<");
  422.  
  423.   lcd.setCursor(8,1);
  424.   lcd.print(last_temp_on_screen, 1);
  425.  
  426.   lcd.setCursor(17,1);
  427.   lcd.print(">>>");
  428.  
  429.   lcd.setCursor(0,3);
  430.   lcd.print("Exit             SET");
  431.  
  432.   return;
  433. }
  434.  
  435.  
  436. /*
  437.  *
  438.  *
  439.  * INPUT HANDLERS
  440.  *
  441.  *
  442. */
  443.  
  444. void handle_menu_button_ISR() {
  445.   if (!is_valid_interrupt())
  446.     return;
  447.   Serial.println("menu depressed");
  448.  
  449.   switch (display_state) {
  450.     case STATS:
  451.       display_state = MAIN_MENU;
  452.       break;
  453.     case MAIN_MENU:
  454.       break;
  455.     case HIGHLIGHT_TEMP_A:
  456.       last_temp_on_screen = get_set_temp('a');
  457.       display_state = SET_TEMP_A;
  458.       break;
  459.     case HIGHLIGHT_TEMP_B:
  460.       last_temp_on_screen = get_set_temp('b');
  461.       display_state = SET_TEMP_B;
  462.       break;
  463.     case HIGHLIGHT_TEMP_C:
  464.       last_temp_on_screen = get_set_temp('c');
  465.       display_state = SET_TEMP_C;
  466.       break;
  467.     case SET_TEMP_A:
  468.       set_new_temp('a', last_temp_on_screen);
  469.       display_state = HIGHLIGHT_TEMP_A;
  470.       break;
  471.     case SET_TEMP_B:
  472.       set_new_temp('b', last_temp_on_screen);
  473.       display_state = HIGHLIGHT_TEMP_B;
  474.       break;
  475.     case SET_TEMP_C:
  476.       set_new_temp('c', last_temp_on_screen);
  477.       display_state = HIGHLIGHT_TEMP_C;
  478.       break;
  479.     default:
  480.       // Should never get here
  481.       die();
  482.   }
  483.   return;
  484.  
  485. }
  486.  
  487. void handle_exit_button_ISR() {
  488.   if (!is_valid_interrupt())
  489.     return;
  490.  
  491.   switch (display_state) {
  492.     case STATS:
  493.       break;
  494.     case MAIN_MENU:
  495.       display_state = STATS;
  496.       break;
  497.     case HIGHLIGHT_TEMP_A:
  498.       display_state = STATS;
  499.       break;
  500.     case HIGHLIGHT_TEMP_B:
  501.       display_state = STATS;
  502.       break;
  503.     case HIGHLIGHT_TEMP_C:
  504.       display_state = STATS;
  505.       break;
  506.     case SET_TEMP_A:
  507.       display_state = HIGHLIGHT_TEMP_A;
  508.       break;
  509.     case SET_TEMP_B:
  510.       display_state = HIGHLIGHT_TEMP_B;
  511.       break;
  512.     case SET_TEMP_C:
  513.       display_state = HIGHLIGHT_TEMP_C;
  514.       break;
  515.     default:
  516.       // Should never get here
  517.       die();
  518.   }
  519.   return;
  520. }
  521.  
  522. void handle_left_button_ISR() {
  523.   if (!is_valid_interrupt())
  524.     return;
  525.  
  526.   switch (display_state) {
  527.     case STATS:
  528.       break;
  529.     case MAIN_MENU:
  530.       display_state = HIGHLIGHT_TEMP_C;
  531.       break;
  532.     case HIGHLIGHT_TEMP_A:
  533.       display_state = MAIN_MENU;
  534.       break;
  535.     case HIGHLIGHT_TEMP_B:
  536.       display_state = HIGHLIGHT_TEMP_A;
  537.       break;
  538.     case HIGHLIGHT_TEMP_C:
  539.       display_state = HIGHLIGHT_TEMP_B;
  540.       break;
  541.     case SET_TEMP_A:
  542.       last_temp_on_screen-=0.1;
  543.       break;
  544.     case SET_TEMP_B:
  545.       last_temp_on_screen-=0.1;
  546.       break;
  547.     case SET_TEMP_C:
  548.       last_temp_on_screen-=0.1;
  549.       break;
  550.     default:
  551.       // Should never get here
  552.       die();
  553.   }
  554.   return;
  555. }
  556.  
  557. void handle_right_button_ISR() {
  558.   if (!is_valid_interrupt())
  559.     return;
  560.  
  561.   switch (display_state) {
  562.     case STATS:
  563.       break;
  564.     case MAIN_MENU:
  565.       display_state = HIGHLIGHT_TEMP_A;
  566.       break;
  567.     case HIGHLIGHT_TEMP_A:
  568.       display_state = HIGHLIGHT_TEMP_B;
  569.       break;
  570.     case HIGHLIGHT_TEMP_B:
  571.       display_state = HIGHLIGHT_TEMP_C;
  572.       break;
  573.     case HIGHLIGHT_TEMP_C:
  574.       display_state = MAIN_MENU;
  575.       break;
  576.     case SET_TEMP_A:
  577.       last_temp_on_screen+=0.1;
  578.       break;
  579.     case SET_TEMP_B:
  580.       last_temp_on_screen+=0.1;
  581.       break;
  582.     case SET_TEMP_C:
  583.       last_temp_on_screen+=0.1;
  584.       break;
  585.     default:
  586.       // Should never get here
  587.       die();
  588.   }
  589.   return;
  590. }
  591.  
  592. /*
  593.  *
  594.  *
  595.  * MAIN
  596.  *
  597.  *
  598. */
  599. void loop() {
  600.  
  601.   if (take_temps_if_needed()) {
  602.    open_valves_if_needed();
  603.    close_valves_if_needed();
  604.   }
  605.  
  606.   switch (display_state) {
  607.     case STATS:
  608.     print_stats();
  609.     break;
  610.   case MAIN_MENU:
  611.     print_main_menu();
  612.     break;
  613.   case HIGHLIGHT_TEMP_A:
  614.     lcd.setCursor(0,0);
  615.     print_highlight_temp('a');
  616.     break;
  617.   case HIGHLIGHT_TEMP_B:
  618.     lcd.setCursor(0,0);
  619.     print_highlight_temp('b');
  620.     break;
  621.   case HIGHLIGHT_TEMP_C:
  622.     lcd.setCursor(0,0);
  623.     print_highlight_temp('c');
  624.     break;
  625.   case SET_TEMP_A:
  626.     lcd.setCursor(0,0);
  627.     print_set_temp('a');
  628.     break;
  629.   case SET_TEMP_B:
  630.     lcd.setCursor(0,0);
  631.     print_set_temp('b');
  632.     break;
  633.   case SET_TEMP_C:
  634.     lcd.setCursor(0,0);
  635.     print_set_temp('c');
  636.     break;
  637.   default:
  638.     //If we got here, then shit went really sideways somewhere
  639.     //We should just reset the arduino and let it sort itself out
  640.     lcd.clear();
  641.     lcd.print("ERROR: Unhandled State");
  642.     delay(1000);
  643.     die();
  644.   }
  645.   delay(50);
  646. }
Advertisement
Add Comment
Please, Sign In to add comment