Created
January 19, 2021 11:23
-
-
Save sivar2311/20bf1feeafeb3f1835ba82dfc2d046bc to your computer and use it in GitHub Desktop.
Thermostat_LM75_Relay
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include "credentials.h" | |
#include <Arduino.h> | |
#include <ESP8266WiFi.h> | |
#include "lm75.h" | |
#include "SinricPro.h" | |
#include "SinricProThermostat.h" | |
#include "EEPROM.h" | |
#define PRINT_TIME 1000 // interval for serial print | |
#define REPORT_TIME 60000 // interval for reporting temperature to SinricPro server | |
#define RELAY_PIN 2 // pin for relay (here internal LED is used) | |
TempI2C_LM75 tempSensor(0x48, TempI2C_LM75::nine_bits); | |
SinricProThermostat &myThermostat = SinricPro[THERMOSTAT_ID]; | |
enum ThermostatMode { AUTO, COOL, HEAT }; // thermostat modes as enum | |
struct ThermostatCfg { // configuration struct, used to save and load from eeprom | |
bool powerState = false; // powerstate (device is on or off) | DEFAULT: OFF (false) | |
float targetTemperature = 25.0f; // target temperature | DEFAULT: 25°C | |
ThermostatMode mode = AUTO; // thermostat mode (AUTO, COOL, HEAT) | DEFAULT: AUTO | |
unsigned char check = 0x42; // just a fixed byte value. used to detect if eeprom data is valid or not | |
}; | |
ThermostatCfg thermostatConfig; // stores the configuration | |
float temperature; // keep the current temperature | |
bool relayState = false; // keep the relay state | |
float tempThreshold = 1.0f; // temperature hysteresis threshold | |
/** | |
* printConfig() | |
* Print current configuration to serial | |
**/ | |
void printConfig() { | |
Serial.printf("Device is %s\r\n", thermostatConfig.powerState?"ON":"OFF"); | |
Serial.printf("Mode is %s\r\n", thermostatConfig.mode == AUTO?"AUTO":thermostatConfig.mode==HEAT?"HEAT":"COOL"); | |
Serial.printf("Target temperature is %2.1f\r\n", thermostatConfig.targetTemperature); | |
} | |
/** | |
* saveConfig() | |
* Save cofnigruation to EEPROM | |
**/ | |
void saveConfig() { // saves the configuration to eeprom | |
Serial.printf("Saving config\r\n"); | |
EEPROM.put(0, thermostatConfig); | |
EEPROM.commit(); | |
} | |
/** | |
* loadConfig() | |
* loads configuration from eeprom | |
* applies default configuration if eeprom configuration was not valid (first run) | |
**/ | |
void loadConfig() { | |
Serial.printf("Loading config\r\n"); | |
ThermostatCfg tempConfig; | |
EEPROM.get(0, tempConfig); | |
if (tempConfig.check == 0xAB) { | |
Serial.printf("Config is valid\r\n"); | |
thermostatConfig = tempConfig; | |
} else { | |
Serial.printf("Config is invalid. Saving default config.\r\n"); | |
saveConfig(); | |
} | |
printConfig(); | |
if (thermostatConfig.powerState == false) return; | |
if (thermostatConfig.mode == HEAT) { digitalWrite(RELAY_PIN, HIGH); relayState = true; } | |
if (thermostatConfig.mode == COOL) { digitalWrite(RELAY_PIN, LOW); relayState = false; } | |
} | |
/** | |
* reportTemperature() | |
* report current temperature to SinricPro in a given interval (waitTime) | |
**/ | |
void reportTemperature(unsigned long waitTime) { | |
if (thermostatConfig.powerState == false) return; | |
static unsigned long lastMillis; | |
unsigned long currentMillis = millis(); | |
if (currentMillis - lastMillis <= waitTime) return; | |
lastMillis = currentMillis; | |
myThermostat.sendTemperatureEvent(temperature); | |
Serial.printf("Reporting measured temperature to SinricPro server: %2.1f\r\n", temperature); | |
} | |
/** | |
* handleTemperature() | |
* - get temperature from sensor | |
* - return if sensor reading failed | |
* - if device is in AUTO mode and not turned off | |
* - if temperature is below target temperature and relay is off: turn on relay, report temperature to SinricPro server | |
* - if temperature is above target temperature and relay is on: turn off relay, report temperature to SinricPro server | |
**/ | |
void handleTemperature() { | |
float tempTemperature = tempSensor.getTemp(); | |
if (tempTemperature > 100.0f) return; // reading was wrong..do nothing | |
temperature = tempTemperature; | |
if (thermostatConfig.mode != AUTO || thermostatConfig.powerState == false) return; | |
if (temperature <= thermostatConfig.targetTemperature && relayState == false) { | |
Serial.printf("Temperature (%2.3f)is below target temperature. Relay turned on.\r\n", temperature); | |
digitalWrite(RELAY_PIN, HIGH); | |
relayState = true; | |
reportTemperature(0); | |
} | |
if (temperature >= (thermostatConfig.targetTemperature + tempThreshold) && relayState == true) { | |
Serial.printf("Temperature (%2.3f) is above target temeprature. Relay turned off\r\n", temperature); | |
digitalWrite(RELAY_PIN, LOW); | |
relayState = false; | |
reportTemperature(0); | |
} | |
} | |
/** | |
* printTemperature() | |
* if device is not turned off: print the temperature in given interval (waitTime) to serial | |
**/ | |
void printTemperature(unsigned long waitTime) { | |
if (thermostatConfig.powerState == false) return; | |
static unsigned long lastMillis; | |
unsigned long currentMillis = millis(); | |
if (currentMillis - lastMillis <= waitTime) return; | |
lastMillis = currentMillis; | |
if (thermostatConfig.mode == AUTO) { | |
Serial.printf("Current temperature: %2.1f C (Target temperature: %2.1f C: %s)\r\n", temperature, thermostatConfig.targetTemperature, relayState?"ON":"OFF"); | |
} else { | |
Serial.printf("Current temperature: %2.1f C (Mode is %s)\r\n", temperature, thermostatConfig.mode == HEAT ? "HEAT" : "COOL"); | |
} | |
} | |
/** | |
* onPowerState() | |
* if relayState is on and newState is off: turn off relay | |
* if relayState is OFF and newState is on and mode is HEAT, turn on relay | |
* save config to eerpom | |
**/ | |
bool onPowerState(const String& deviceId, bool &newState) { | |
Serial.printf("Device turned %s\r\n", newState?"ON":"OFF"); | |
thermostatConfig.powerState = newState; | |
if (relayState == true && newState == false) { | |
digitalWrite(RELAY_PIN, LOW); | |
relayState = newState; | |
} | |
if (relayState == false && newState == true && thermostatConfig.mode == HEAT) { | |
digitalWrite(RELAY_PIN, HIGH); | |
relayState = newState; | |
} | |
saveConfig(); | |
return true; | |
} | |
/** | |
* onTargetTemperature() | |
* set the new targetTemperature and save to eeprom | |
**/ | |
bool onTargetTemperature(const String& deviceId, float &newTargetTemperature) { | |
Serial.printf("Target temperature set to %2.0f\r\n", newTargetTemperature); | |
thermostatConfig.targetTemperature = newTargetTemperature; | |
saveConfig(); | |
return true; | |
} | |
/** | |
* onThermostatMode() | |
* set the new mode | |
* if mode is HEAT and relay is off: turn on relay | |
* if mode is COOL and relay is on: turn off relay | |
* save value to EEPROM | |
*/ | |
bool onThermostatMode(const String& deviceId, const String& mode) { | |
Serial.printf("Mode changed to %s\r\n", mode.c_str()); | |
if (mode == "AUTO") { | |
thermostatConfig.mode = AUTO; | |
} | |
if (mode == "HEAT") { | |
thermostatConfig.mode = HEAT; | |
if (relayState == false) digitalWrite(RELAY_PIN, HIGH); | |
relayState = true; | |
} | |
if (mode == "COOL") { | |
thermostatConfig.mode = COOL; | |
if (relayState == true) digitalWrite(RELAY_PIN, LOW); | |
relayState = false; | |
} | |
saveConfig(); | |
return true; | |
} | |
void setupWiFi() { | |
Serial.printf("Connecting to %s", WIFI_SSID); | |
WiFi.begin(WIFI_SSID, WIFI_PASS); | |
while (WiFi.status() != WL_CONNECTED) { | |
Serial.printf("."); | |
delay(250); | |
} | |
Serial.printf("connected! IP is %s\r\n", WiFi.localIP().toString().c_str()); | |
} | |
void setupSinricPro() { | |
myThermostat.onTargetTemperature(onTargetTemperature); | |
myThermostat.onPowerState(onPowerState); | |
myThermostat.onThermostatMode(onThermostatMode); | |
SinricPro.onConnected([](){ Serial.printf("Connected to SinricPro\r\n"); reportTemperature(0); }); | |
SinricPro.onDisconnected([](){ Serial.printf("Disconnected from SinricPro!\r\n"); }); | |
SinricPro.begin(APPKEY, APPSECRET); | |
} | |
void setup() { | |
Serial.begin(921600); | |
pinMode(LED_BUILTIN, OUTPUT); | |
EEPROM.begin(sizeof(ThermostatCfg)); | |
loadConfig(); | |
setupWiFi(); | |
setupSinricPro(); | |
} | |
void loop() { | |
SinricPro.handle(); | |
handleTemperature(); | |
printTemperature(PRINT_TIME); | |
reportTemperature(REPORT_TIME); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment