Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /*Thermostat with Real Time Clock Module and web support.
- This sketch takes temp readings from three temp sensors and a door sensor and decides when to turn the heat on or off while serving a web page.
- steve.a.mccluskey@gmail.com
- Hardware used:
- Arduino Mega 2560 R3. http://arduino.cc/en/Main/ArduinoBoardMega2560
- Arduino Ethernet Shield. http://arduino.cc/en/Main/ArduinoEthernetShield
- Arduino ProtoShield. http://arduino.cc/en/Main/ArduinoProtoShield
- Adafruit I2C RGB/LCD Shield. https://www.adafruit.com/products/772
- Adafruit MCP9808 I2C temp sensor breakout board (3). https://www.adafruit.com/products/1782
- DS18B20 OneWire digital waterproof temp sensor. https://www.adafruit.com/products/381
- Adafruit DS1307 I2C Real Time Clock breakout board. https://www.adafruit.com/products/264
- 5Vdc relay.
- Magnetic door sensor.
- 5V voltage regulator.
- Web page and server code modified from sketch found at
- http://startingelectronics.com/tutorials/arduino/ethernet-shield-web-server-tutorial/SD-card-AJAX-XML-web-server/
- Original Author: W.A. Smith, http://startingelectronics.com
- References: - WebServer example by David A. Mellis and
- modified by Tom Igoe
- - SD card examples by David A. Mellis and
- Tom Igoe
- Revisions:
- V2.2: Web support using second arduino with ethernet shield. Master sends single char commands over serial and thermostat responds accordingly.
- V2.3: Added door and heater state to web page.
- V2.4: Added EEPROM functionality to save settings to resume on startup.
- V2.5: Added code to handle if one of the sensors is unplugged on the web page, 02/18/14.
- V2.6: Rewrote button polling, bottom line display and ReadTimeDate() with switch/cases; consolidated door logic, rewrote average functions. 02/19/14.
- V2.7: Added functionality to display negative temps down to -40. 02/20/14.
- V2.8: Removed averageC(), removed unneccesary lcd.setCursor()'s, fixed average() to correctly return negative temps, changed tempAvgC calculation,
- 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.
- Changed average() to use floating point math as well. 03/03/14.
- V2.9: Changed how often ReadTimeDate() is called. 03/05/14.
- V3.0: Added daylight savings time option menu and functionality. 02/23/15.
- V3.1: Added doorState variable and only reads door once per loop instead of several times. 02/25/15.
- V3.2: Changed ReadTimeDate() to only initialize one string instead of three. Added heaterDelay variable. 02/27/15.
- V4.0: Added One-Wire Temp sensor support for outdoor temps and getOneWireTemp(). Changed temp variables to temp1, temp2, temp3 from tempNear/Far/Out.
- 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.
- Version 4.0 which uses analog TMP36 temp sensors can be found here: http://pastebin.com/YxKFUr2y
- V5.0: Rewrote entire sketch to use I2C temp sensors and I2C clock module. 03/04/14.
- V5.1: TempHold is now changeable on M8 (temp Out) screen. Added RTC_Interval and changed sensorInterval. Added lastClockCheck variable. 03/09/14.
- V6.0: Combined I2C and Ajax Server to run on a Mega. 03/10/14.
- V6.1: Shortened strings sent to and from client to save clock cycles. Combined lines in XML_Response() to eliminate cl.print()'s by butting successive HTML tags on the same line.
- Eliminated RTC_Interval check on Menu 5 and 6 since the RTC is being updated during loop(), eliminated lastClockCheck2. Misc clock cycle savings. 03/17/15.
- V6.2: Made C temp variables global because sketch initializes them every loop and it caused errors with web server. sendCommands() only called if there is a button pushed
- on web page. 03/18/15.
- V6.3: All temps are updated every sensor interval in celsius then converted to F regardless of celsius mode. getOneWireTemp() now only returns temp in C. 03/19/15.
- V6.4: Consolidated a few client.println()'s and index.htm is sent in 64 byte packets instead of byte by byte (thanks SurferTim!). Temps are read as floats then rounded. 03/20/15.
- V6.5: Button presses are executed as nested switch/cases instead of if/else if/else. 03/21/15.
- V6.6: Button presses and web commands now execute a specific function instead of identical code. IE tempHoldUp(), tempHoldDn(), etc.
- sendCommands() is now a switch/case, using char after "%" in HTTP_req as its argument to reduce calls to StrContains(). 03/25/15.
- Pin layout as follows:
- 0 : Hardware serial RX.
- 1 : Hardware serial TX.
- 2 ~: OneWire bus.
- 3 ~: Green LED.
- 4 ~: SD CS.
- 5 ~: Yellow LED.
- 6 ~: Red LED.
- 7 ~: Door sensor.
- 8 ~: Heater relay.
- 9 ~:
- 10~: Ethernet CS.
- 11~:
- 12~:
- 13~:
- 14 ... 19 : N/C.
- 20 : SDA.
- 21 : SCL.
- 22 ... 49 : N/C.
- 50 : SPI MISO.
- 51 : SPI MOSI.
- 52 : SPI SCK.
- 53 :
- A0 ... A15: N/C.
- Sketch outline:
- Libraries.
- Pin Declarations.
- Global Variables.
- setup().
- loop() {
- Web server.
- Poll door.
- Static variables.
- Poll buttons.
- Poll sensors.
- Print avg/hold to first line.
- Print menu to second line.
- Door closed: switch/case for second line.
- Door open: door open.
- Heater on/off logic.
- }
- cToF().
- getOneWireTemp().
- heaterOn().
- heaterOff().
- clearLine().
- average().
- XML_Response().
- StrClear().
- StrContains().
- sendCommands().
- tempHoldUp().
- tempHoldDn().
- tempReductionUp().
- tempReductionDn().
- eveningHourUp().
- eveningHourDn().
- morningHourUp().
- morningHourDn().
- dayLightSavings().
- */
- #include <Wire.h>
- #include "RTClib.h"
- #include <RTC_DS1307.h>
- #include "Adafruit_MCP9808.h"
- #include <Adafruit_MCP23017.h>
- #include <Adafruit_RGBLCDShield.h>
- #include <EEPROM.h>
- #include <OneWire.h>
- #include <SPI.h>
- #include <Ethernet.h>
- #include <SD.h>
- #define RTC_Interval 150 //delay between RTC updates.
- #define sensorInterval 1000 //delay between sensor readings.
- #define heaterDelay 120000 //heater on/off delay.
- #define REQ_BUF_SZ 60 // size of buffer used to capture HTTP requests.
- //pin declarations:
- #define oneWireBus 2
- #define greenLed 3
- #define yellowLed 5
- #define redLed 6
- #define door 7
- #define relay 8
- byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xFD };
- IPAddress ip(192, 168, 1, 177); // IP address, may need to change depending on network.
- EthernetServer server(80); // create a server at port 80.
- File webFile;
- char HTTP_req[REQ_BUF_SZ] = {0}; // buffered HTTP request stored as null terminated string.
- char req_index = 0; // index into HTTP_req buffer.
- OneWire oneWire(oneWireBus);
- byte addr[8]; //array to store OneWire device's address.
- //objects:
- Adafruit_RGBLCDShield lcd = Adafruit_RGBLCDShield();
- RTC_DS1307 rtc;
- Adafruit_MCP9808 tempSensor1 = Adafruit_MCP9808();
- Adafruit_MCP9808 tempSensor2 = Adafruit_MCP9808();
- Adafruit_MCP9808 tempSensor3 = Adafruit_MCP9808();
- //global variables:
- boolean celsius = EEPROM.read(5);
- boolean doorLineCleared = false;
- boolean daylightSavings = EEPROM.read(6);
- uint8_t tempHold = EEPROM.read(0); // read saved tempHold value from EEPROM.
- uint8_t menu = EEPROM.read(4);
- uint8_t heaterState = 0, doorState = 0;
- int8_t tempReduction = EEPROM.read(1);
- int8_t temp1, temp2, temp3, tempOneWire, tempAvg; // variables to store temps.
- int8_t tempAvgC, temp1C, temp2C, temp3C, tempOneWireC, tempHoldC, tempReductionC;
- unsigned long heaterOnTime = 0, heaterOffTime = 0, currentTime = 0, lastReadingTime = 0, lastClockCheck = 0;
- DateTime now;
- uint8_t hour;
- uint8_t eveningHour = EEPROM.read(3);
- uint8_t morningHour = EEPROM.read(2);
- void setup() {
- pinMode(10, OUTPUT);
- digitalWrite(10, HIGH); // disable Ethernet chip.
- Serial.begin(19200);
- Wire.begin();
- lcd.begin(16, 2);
- lcd.setCursor(0, 0);
- lcd.print(F("RTC Thermostat"));
- lcd.setCursor(0, 1);
- lcd.print(F("V 6.6 for Mega!"));
- delay(1000);
- lcd.clear();
- lcd.setCursor(0, 0);
- if (!SD.begin(4)) { // initialize SD card.
- lcd.print(F("No SD Card!")); // init failed.
- while(true);
- } //end if.
- if (!SD.exists("index.htm")) { // check for index.htm file.
- lcd.print(F("index.htm"));
- lcd.setCursor(0, 1);
- lcd.print(F("not found!"));
- while(true); // can't find index file.
- } //end if.
- digitalWrite(10, LOW);
- Ethernet.begin(mac, ip);
- server.begin();
- lcd.print(F("IP Address:"));
- lcd.setCursor(0, 1);
- lcd.print(Ethernet.localIP());
- Serial.println(F("IP Address is: "));
- Serial.println(Ethernet.localIP());
- pinMode(redLed, OUTPUT);
- pinMode(greenLed, OUTPUT);
- pinMode(yellowLed, OUTPUT);
- pinMode(door, INPUT_PULLUP); //door pin is pulled to ground while door is closed.
- pinMode(relay, OUTPUT);
- tempSensor1.begin(0x18); //I2C address.
- tempSensor2.begin(0x19);
- tempSensor3.begin(0x1A);
- oneWire.search(addr); //get connected OneWire device address.
- rtc.begin();
- //rtc.adjust(DateTime(__DATE__, __TIME__)); //set RTC to time of compile, will revert to that time every time arduino is reset. run once and then comment out and reload.
- delay(1000);
- lcd.clear();
- } //end setup().
- void loop() {
- float convF = (5.0 * (tempHold - 32)) / 9.0;
- tempHoldC = round(convF);
- tempReductionC = tempReduction / 4;
- uint8_t buttons = lcd.readButtons(); //MUST be in main loop. will not work if global.
- EthernetClient client = server.available(); // try to get client.
- if (client) { // got client?
- boolean currentLineIsBlank = true;
- boolean commandRecieved = false;
- uint8_t index = 0;
- while (client.connected()) {
- if (client.available()) {
- char c = client.read(); // read 1 byte (character) from client.
- if (c == '%') {
- commandRecieved = true; //"%" recieved indicating a web button was pressed.
- index = req_index; //save slot of "%".
- } //end if.
- // limit the size of the stored received HTTP request.
- // buffer first part of HTTP request in HTTP_req array (string),
- // leave last element in array as 0 to null terminate string (REQ_BUF_SZ - 1).
- if (req_index < (REQ_BUF_SZ - 1)) {
- HTTP_req[req_index] = c; // save HTTP request character.
- req_index ++;
- } //end if.
- // last line of client request is blank and ends with \n
- // respond to client only after last line received:
- if (c == '\n' && currentLineIsBlank) { // send a standard http response header.
- client.println(F("HTTP/1.1 200 OK"));
- // remainder of header follows below, depending on if
- // web page or XML page is requested.
- // Ajax request - send XML file:
- if (StrContains(HTTP_req, "getIO")) { //send rest of HTTP header.
- client.println(F("Content-Type: text/xml\r\nConnection: keep-alive\r\n"));
- if (commandRecieved) {
- sendCommands(HTTP_req[index + 1]); //send char after "%".
- }
- XML_response(client); //send XML file containing input states.
- } //end if.
- else { // web page request.
- // send rest of HTTP header:
- client.println(F("Content-Type: text/html\r\nConnection: keep-alive\r\n\r\n"));
- // send web page:
- char tBuf[64];
- uint8_t clientCount;
- webFile = SD.open("index.htm");
- if (webFile) {
- while(webFile.available()) {
- clientCount = webFile.read(tBuf, 64);
- client.write((byte*)tBuf, clientCount); //send web page to client 64 bytes at a time.
- } //end while.
- webFile.close();
- } //end if.
- } //end else.
- //Serial.println(HTTP_req); // display received HTTP request on serial port.
- // reset buffer index and all buffer elements to 0:
- req_index = 0;
- StrClear(HTTP_req, REQ_BUF_SZ); //clear the buffer.
- break;
- } //end if.
- // every line of text received from the client ends with \r\n.
- if (c == '\n') {
- // last character on line of received text.
- // starting new line with next character read.
- currentLineIsBlank = true;
- } //end if.
- else if (c != '\r') { // a text character was received from client.
- currentLineIsBlank = false;
- } //end if.
- } // end if client.available().
- } // end while client.connected().
- commandRecieved = false;
- client.stop(); // close the connection.
- } // end if (client).
- if (digitalRead(door) == HIGH) { //only read once per loop.
- doorState = 1;
- } //end if.
- else {
- doorState = 0;
- } //end else.
- currentTime = millis();
- if (buttons) { //poll the buttons.
- switch (buttons) {
- case 1: //select:
- celsius = !celsius;
- EEPROM.write(5, celsius); //only write to EEPROM when something is changed to reduce write cycles.
- break; // end select.
- case 8: //up:
- switch (menu) { //update variables depending on which menu is selected.
- case 1:
- tempHoldUp();
- break; //end case 1.
- case 2:
- tempReductionUp();
- break; //end case 2.
- case 3:
- eveningHourUp();
- break; //end case 3.
- case 4:
- morningHourUp();
- break; //end case 4.
- case 5:
- break; //end case 5.
- case 6:
- break; //end case 6.
- case 7:
- dayLightSavings();
- break; //end case 7.
- case 8:
- tempHoldUp();
- break; //end case 8.
- default:
- break;
- } //end switch.
- break; //end up.
- case 4: //down:
- switch (menu) {
- case 1:
- tempHoldDn();
- break; //end case 1.
- case 2:
- tempReductionDn();
- break; //end case 2.
- case 3:
- eveningHourDn();
- break; //end case 3.
- case 4:
- morningHourDn();
- break; //end case 4.
- case 5:
- break; //end case 5.
- case 6:
- break; //end case 6.
- case 7:
- dayLightSavings();
- break; //end case 7.
- case 8:
- tempHoldDn();
- break; //end case 8.
- default:
- break;
- } //end switch.
- break; //end down.
- case 2: //right:
- menu ++; //advances menu.
- clearLine(); //clears 2nd line only when menu number is changed.
- if (menu > 8) {
- menu = 1;
- } //end if.
- EEPROM.write(4, menu);
- break; //end right.
- case 16: //left:
- menu --; //retreats menu.
- clearLine();
- if (menu < 1) {
- menu = 8;
- } //end if.
- EEPROM.write(4, menu);
- break; //end left
- default:
- break;
- } //end switch buttons.
- } // end if buttons.
- if (currentTime - lastClockCheck > RTC_Interval) { //get hour of day from RTC.
- now = rtc.now();
- hour = now.hour();
- if (daylightSavings) {
- hour += 1;
- } //end if.
- lastClockCheck = currentTime;
- } //end if.
- if (currentTime - lastReadingTime > sensorInterval) { //only poll sensors every interval
- float t1 = tempSensor1.readTempC();
- float t2 = tempSensor2.readTempC();
- float t3 = tempSensor3.readTempC();
- temp1C = round(t1);
- temp2C = round(t2);
- temp3C = round(t3);
- tempAvgC = average(temp1C, temp2C, temp3C);
- temp1 = cToF(t1);
- temp2 = cToF(t2);
- temp3 = cToF(t3);
- tempAvg = average(temp1, temp2, temp3);
- tempOneWireC = getOneWireTemp(addr);
- tempOneWire = cToF(tempOneWireC);
- lastReadingTime = currentTime;
- } //end if.
- //print avg to screen:
- lcd.setCursor(0, 0);
- lcd.print(F("Avg:"));
- if (!celsius) {
- if (tempAvg >= -40 && tempAvg < 0) { //displays negative temps.
- lcd.print(tempAvg);
- lcd.print(F("F"));
- } //end if.
- else if (tempAvg >= 0) { //displays positive temps and clears last digit.
- lcd.print(tempAvg);
- lcd.print(F("F "));
- } //end else if.
- else {
- lcd.print(F("--F ")); //displays "--" if all 3 sensors are unplugged.
- } //end else.
- } //end if !celsius.
- else {
- if (tempAvgC >= -40 && tempAvgC < 0) {
- lcd.print(tempAvgC);
- lcd.print(F("C"));
- } //end if.
- else if (tempAvgC >= 0) {
- lcd.print(tempAvgC);
- lcd.print(F("C "));
- } //end else if.
- else {
- lcd.print(F("--C "));
- } //end else.
- } //end else.
- //print hold temp to screen:
- lcd.setCursor(8, 0);
- lcd.print(F("Hold:"));
- lcd.setCursor(13, 0);
- if (hour < morningHour || hour >= eveningHour) { //displays night temp hold at night.
- if (!celsius) {
- lcd.print(tempHold - tempReduction);
- lcd.print(F("*")); //star indicates night time temp reduction.
- } //end if.
- else {
- lcd.print(tempHoldC - tempReductionC);
- lcd.print(F("*"));
- } //end else.
- } //end if.
- else if (hour >= morningHour && hour < eveningHour) { //displays regular temp hold during day.
- if (!celsius) {
- lcd.print(tempHold);
- lcd.print(F("F"));
- } //end if.
- else {
- lcd.print(tempHoldC);
- lcd.print(F("C"));
- } //end else.
- } //end else if.
- lcd.setCursor(0, 1);
- lcd.print(F("M")); //displays menu number.
- lcd.print(menu);
- //bottom line display:
- if (doorState == 0) {
- analogWrite(redLed, 0);
- digitalWrite(greenLed, HIGH); //green led indicates system normal.
- if (!doorLineCleared) { //only clears line once when door is shut.
- clearLine();
- doorLineCleared = true;
- } //end if.
- switch (menu) {
- case 1: //displays sensors to screen and allows changing of temp hold.
- lcd.setCursor(2, 1);
- if (!celsius) { //sensor one:
- if (temp1 < -40) { //displays "--" if tempNear returns null and clears leading minus sign.
- lcd.print(F(" --"));
- } //end if.
- else if (temp1 >= -40 && temp1 < 0) { //negative temps.
- lcd.print(temp1);
- } //end else if.
- else {
- lcd.print(F(" ")); //positive temps and clears minus sign.
- lcd.print(temp1);
- } //end else.
- lcd.print(F("F "));
- } //end if.
- else {
- if (temp1C < -40) {
- lcd.print(F(" --"));
- } //end if.
- else if (temp1C >= 40 && temp1C < 0) {
- lcd.print(temp1C);
- } //end else if.
- else {
- lcd.print(F(" "));
- lcd.print(temp1C);
- } // end else.
- lcd.print(F("C "));
- } //end else.
- lcd.setCursor(7, 1);
- if (!celsius) { //sensor 2:
- if (temp2 < -40) {
- lcd.print(F(" --"));
- } //end if.
- else if (temp2 >= -40 && temp2 < 0) {
- lcd.print(temp2);
- } //end else if.
- else {
- lcd.print(F(" "));
- lcd.print(temp2);
- } //end else.
- lcd.print(F("F "));
- } //end if.
- else {
- if (temp2C < -40) {
- lcd.print(F(" --"));
- } //end if.
- else if (temp2C >= 40 && temp2C < 0) {
- lcd.print(temp2C);
- } //end else if.
- else {
- lcd.print(F(" "));
- lcd.print(temp2C);
- } // end else.
- lcd.print(F("C "));
- } //end else.
- lcd.setCursor(12, 1);
- if (!celsius) { //sensor 3:
- if (temp3 < -40) {
- lcd.print(F(" --"));
- } //end if.
- else if (temp3 >= -40 && temp3 < 0) {
- lcd.print(temp3);
- } //end else if.
- else {
- lcd.print(F(" "));
- lcd.print(temp3);
- } //end else.
- lcd.print(F("F "));
- } //end if.
- else {
- if (temp3C < -40) {
- lcd.print(F(" --"));
- } //end if.
- else if (temp3C >= 40 && temp3C < 0) {
- lcd.print(temp3C);
- } //end else if.
- else {
- lcd.print(F(" "));
- lcd.print(temp3C);
- } // end else.
- lcd.print(F("C "));
- } //end else.
- break; //end menu 1.
- case 2: //displays temp drop amount.
- lcd.setCursor(3, 1);
- lcd.print(F("Drop Temp:"));
- if (!celsius) {
- if (tempReduction < 10) {
- lcd.print(F(" "));
- } //end if.
- lcd.print(tempReduction);
- lcd.print(F("F"));
- } //end if.
- else {
- if (tempReductionC < 10) {
- lcd.print(F(" "));
- } //end if.
- lcd.print(tempReductionC);
- lcd.print(F("C"));
- } //end else.
- break; //end menu 2.
- case 3: //displays PM time to drop temp:
- lcd.setCursor(3, 1);
- lcd.print(F("Heat Dn: "));
- if (eveningHour < 22) {
- lcd.print(F(" "));
- } //end if.
- lcd.print(eveningHour - 12);
- lcd.print(F("pm"));
- break; //end menu 3.
- case 4: //displays AM time to raise temp:
- lcd.setCursor(3, 1);
- lcd.print(F("Heat Up: "));
- if (morningHour < 10) {
- lcd.print(F(" "));
- } //end if.
- lcd.print(morningHour);
- lcd.print(F("am"));
- break; //end menu 4.
- case 5: //display time to 2nd row:
- lcd.setCursor(4, 1);
- lcd.print(F("Tm: "));
- if (hour < 10) {
- lcd.print(F(" "));
- } //end if.
- lcd.print(now.hour());
- lcd.print(F(":"));
- if (now.minute() < 10) {
- lcd.print(F("0"));
- } //end if.
- lcd.print(now.minute());
- lcd.print(F(":"));
- if (now.second() < 10) {
- lcd.print(F("0"));
- } //end if.
- lcd.print(now.second());
- break; //end menu 5.
- case 6: //display date to 2nd row:
- lcd.setCursor(4, 1);
- lcd.print(F("Dt: "));
- if (now.month() < 10) {
- lcd.print(F(" "));
- } //end if.
- lcd.print(now.month());
- lcd.print(F("/"));
- if (now.day() < 10) {
- lcd.print(F("0"));
- } //end if.
- lcd.print(now.day());
- lcd.print(F("/"));
- lcd.print(now.year() - 2000);
- break; //end menu 6.
- case 7: //daylight savings time enable/disable:
- lcd.setCursor(4, 1);
- lcd.print(F("DST:"));
- if (daylightSavings) {
- lcd.print(F("Active "));
- } //end if.
- else {
- lcd.print(F("Inactive"));
- } //end else.
- break; //end menu 7.
- case 8: //prints outside temp to screen.
- lcd.setCursor(4, 1);
- lcd.print(F("Out: "));
- if (!celsius) {
- if (tempOneWire > -51) {
- lcd.print(tempOneWire);
- } //end if.
- else {
- lcd.print("--");
- } //end else.
- lcd.print(F("F "));
- } //end if celsius.
- else {
- if (tempOneWireC > -51) {
- lcd.print(tempOneWireC);
- } //end if.
- else {
- lcd.print("--");
- } //end else.
- lcd.print(F("C "));
- } // else.
- break; //end case 8.
- } //end switch menu.
- } //end if door closed.
- else {
- doorLineCleared = false;
- lcd.setCursor(2, 1);
- lcd.print(F(" Door open! "));
- digitalWrite(greenLed, LOW);
- digitalWrite(yellowLed, LOW);
- digitalWrite(relay, LOW);
- heaterState = 0;
- analogWrite(redLed, 180);
- heaterOffTime = currentTime;
- } //end else if.
- //decide when to turn heater on or off:
- if (hour >= morningHour && hour < eveningHour) { //day time
- if (((!celsius && tempAvg > -41 && tempAvg < tempHold) ||
- (celsius && tempAvgC > -41 && tempAvgC < tempHoldC)) && doorState == 0) {
- heaterOn();
- } //end if.
- else {
- heaterOff();
- } //end else.
- } //end if day time.
- else if (hour < morningHour || hour >= eveningHour) { //night time
- if (((!celsius && tempAvg > -41 && tempAvg < (tempHold - tempReduction)) ||
- (celsius && tempAvgC > -41 && tempAvgC < (tempHoldC - tempReductionC))) && doorState == 0) {
- heaterOn();
- } //end if.
- else {
- heaterOff();
- } //end else.
- } //end if night time.
- } //end loop().
- int8_t cToF(float c) { //convert float C to int F.
- return round((1.8 * c) + 32.0);
- } //end cToF().
- int8_t getOneWireTemp(byte *str) { //get OneWire temp.
- byte data[2]; //array to store data retrieved from sensor.
- oneWire.reset();
- oneWire.select(str);
- oneWire.write(0x44, 1); //start conversion.
- oneWire.reset();
- oneWire.select(str);
- oneWire.write(0xBE); //read scratchpad.
- for (byte i = 0; i < 2; i ++) {
- data[i] = oneWire.read(); //collect data.
- } //end for.
- int16_t raw = (data[1] << 8) | data[0]; //convert raw data to C.
- return round((float)raw / 16.0);
- } //end getOneWireTemp().
- void heaterOn() {
- if (currentTime - heaterOffTime > heaterDelay) { //check to see if heater has been off for at least 2 min.
- digitalWrite(relay, HIGH);
- analogWrite(yellowLed, 180);
- heaterOnTime = currentTime;
- heaterState = 1;
- } //end if.
- } //end heaterOn().
- void heaterOff() {
- if (currentTime - heaterOnTime > heaterDelay) { //check to see if heater has been on for at least 2 min.
- digitalWrite(relay, LOW);
- digitalWrite(yellowLed, LOW);
- heaterOffTime = currentTime;
- heaterState = 0;
- } //end if.
- } //end heaterOff().
- void clearLine() { //clears 2nd line past M#.
- lcd.setCursor(2, 1);
- lcd.print(F(" "));
- } //end clearLine().
- 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.
- uint8_t count = 0;
- float avg = 0.0;
- if (temp_1 > -41) { //sensor connected.
- count ++;
- avg += temp_1;
- } //end if.
- if (temp_2 > -41) {
- count ++;
- avg += temp_2;
- } //end if.
- if (temp_3 > -41) {
- count ++;
- avg += temp_3;
- } //end if.
- if (count != 0) {
- return round(avg / count);
- } //end if.
- else {
- return -41; //all three sensors unplugged.
- } //end else.
- } //end average().
- void XML_response(EthernetClient cl) {
- cl.print(F("<?xml version = \"1.0\" ?><inputs><tAvg>"));
- cl.print(tempAvg);
- cl.print(F("</tAvg><tHold>"));
- cl.print(tempHold);
- cl.print(F("</tHold><eHour>"));
- cl.print(eveningHour - 12);
- cl.print(F("</eHour><mHour>"));
- cl.print(morningHour);
- cl.print(F("</mHour><tReduct>"));
- cl.print(tempReduction);
- cl.print(F("</tReduct><dState>"));
- cl.print(doorState);
- cl.print(F("</dState><hState>"));
- cl.print(heaterState);
- cl.print(F("</hState><sensors>"));
- if (temp1 >= -40) { //sensor 1.
- cl.print(temp1);
- } //end if.
- else {
- cl.print(F("--"));
- } //end else.
- cl.print(F("</sensors><sensors>"));
- if (temp2 >= -40) { //sensor 2.
- cl.print(temp2);
- } //end if.
- else {
- cl.print(F("--"));
- } //end else.
- cl.print(F("</sensors><sensors>"));
- if (temp3 >= -40) { //sensor 3.
- cl.print(temp3);
- } //end if.
- else {
- cl.print(F("--"));
- } //end else.
- cl.print(F("</sensors><sensors>"));
- if (tempOneWire >= -40) { //outdoor sensor.
- cl.print(tempOneWire);
- } //end if.
- else {
- cl.print(F("--"));
- } //end else.
- cl.print(F("</sensors><dateTime>"));
- if (now.hour() < 10) {
- cl.print(F("0"));
- }
- cl.print(now.hour());
- cl.print(F(":"));
- if (now.minute() < 10) {
- cl.print(F("0"));
- }
- cl.print(now.minute());
- cl.print(F(":"));
- if (now.second() < 10) {
- cl.print(F("0"));
- }
- cl.print(now.second());
- cl.print(F("</dateTime><dateTime>"));
- if (now.month() < 10) {
- cl.print(F("0"));
- }
- cl.print(now.month());
- cl.print(F("/"));
- if (now.day() < 10) {
- cl.print(F("0"));
- }
- cl.print(now.day());
- cl.print(F("/"));
- cl.print(now.year());
- cl.print(F("</dateTime></inputs>"));
- } //end XML_response().
- // sets every element of str to 0 (clears array)
- void StrClear(char *str, char length) {
- for (uint8_t i = 0; i < length; i ++) {
- str[i] = 0;
- } //end for.
- } //end StrClear().
- // searches for the string sfind in the string str
- // returns 1 if string found
- // returns 0 if string not found
- char StrContains(char *str, char *sfind) {
- char found = 0;
- char index = 0;
- char len;
- len = strlen(str);
- if (strlen(sfind) > len) {
- return 0;
- } //end if.
- while (index < len) {
- if (str[index] == sfind[found]) {
- found ++;
- if (strlen(sfind) == found) {
- return 1;
- } //end if.
- } //end if.
- else {
- found = 0;
- } //end else.
- index ++;
- } //end while.
- return 0;
- } //end StrContains().
- //issues commands according to HTTP_req char after "%".
- void sendCommands(char index) {
- switch (index) {
- case '1':
- tempHoldUp();
- break;
- case '2':
- tempHoldDn();
- break;
- case '3':
- tempReductionUp();
- break;
- case '4':
- tempReductionDn();
- break;
- case '5':
- eveningHourUp();
- break;
- case '6':
- eveningHourDn();
- break;
- case '7':
- morningHourUp();
- break;
- case '8':
- morningHourDn();
- break;
- default:
- break;
- } //end switch.
- } //end sendCommands().
- void tempHoldUp() {
- tempHold += 2;
- if (tempHold > 80) {
- tempHold = 80;
- } //end if.
- EEPROM.write(0, tempHold);
- } //end tempHoldUp().
- void tempHoldDn() {
- tempHold -= 2;
- if (tempHold < 12) {
- tempHold = 12;
- } //end if.
- EEPROM.write(0, tempHold);
- } //end tempHoldDn().
- void tempReductionUp() {
- tempReduction += 2;
- if (tempReduction > 12) {
- tempReduction = 12;
- } //end if.
- EEPROM.write(1, tempReduction);
- } //end tempReductionUp().
- void tempReductionDn() {
- tempReduction -= 2;
- if (tempReduction < 0) {
- tempReduction = 0;
- } //end if.
- EEPROM.write(1, tempReduction);
- } //end tempReductionDn().
- void eveningHourUp() {
- eveningHour ++;
- if (eveningHour > 24) {
- eveningHour = 24;
- } //end if.
- EEPROM.write(3, eveningHour);
- } //end eveningHourUp().
- void eveningHourDn() {
- eveningHour --;
- if (eveningHour < 16) {
- eveningHour = 16;
- } //end if.
- EEPROM.write(3, eveningHour);
- } //end eveningHourDn().
- void morningHourUp() {
- morningHour ++;
- if (morningHour > 11) {
- morningHour = 11;
- } //end if.
- EEPROM.write(2, morningHour);
- } //end morningHourUp().
- void morningHourDn() {
- morningHour --;
- if (morningHour < 3) {
- morningHour = 3;
- } //end if.
- EEPROM.write(2, morningHour);
- } //end morningHourDn().
- void dayLightSavings() {
- daylightSavings = !daylightSavings;
- EEPROM.write(6, daylightSavings);
- } //end dayLightSavings().
Add Comment
Please, Sign In to add comment