Advertisement
vulture2600

Thermostat RTC v4.0

Feb 13th, 2014
1,624
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 28.11 KB | None | 0 0
  1. /* Thermostat with Real Time Clock Module and web support using second Arduino with ethernet shield.
  2. This sketch takes temp readings from three temp sensors and a door sensor and decides when to turn the heat on or off.
  3. steve.a.mccluskey@gmail.com
  4.  
  5. This circuit uses a 2.04v analog reference by connecting the 3.3v pin to AREF through a 20k resistor. The internal 32k resistor creates a voltage divider.
  6. The TMP36 temp sensor puts out 1750mV @ 125 degrees Celsius and 100mV @ -40. Since our voltage tops out at 1.75V, using a lower analog reference voltage
  7. provides more resolution at the ADC.
  8.  
  9. To convert an anlog reading to C, we have to do some math:
  10. 0-2.04V over 1024 steps equals 1.992mV per step. At -40C, we should see 100mv, so we divide 100mV by 1.992 to get 50. This means at -40C, we
  11. should see 50 as an analog reading. At 125C the sensor puts out 1750mV, so 1750mV / 1.992 = 878. We then map an analog range of 50 to 878 to a
  12. Celsius range of -40 to 125: map(analogReading, 50, 878, -40, 125). See revision 2.8 for updated floating point math.
  13.  
  14. Revisions:
  15. V2.2: Web support using second arduino with ethernet shield. Master sends single char commands over serial and thermostat responds accordingly.
  16. V2.3: Added door and heater state to web page.
  17. V2.4: Added EEPROM functionality to save settings to resume on startup.
  18. V2.5: Added code to handle if one of the sensors is unplugged on the web page, 02/18/14.
  19. V2.6: Rewrote button polling, bottom line display and ReadTimeDate() with switch/cases; consolidated door logic, rewrote average functions. 02/19/14.
  20. V2.7: Added functionality to display negative temps down to -40. 02/20/14.
  21. V2.8: Removed averageC(), removed unneccesary lcd.setCursor()'s, fixed average() to correctly return negative temps, changed tempAvgC calculation,
  22.   sensorInterval variable added, C/F mode saved to EEPROM, tempHold limited to 12F minimum, getTemp() analog reading to tempC now uses floating point math and rounding. 03/02/14.
  23.   Changed average() to use floating point math as well. 03/03/14.
  24. V2.9: Changed how often ReadTimeDate() is called. 03/05/14.
  25. V3.0: Added daylight savings time option menu and functionality. 02/23/15.
  26. V3.1: Added doorState variable and only reads door once per loop instead of several times. 02/25/15.
  27. V3.2: Changed ReadTimeDate() to only initialize one string instead of three. Added heaterDelay variable. 02/27/15.
  28.  
  29. V4.0: Added One-Wire Temp sensor support for outdoor temps and getOneWireTemp(). Changed temp variables to temp1, temp2, temp3 from tempNear/Far/Out.
  30. Fixed closing parenthesis typo in getTemp(). Changed const uint8_t's to #define in pin declarations. Limited data[] to two slots in getOneWireTemp. 03/02/14.
  31.  
  32. Pin layout as follows:
  33. 0  : Hardware serial RX.
  34. 1  : Hardware serial TX.
  35. 2  : OneWire bus.
  36. 3 ~: Green LED.
  37. 4  :
  38. 5 ~: Yellow LED.
  39. 6 ~: Red LED.
  40. 7  : Door sensor.
  41. 8  : RTC CS.
  42. 9 ~: Heater relay.
  43. 10~:
  44. 11~: RTC MOSI.
  45. 12 : RTC MISO.
  46. 13 : RTC CLK
  47. A0 : Sensor 1.
  48. A1 : Sensor 2.
  49. A2 : Sensor 3.
  50. A3 :
  51. A4 : LCD shield.
  52. A5 : LCD shield.
  53.  
  54. Sketch outline:
  55. Libraries.
  56. Pin Declarations.
  57. Global Variables.
  58. setup().
  59. loop() {
  60.   Static variables.
  61.   Poll buttons.
  62.   Poll sensors.
  63.   Print avg/hold to first line.
  64.   Print menu to second line.
  65.   Door closed: switch/case for second line.
  66.   Door open: door open.
  67.   Heater on/off logic.
  68. }
  69. getTemp().
  70. getOneWireTemp().
  71. heaterOn().
  72. heaterOff().
  73. clearLine().
  74. average().
  75. RTC_init().
  76. ReadTimeDate().
  77. serialEvent().  
  78. */
  79.  
  80. #include <Wire.h>
  81. #include <Adafruit_MCP23017.h>
  82. #include <Adafruit_RGBLCDShield.h>
  83. #include <SPI.h>
  84. #include <EEPROM.h>
  85. #include <OneWire.h>
  86.  
  87. #define sensorInterval 150 //interval between temp sensor readings.
  88. #define heaterDelay 120000 //heater on or off for at least 2 min
  89.  
  90. Adafruit_RGBLCDShield lcd = Adafruit_RGBLCDShield();
  91.  
  92.  
  93. //pin declarations:
  94. #define oneWireBus 2 //OneWire bus.
  95. #define greenLed 3
  96. #define yellowLed 5
  97. #define redLed 6
  98. #define door 7
  99. #define cs 8
  100. #define relay 9
  101.  
  102. #define tempPin1 0
  103. #define tempPin2 1
  104. #define tempPin3 2
  105.  
  106. OneWire oneWire(oneWireBus);
  107. byte addr[8]; //OneWire temp sensor address.
  108.  
  109. //global variables:
  110. boolean celsius = EEPROM.read(5);
  111. boolean doorLineCleared = false;
  112. boolean daylightSavings = EEPROM.read(6);
  113. uint8_t tempHold = EEPROM.read(0); // read saved tempHold value from EEPROM.
  114. uint8_t tempReduction = EEPROM.read(1);
  115. uint8_t menu = EEPROM.read(4);
  116. int8_t temp1, temp2, temp3, tempOneWire, tempAvg; // variables to store temps.
  117. unsigned long heaterOnTime = 0, heaterOffTime = 0, currentTime = 0, lastReadingTime = 0, lastClockCheck = 0;
  118. uint8_t heaterState = 0;
  119. uint8_t doorState = 0;
  120. uint8_t reading = 0; //columns in matrix.
  121.  
  122. uint16_t val[3][10] = { //array to store analog reading values.
  123.   {0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
  124.   {0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
  125.   {0, 0, 0, 0, 0 ,0, 0, 0, 0, 0}
  126. }; //end val.
  127.  
  128. uint8_t hour;
  129. uint8_t eveningHour = EEPROM.read(3);
  130. uint8_t morningHour = EEPROM.read(2);
  131.  
  132. void setup() {
  133.   analogReference(EXTERNAL); //AREF = 2.04v.
  134.   pinMode(redLed, OUTPUT);
  135.   pinMode(greenLed, OUTPUT);
  136.   pinMode(yellowLed, OUTPUT);
  137.   pinMode(door, INPUT_PULLUP); //door pin is pulled to ground while door is closed.
  138.   pinMode(relay, OUTPUT);
  139.   pinMode(cs, OUTPUT);
  140.   Serial.begin(19200);
  141.   lcd.begin(16, 2);
  142.   lcd.setCursor(0, 0);
  143.   lcd.print(F("RTC Thermostat"));
  144.   lcd.setCursor(0, 1);
  145.   lcd.print(F("V. 4.0"));
  146.   RTC_init();
  147.   delay(1000);
  148.   lcd.clear();  
  149.   oneWire.search(addr); //get connected device's address.
  150. } //end setup().
  151.  
  152. void loop() {
  153.   uint8_t buttons = lcd.readButtons(); //MUST be in main loop. will not work if global.
  154.  
  155.   if (digitalRead(door) == HIGH) { //only read once per loop.
  156.     doorState = 1;
  157.   }
  158.   else {
  159.     doorState = 0;
  160.   }
  161.  
  162.   currentTime = millis();
  163.   String timeString;
  164.  
  165.   int8_t tempAvgC, temp1C, temp2C, temp3C, tempOneWireC;
  166.   float convF = (5.0 * (tempHold - 32)) / 9.0;
  167.   int8_t tempHoldC = round(convF);
  168.   int8_t tempReductionC = tempReduction / 4;
  169.  
  170.   if (buttons) { //poll the buttons.
  171.     if (buttons & BUTTON_SELECT) {
  172.       celsius = !celsius;
  173.       EEPROM.write(5, celsius); //only write to EEPROM when something is changed to reduce write cycles.
  174.     } //end if.
  175.        
  176.     else if (buttons & BUTTON_UP) {
  177.       switch (menu) { //update variables depending on which menu is selected.      
  178.         case 1:
  179.           tempHold += 2;
  180.           if (tempHold > 80) {
  181.             tempHold = 80;
  182.           } //end if.
  183.           EEPROM.write(0, tempHold);
  184.         break; //end case 1.
  185.        
  186.         case 2:
  187.           tempReduction += 2;
  188.           if (tempReduction > 12) {
  189.             tempReduction = 12;
  190.           } //end if.
  191.           EEPROM.write(1, tempReduction);
  192.         break; //end case 2.
  193.        
  194.         case 3:
  195.           eveningHour ++;
  196.           if (eveningHour > 24) {
  197.             eveningHour = 24;
  198.           } //end if.
  199.           EEPROM.write(3, eveningHour);
  200.         break; //end case 3.
  201.        
  202.         case 4:
  203.           morningHour ++;
  204.           if (morningHour > 11) {
  205.             morningHour = 11;
  206.           } //end if.
  207.           EEPROM.write(2, morningHour);
  208.         break; //end case 4.
  209.        
  210.         case 5:
  211.         break; //end case 5.
  212.        
  213.         case 6:
  214.         break; //end case 6.
  215.        
  216.         case 7:
  217.           daylightSavings = !daylightSavings;
  218.           EEPROM.write(6, daylightSavings);
  219.         break; //end case 7.
  220.        
  221.         case 8:
  222.         break; //end case 8.
  223.        
  224.         default:
  225.         break;
  226.       } //end switch.
  227.     } //end if button_up.
  228.    
  229.     else if (buttons & BUTTON_DOWN) {
  230.       switch (menu) {
  231.         case 1:
  232.           tempHold -= 2;
  233.           if (tempHold < 12) {
  234.             tempHold = 12;
  235.           } //end if.
  236.           EEPROM.write(0, tempHold);
  237.         break; //end case 1.
  238.          
  239.         case 2:
  240.           tempReduction -= 2;
  241.           if (tempReduction < 0) {
  242.             tempReduction = 0;
  243.           } //end if.
  244.           EEPROM.write(1, tempReduction);
  245.         break; //end case 2.
  246.          
  247.         case 3:
  248.           eveningHour --;
  249.           if (eveningHour < 16) {
  250.             eveningHour = 16;
  251.           } //end if.
  252.           EEPROM.write(3, eveningHour);
  253.         break; //end case 3.
  254.          
  255.         case 4:
  256.           morningHour --;
  257.           if (morningHour < 3) {
  258.             morningHour = 3;
  259.           } //end if.
  260.           EEPROM.write(2, morningHour);
  261.         break; //end case 4.
  262.        
  263.         case 5:
  264.         break; //end case 5.
  265.        
  266.         case 6:
  267.         break; //end case 6.
  268.        
  269.         case 7:
  270.           daylightSavings = !daylightSavings;
  271.           EEPROM.write(6, daylightSavings);
  272.         break; //end case 7.
  273.        
  274.         case 8:
  275.         break;
  276.          
  277.         default:
  278.         break;
  279.       } //end switch
  280.     } //end if button_down.
  281.          
  282.     else if (buttons & BUTTON_RIGHT) {
  283.       menu ++;
  284.       clearLine(); //clears 2nd line only when menu number is changed.
  285.       if (menu > 8) {
  286.         menu = 1;
  287.       } //end if.
  288.       EEPROM.write(4, menu);
  289.     } //end if.
  290.    
  291.     else if (buttons & BUTTON_LEFT) {
  292.       menu --;
  293.       clearLine();
  294.       if (menu < 1) {
  295.         menu = 8;
  296.       } //end if.
  297.       EEPROM.write(4, menu);
  298.     } //end if.
  299.   } // end if buttons.
  300.  
  301.   if (currentTime - lastReadingTime > sensorInterval) { //only poll sensors every 150ms.
  302.     timeString = ReadTimeDate(2);
  303.     hour = timeString.toInt(); //gets hour of day.
  304.    
  305.     if (!celsius) {
  306.       temp1 = getTemp(tempPin1); //poll the sensors.
  307.       temp2 = getTemp(tempPin2);
  308.       temp3 = getTemp(tempPin3);
  309.       tempAvg = average(temp1, temp2, temp3);
  310.       tempOneWire = getOneWireTemp();      
  311.     } //end if.
  312.     else {
  313.       temp1C = getTemp(tempPin1);
  314.       temp2C = getTemp(tempPin2);
  315.       temp3C = getTemp(tempPin3);
  316.       tempAvgC = average(temp1C, temp2C, temp3C);
  317.       tempOneWireC = getOneWireTemp();
  318.     } //end else.
  319.    
  320.     lastReadingTime = currentTime;
  321.     reading ++; //next column number in the matrix.
  322.     if (reading > 9) { //reset reading counter every 10 readings.
  323.       reading = 0;
  324.     } //end if.
  325.   } //end if.
  326.  
  327.   //print avg to screen:
  328.   lcd.setCursor(0, 0);
  329.   lcd.print(F("Avg:"));
  330.   if (!celsius) {
  331.     if (tempAvg >= -40 && tempAvg < 0) { //displays negative temps.
  332.       lcd.print(tempAvg);
  333.       lcd.print(F("F"));
  334.     } //end if.
  335.     else if (tempAvg >= 0) { //displays positive temps and clears last digit.
  336.       lcd.print(tempAvg);
  337.       lcd.print(F("F "));
  338.     } //end else if.
  339.     else {
  340.       lcd.print(F("--F ")); //displays "--" if all 3 sensors are unplugged.
  341.     } //end else.
  342.   } //end if !celsius.
  343.  
  344.   else {
  345.     if (tempAvgC >= -40 && tempAvgC < 0) {
  346.       lcd.print(tempAvgC);
  347.       lcd.print(F("C"));
  348.     } //end if.
  349.     else if (tempAvgC >= 0) {
  350.       lcd.print(tempAvgC);
  351.       lcd.print(F("C "));
  352.     } //end else if.
  353.     else {
  354.       lcd.print(F("--C "));
  355.     } //end else.
  356.   } //end else.
  357.  
  358.   //print hold temp to screen:
  359.   lcd.setCursor(8, 0);
  360.   lcd.print(F("Hold:"));
  361.   lcd.setCursor(13, 0);
  362.   if (hour < morningHour || hour >= eveningHour) { //displays night temp hold at night.
  363.     if (!celsius) {
  364.       lcd.print(tempHold - tempReduction);
  365.       lcd.print(F("*")); //star indicates night time temp reduction.
  366.     } //end if.
  367.     else {
  368.       lcd.print(tempHoldC - tempReductionC);
  369.       lcd.print(F("*"));
  370.     } //end else.
  371.   } //end if.
  372.  
  373.   else if (hour >= morningHour && hour < eveningHour) { //displays regular temp hold during day.
  374.     if (!celsius) {
  375.       lcd.print(tempHold);
  376.       lcd.print(F("F"));
  377.     } //end if.
  378.     else {
  379.       lcd.print(tempHoldC);
  380.       lcd.print(F("C"));
  381.     } //end else.
  382.   } //end else if.
  383.  
  384.   lcd.setCursor(0, 1);
  385.   lcd.print(F("M")); //displays menu number.
  386.   lcd.print(menu);
  387.  
  388.   //bottom line display:
  389.   if (doorState == 0) {
  390.     analogWrite(redLed, 0);
  391.     digitalWrite(greenLed, HIGH); //green led indicates system normal.
  392.     if (!doorLineCleared) { //only clears line once when door is shut.
  393.       clearLine();
  394.       doorLineCleared = true;
  395.     } //end if.
  396.    
  397.     switch (menu) {
  398.       case 1: //displays sensors to screen and allows changing of temp hold.
  399.         lcd.setCursor(2, 1);
  400.         if (!celsius) { //sensor one:
  401.           if (temp1 < -40) { //displays "--" if tempNear returns null and clears leading minus sign.
  402.             lcd.print(F(" --"));
  403.           } //end if.
  404.           else if (temp1 >= -40 && temp1 < 0) { //negative temps.
  405.             lcd.print(temp1);
  406.           } //end else if.
  407.           else {
  408.             lcd.print(F(" ")); //positive temps and clears minus sign.
  409.             lcd.print(temp1);
  410.           } //end else.
  411.           lcd.print(F("F "));
  412.         } //end if.
  413.         else {
  414.           if (temp1C < -40) {
  415.             lcd.print(F(" --"));
  416.           } //end if.
  417.           else if (temp1C >= 40 && temp1C < 0) {
  418.             lcd.print(temp1C);
  419.           } //end else if.
  420.           else {
  421.             lcd.print(F(" "));
  422.             lcd.print(temp1C);
  423.           } // end else.
  424.           lcd.print(F("C "));
  425.         } //end else.
  426.  
  427.         lcd.setCursor(7, 1);
  428.         if (!celsius) { //sensor 2:
  429.           if (temp2 < -40) {
  430.             lcd.print(F(" --"));
  431.           } //end if.
  432.           else if (temp2 >= -40 && temp2 < 0) {
  433.             lcd.print(temp2);
  434.           } //end else if.
  435.           else {
  436.             lcd.print(F(" "));
  437.             lcd.print(temp2);
  438.           } //end else.
  439.           lcd.print(F("F "));
  440.         } //end if.
  441.         else {
  442.           if (temp2C < -40) {
  443.             lcd.print(F(" --"));
  444.           } //end if.
  445.           else if (temp2C >= 40 && temp2C < 0) {
  446.             lcd.print(temp2C);
  447.           } //end else if.
  448.           else {
  449.             lcd.print(F(" "));
  450.             lcd.print(temp2C);
  451.           } // end else.
  452.           lcd.print(F("C "));
  453.         } //end else.
  454.        
  455.         lcd.setCursor(12, 1);
  456.         if (!celsius) { //sensor 3:
  457.           if (temp3 < -40) {
  458.             lcd.print(F(" --"));
  459.           } //end if.
  460.           else if (temp3 >= -40 && temp3 < 0) {
  461.             lcd.print(temp3);
  462.           } //end else if.
  463.           else {
  464.             lcd.print(F(" "));
  465.             lcd.print(temp3);
  466.           } //end else.
  467.           lcd.print(F("F "));
  468.         } //end if.
  469.         else {
  470.           if (temp3C < -40) {
  471.             lcd.print(F(" --"));
  472.           } //end if.
  473.           else if (temp3C >= 40 && temp3C < 0) {
  474.             lcd.print(temp3C);
  475.           } //end else if.
  476.           else {
  477.             lcd.print(F(" "));
  478.             lcd.print(temp3C);
  479.           } // end else.
  480.           lcd.print(F("C "));
  481.         } //end else.
  482.       break; //end menu 1.
  483.  
  484.       case 2: //displays temp drop amount.
  485.         lcd.setCursor(3, 1);
  486.         lcd.print(F("Drop Temp:"));
  487.         if (!celsius) {
  488.           if (tempReduction < 10) {
  489.             lcd.print(F(" "));
  490.           } //end if.
  491.           lcd.print(tempReduction);
  492.           lcd.print(F("F"));
  493.         } //end if.
  494.         else {
  495.           if (tempReductionC < 10) {
  496.             lcd.print(F(" "));
  497.           } //end if.
  498.           lcd.print(tempReductionC);
  499.           lcd.print(F("C"));
  500.         } //end else.
  501.       break; //end menu 2.
  502.  
  503.       case 3: //displays PM time to drop temp:
  504.         lcd.setCursor(3, 1);
  505.         lcd.print(F("Heat Dn: "));
  506.         if (eveningHour < 22) {
  507.           lcd.print(F(" "));
  508.         } //end if.
  509.         lcd.print(eveningHour - 12);
  510.         lcd.print(F("pm"));
  511.       break; //end menu 3.
  512.  
  513.       case 4: //displays AM time to raise temp:
  514.         lcd.setCursor(3, 1);
  515.         lcd.print(F("Heat Up: "));
  516.         if (morningHour < 10) {
  517.           lcd.print(F(" "));
  518.         } //end if.
  519.         lcd.print(morningHour);
  520.         lcd.print(F("am"));
  521.       break; //end menu 4.
  522.  
  523.       case 5: //display time to 2nd row:  
  524.         lcd.setCursor(4, 1);
  525.         lcd.print(F("Tm: "));
  526.         if (currentTime - lastClockCheck > sensorInterval) {
  527.           lcd.print(ReadTimeDate(1)); //gets time only.
  528.           lastClockCheck = currentTime;
  529.         } //end if.
  530.       break; //end menu 5.
  531.  
  532.       case 6: //display date to 2nd row:
  533.         lcd.setCursor(4, 1);
  534.         lcd.print(F("Dt: "));
  535.         if (currentTime - lastClockCheck > sensorInterval) {
  536.           lcd.print(ReadTimeDate(0)); //gets date only.
  537.           lastClockCheck = currentTime;
  538.         } //end if.
  539.       break; //end menu 6.
  540.      
  541.       case 7: //daylight savings time enable/disable:
  542.         lcd.setCursor(4, 1);
  543.         lcd.print(F("DST:"));
  544.         if (daylightSavings) {
  545.           lcd.print(F("Active  "));
  546.         } //end if.
  547.        
  548.         else {
  549.           lcd.print(F("Inactive"));
  550.         } //end else.
  551.       break;  //end menu 7.
  552.      
  553.       case 8: //prints outside temp to screen.
  554.         lcd.setCursor(4, 1);
  555.         lcd.print(F("Out: "));
  556.         if (!celsius) {
  557.           if (tempOneWire > -51) {
  558.             lcd.print(tempOneWire);
  559.          } //end if.
  560.           else {
  561.             lcd.print("--");
  562.           } //end else.
  563.           lcd.print(F("F   "));
  564.         } //end if celsius.
  565.         else {
  566.           if (tempOneWireC > -51) {
  567.             lcd.print(tempOneWireC);
  568.           } //end if.
  569.           else {
  570.             lcd.print("--");
  571.           } //end else.
  572.           lcd.print(F("C   "));
  573.         } // else.
  574.       break; //end case 8.  
  575.     } //end switch menu.
  576.   } //end if door closed.
  577.  
  578.   else {
  579.     doorLineCleared = false;
  580.     lcd.setCursor(2, 1);
  581.     lcd.print(F(" Door open!   "));
  582.     digitalWrite(greenLed, LOW);
  583.     digitalWrite(yellowLed, LOW);
  584.     digitalWrite(relay, LOW);
  585.     heaterState = 0;
  586.     analogWrite(redLed, 180);
  587.     heaterOffTime = currentTime;
  588.   } //end else if.
  589.  
  590.   //decide when to turn heater on or off:
  591.   if (hour >= morningHour && hour < eveningHour) { //day time
  592.     if (((!celsius && tempAvg > -41 && tempAvg < tempHold) ||
  593.     (celsius && tempAvgC > -41 && tempAvgC < tempHoldC)) && doorState == 0) {
  594.       heaterOn();
  595.     } //end if.
  596.     else {
  597.       heaterOff();
  598.     } //end else.
  599.   } //end if day time.
  600.        
  601.   else if (hour < morningHour || hour >= eveningHour) { //night time
  602.     if (((!celsius && tempAvg > -41 && tempAvg < (tempHold - tempReduction)) ||
  603.     (celsius && tempAvgC > -41 && tempAvgC < (tempHoldC - tempReductionC))) && doorState == 0) {
  604.       heaterOn();
  605.     } //end if.
  606.     else {
  607.       heaterOff();
  608.     } //end else.
  609.   } //end if night time.
  610. } //end loop().  
  611.  
  612. /* getTemp(): each time the function is called, a new reading is taken and stored to the 3x10 matrix. each row is then averaged and
  613. returned as temp for each sensor. AREF = 2.04V.
  614. */
  615. int8_t getTemp(uint8_t pin) {
  616.   val[pin][reading] = analogRead(pin);
  617.   delay(2); //delay between each analog pin is needed to reduce cross interferance between readings.
  618.   if (val[pin][reading] < 50) { //sensor unplugged.
  619.     return -41;
  620.   } //end if.
  621.   uint16_t sum = 0;
  622.   for (uint8_t i = 0; i <= 9; i ++) { //adds up all the values in the row.
  623.     sum += val[pin][i];
  624.   } //end for.
  625.   sum /= 10;
  626.   float tempC = ((sum - 50.0) * (165.0) / (828.0)) - 40.0; //convert analog reading to celsius using floating point math instead of map(sum, 50, 878, -40, 125).
  627.   if (celsius) {
  628.     return round(tempC);
  629.   } //end if.
  630.   else {
  631.     return round((1.8 * tempC) + 32.0);
  632.   } // end else.
  633. } //end getTemp().
  634.  
  635. int8_t getOneWireTemp() {
  636.   byte data[2]; //array to store data retrieved from sensor.
  637.   oneWire.reset();
  638.   oneWire.select(addr);
  639.   oneWire.write(0x44, 1); //start conversion.
  640.   oneWire.reset();
  641.   oneWire.select(addr);
  642.   oneWire.write(0xBE); //read scratchpad.
  643.  
  644.   for (byte i = 0; i < 3; i ++) {
  645.     data[i] = oneWire.read(); //collect data.
  646.   } //end for.
  647.  
  648.   int16_t raw = (data[1] << 8) | data[0]; //convert raw data to C.
  649.  
  650.   if (celsius) {
  651.     return round((float)raw / 16.0);
  652.   } //end if.
  653.   else {
  654.     return round(((float)raw / 16.0) * 1.8 + 32.0);
  655.   } //end else.
  656. } //end getOneWireTemp().
  657.  
  658. void heaterOn() {
  659.   if (currentTime - heaterOffTime > heaterDelay) { //check to see if heater has been off for at least 2 min.
  660.     digitalWrite(relay, HIGH);
  661.     analogWrite(yellowLed, 180);
  662.     heaterOnTime = currentTime;
  663.     heaterState = 1;
  664.   } //end if.
  665. } //end heaterOn().
  666.  
  667. void heaterOff() {
  668.   if (currentTime - heaterOnTime > heaterDelay) { //check to see if heater has been on for at least 2 min.
  669.     digitalWrite(relay, LOW);
  670.     digitalWrite(yellowLed, LOW);
  671.     heaterOffTime = currentTime;
  672.     heaterState = 0;
  673.   } //end if.
  674. } //end heaterOff().
  675.  
  676. void clearLine() { //clears 2nd line past M#.
  677.   lcd.setCursor(2, 1);
  678.   lcd.print(F("              "));
  679. } //end clearLine().
  680.  
  681. int8_t average(int8_t temp_1, int8_t temp_2, int8_t temp_3) { //averages 3 temps and knows how depending on which sensors are plugged in.
  682.   uint8_t count = 0;
  683.   float avg = 0.0;
  684.   if (temp_1 > -41) { //sensor connected.
  685.    count ++;
  686.    avg += temp_1;
  687.   } //end if.
  688.   if (temp_2 > -41) {
  689.     count ++;
  690.     avg += temp_2;
  691.   } //end if.
  692.   if (temp_3 > -41) {
  693.     count ++;
  694.     avg += temp_3;
  695.   } //end if.
  696.   if (count != 0) {
  697.     return round(avg / count);
  698.   } //end if.
  699.   else {
  700.     return -41; //all three sensors unplugged.
  701.   } //end else.
  702. } //end average().
  703.  
  704. void RTC_init() { //start the RTC chip.
  705.   SPI.begin();
  706.   SPI.setBitOrder(MSBFIRST);
  707.   SPI.setDataMode(SPI_MODE1); // both mode 1 & 3 should work.  
  708.   digitalWrite(cs, LOW); //set control register.  
  709.   SPI.transfer(0x8E);
  710.   SPI.transfer(0x60); //60= disable Osciallator and Battery SQ wave @1hz, temp compensation, Alarms disabled.
  711.   digitalWrite(cs, HIGH);
  712.   delay(10);
  713. } //end RTC_init().
  714.  
  715. String ReadTimeDate(uint8_t mode) { //gets time and date.
  716.   String dateTime;
  717.   uint8_t TimeDate [7]; //second,minute,hour,null,day,month,year       
  718.   for (uint8_t i = 0; i <= 6; i ++) {
  719.     if (i == 3) {
  720.       i ++;
  721.     } //end if.
  722.     digitalWrite(cs, LOW);
  723.     SPI.transfer(i + 0x00);
  724.     unsigned int n = SPI.transfer(0x00);        
  725.     digitalWrite(cs, HIGH);
  726.     int a = n & B00001111;    
  727.     if (i == 2) {  
  728.       int b = (n & B00110000) >> 4; //24 hour mode
  729.       if (b == B00000010) {
  730.         b = 20;
  731.       } //end if.        
  732.       else if (b == B00000001) {
  733.         b = 10;
  734.       } //end else.
  735.       TimeDate[i] = a + b;
  736.     } //end if.
  737.     else if (i == 4) {
  738.       int b = (n & B00110000) >> 4;
  739.       TimeDate[i] = a + b * 10;
  740.     } //end else.
  741.     else if (i == 5) {
  742.       int b = (n & B00010000) >> 4;
  743.       TimeDate[i] = a + b * 10;
  744.     } //end else.
  745.     else if (i == 6) {
  746.       int b = (n & B11110000) >> 4;
  747.       TimeDate[i] = a + b * 10;
  748.     } //end else.
  749.     else { 
  750.       int b = (n & B01110000) >> 4;
  751.       TimeDate[i] = a + b * 10;
  752.     } //end else.
  753.   } //end for.
  754.  
  755.   if (daylightSavings) { //reduce hour slot by 1.
  756.         TimeDate[2] -= 1;
  757.   } //end if.
  758.  
  759.   switch (mode) {
  760.     case 0: //returns date only.
  761.       if (TimeDate[5] < 10) {
  762.         dateTime.concat("0"); //leading zero.
  763.       } //end if.
  764.       dateTime.concat(TimeDate[5]);
  765.       dateTime.concat("/");
  766.       if (TimeDate[4] < 10) {
  767.         dateTime.concat("0");
  768.       } //end if.
  769.       dateTime.concat(TimeDate[4]);
  770.       dateTime.concat("/");
  771.       dateTime.concat(TimeDate[6]);
  772.       return dateTime;
  773.     break; //end mode 0.
  774.  
  775.     case 1: //returns time only.
  776.       if (TimeDate[2] < 10) {
  777.         dateTime.concat("0"); //leading zero
  778.       } //end if.
  779.       dateTime.concat(TimeDate[2]);
  780.       dateTime.concat(":");
  781.       if (TimeDate[1] < 10) {
  782.         dateTime.concat("0");
  783.       } //end if.
  784.       dateTime.concat(TimeDate[1]);
  785.       dateTime.concat(":");
  786.       if (TimeDate[0] < 10) {
  787.         dateTime.concat("0");
  788.       } //end if.
  789.       dateTime.concat(TimeDate[0]);
  790.       return dateTime;
  791.     break; //end mode 1.
  792.  
  793.     case 2: //returns hour of day only.
  794.       dateTime.concat(TimeDate[2]);
  795.       return dateTime;
  796.     break; //end mode 2.
  797.   } //end switch.
  798. } //end ReadTimeDate().
  799.  
  800. void serialEvent() { //called any time serial data is available.
  801.   char c = Serial.read();
  802.   switch (c) {
  803.     case '*': //all values requested. sends string of data to be served by other arduino. IE " 64h63a17j9e7m8t0d1f61x62y65z58w* "
  804.       Serial.print(tempHold);
  805.       Serial.print(F("h")); //indicates end of tempHold.
  806.      
  807.       if (tempAvg > -41) {
  808.         Serial.print(tempAvg);
  809.       } //end if.
  810.       else {
  811.         Serial.print(F("--"));
  812.       } //end else.
  813.      
  814.       Serial.print(F("a"));
  815.       Serial.print(hour);
  816.       Serial.print(F("j"));
  817.       Serial.print(eveningHour);
  818.       Serial.print(F("e"));
  819.       Serial.print(morningHour);
  820.       Serial.print(F("m"));
  821.       Serial.print(tempReduction);
  822.       Serial.print(F("t"));
  823.       Serial.print(doorState);
  824.       Serial.print(F("d"));
  825.       Serial.print(heaterState);
  826.       Serial.print(F("f"));
  827.      
  828.       if (temp1 > -41) {
  829.         Serial.print(temp1);
  830.       } //end if.
  831.       else {
  832.         Serial.print(F("--"));
  833.       } //end else.
  834.       Serial.print(F("x"));
  835.    
  836.       if (temp2 > -41) {
  837.         Serial.print(temp2);
  838.       } //end if.
  839.       else {
  840.         Serial.print(F("--"));
  841.       } //end else.
  842.       Serial.print(F("y"));
  843.      
  844.       if (temp3 > -41) {
  845.         Serial.print(temp3);
  846.       } //end if.
  847.       else {
  848.         Serial.print(F("--"));
  849.       } //end else.
  850.       Serial.print(F("z"));
  851.      
  852.       if (tempOneWire > -51) {
  853.         Serial.print(tempOneWire);
  854.       }
  855.       else {
  856.         Serial.print(F("--"));
  857.       }
  858.       Serial.print(F("w"));
  859.      
  860.       Serial.println(F("*")); //end of data character.
  861.     break; //end case '*'.
  862.    
  863.     case 'h': //increase hold temp.
  864.       tempHold += 2;
  865.       if (tempHold > 80) {
  866.         tempHold = 80;
  867.       } //end if.
  868.       EEPROM.write(0, tempHold);
  869.     break; //end case 'h'.
  870.    
  871.     case 'n': //decrease hold temp.
  872.       tempHold -= 2;
  873.       if (tempHold < 12) {
  874.         tempHold = 12;
  875.       } //end if.
  876.       EEPROM.write(0, tempHold);
  877.     break; //end case 'n'.
  878.    
  879.     case 'e': //heat off later.
  880.       eveningHour ++;
  881.       if (eveningHour > 24) {
  882.         eveningHour = 24;
  883.       } //end if.
  884.       EEPROM.write(3, eveningHour);
  885.     break; //end case 'e'.
  886.    
  887.     case 'd': //heat off earlier.
  888.       eveningHour --;
  889.       if (eveningHour < 16) {
  890.         eveningHour = 16;
  891.       } //end if.
  892.       EEPROM.write(3, eveningHour);
  893.     break; //end case 'd'.
  894.    
  895.     case 'm': //heat on later.
  896.       morningHour ++;
  897.       if (morningHour > 11) {
  898.         morningHour = 11;
  899.       } //end if.
  900.       EEPROM.write(2, morningHour);
  901.     break; //end case 'm'.
  902.    
  903.     case 'j': //heat on earlier.
  904.       morningHour --;
  905.       if (morningHour < 3) {
  906.         morningHour = 3;
  907.       } //end if.
  908.       EEPROM.write(2, morningHour);
  909.     break; //end case 'j'.
  910.    
  911.     case 't': //reduce temp more.
  912.       tempReduction += 2;
  913.       if (tempReduction > 12) {
  914.         tempReduction = 12;
  915.       } //end if.
  916.       EEPROM.write(1, tempReduction);
  917.     break; //end case 't'.
  918.    
  919.     case 'g': //reduce temp less.
  920.       tempReduction -= 2;
  921.       if (tempReduction < 0) {
  922.         tempReduction = 0;
  923.       } //end if.
  924.       EEPROM.write(1, tempReduction);
  925.     break; //end case 'g'.
  926.   } //end switch.
  927. } //end serialEvent().
  928.  
  929. /*
  930. void printResults() { //for debugging.
  931.   Serial.println(ReadTimeDate(0));
  932.   Serial.println(ReadTimeDate(1));
  933.   Serial.print(F("Menu #: "));
  934.   Serial.println(menu);
  935.   Serial.println();
  936.   Serial.print(F("Hold temp: "));
  937.   Serial.println(tempHold);
  938.   Serial.println();
  939.   Serial.print(F("Average temp: "));
  940.   Serial.println(tempAvg);
  941.   Serial.println();
  942.   Serial.println(F("Sensor one: "));
  943.   for (uint8_t i = 0; i <= 9; i ++) {
  944.     Serial.print(val[0][i]);
  945.     Serial.print(F(" "));
  946.   } //end for.
  947.   Serial.println();
  948.   Serial.println(F("Sensor two: "));
  949.   for (uint8_t i = 0; i <= 9; i ++) {  
  950.     Serial.print(val[1][i]);
  951.     Serial.print(F(" "));
  952.   } //end for.
  953.   Serial.println();
  954.   Serial.println(F("Sensor three: "));
  955.   for (uint8_t i = 0; i <= 9; i ++) {
  956.     Serial.print(val[2][i]);
  957.     Serial.print(F(" "));
  958.   } //end for.
  959.   Serial.println();
  960. } //end printResults().*/
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement