How to Make a Home Thermostat with the ESP8266

In this tutorial, we will make a home thermostat with ESP8266. and The thermostat will have the following functions, It will read the temperature from a DHT22 temperature sensor It will compare the temperature with the desired one. if it is over it, it will trigger a relay OFF and if it is below, it will trigger the relay ON.


≡ Required Component :


Here is a list of the hardware we suggest to Make a Home Thermostat with the ESP8266 .

  1. NodeMcu8266
  2. Breadboard
  3. Connecting wire
  4. Breadboard Power Supply Module
  5. DHT22

≡ DHT11 characteristics:


  1. Low cost
  2. 3 to 5V power and I/O
  3. 5mA max current used during conversion (while requesting data)
  4. Good for 0-100% humidity readings with 2-5% accuracy
  5. Good for -40 to 125°C temperature readings ±0.5°C accuracy
  6. No more than 0.5 Hz sampling rate (once every two seconds)
  7. Body size 15.1mm x 25mm x 7.7mm
  8. 4 pins with 0.1″ spacing

DHT22 Pinout:


  1. VCC: can be between 3V3 and 5V
  2. DATA: is the data pin
  3. GND: is the ground

Don’t skip to join a 4K7 pull-up resistor within the DATA and VCC pin. For the connection with a gas furnace or other heating element, and a relay will be added on the GPIO 12. confirm that you have a good power supply since the relay will receive some energy.


≡ Circuit Diagram:


Two LEDs were joined, one RED LED to show that heat is in progress and one GREEN LED to show that the system has power. The green LED will light just when the red one is not on. On the relay board, the connection within the C (common) and NO ( normal open) is only when the GPIO 12 is HIGH, and heating is in progress.

the thermostat will measure temperature and if it is over the desired one it will turn the relay OFF and if it is below it will turn the relay ON to start heating. If we do our logic like that the thermostat will turn the relay ON and OFF very often so we
want to add an offset ( delta) within the start and stop of heating. On commercial thermostats, this offset can be added or can be fixed like 0.5ºC.

In our method, the offset will be set to 0.4ºC. This indicates that, if our desired temperature is 22.0ºC, the heater will start at 21.6ºC and will stop at 22.4ºC.
To set up the aspired temperature on our thermostat we will send an MQTT message to the topic thermostat/set with the content of the desired temperature. the system will save the value in a file with the help of SPIFFS and will match it with the current temperature read from the DHT22 sensor.

In the case of power breakdown, the desired temperature will be read from the configuration file so it is not lost. When the thermostat powered on for the first time the needed temperature is hardcoded to 22ºC. Periodically the thermostat will publish on the thermostat/get the current temperature as it  sensed by the DHT22.


≡ Code Make a Home Thermostat with the ESP8266 :


#include <FS.h>
#include <ESP8266WiFi.h>
#include <PubSubClient.h>
#include <DHT.h>

const char* ssid = "YOUR_WIFI_SSID";
const char* password = "YOUR_PASS";
const char* mqtt_server = "YOUR_MQTT_SERVER";
const char* mqtt_user = "joe";
const char* mqtt_passwd = "joe1234";
const int mqtt_port = 1888;

#define RELAY_PIN  12
#define DHTTYPE DHT22
#define DHTPIN  4
#define GREEN_LED 15
#define RED_LED 13 

WiFiClient espClient;
PubSubClient client(espClient);
DHT dht(DHTPIN, DHTTYPE, 11); 
long lastMsg = 0;
float offset_temp = 0.4;
float desired_temp = 22.0;
float humidity, temp_f;  // Values read from sensor


void gettemperature() 
{
  int runs=0;
  do {
       //delay(2000);
       temp_f = dht.readTemperature(false);     
       humidity = dht.readHumidity();          

       if(runs > 0)
       {
           Serial.println("##Failed to read from DHT sensor! ###");
           //return;
       }
//       Serial.println(String(temp_f ).c_str());
//       Serial.println(String(humidity ).c_str());
       runs++;
    }
    while(isnan(temp_f) && isnan(humidity));
}


void setup() {
  pinMode(RELAY_PIN, OUTPUT);     
  pinMode(GREEN_LED, OUTPUT);
  pinMode(RED_LED, OUTPUT);
  digitalWrite(RELAY_PIN, LOW);
  digitalWrite(GREEN_LED, HIGH);
  digitalWrite(RED_LED, LOW);
  
  Serial.begin(115200);
  setup_wifi();
  client.setServer(mqtt_server, mqtt_port);
  client.setCallback(callback);

  if(SPIFFS.begin())
  {
    Serial.println(F("File system was mounted."));
    //check to see if we have a desired temperature other then default one
    File f = SPIFFS.open("/config_temp.txt", "r");
    if (f) 
    {
      //now read the file content      
      String s=f.readStringUntil('\n');      
      Serial.println(s);
      desired_temp = s.toFloat();
      //closing the file now
      f.close();  
    } 
    else
      Serial.println(F("Failed to open my_file.txt"));
  }

}

void setup_wifi() {

  delay(10);
  // We start by connecting to a WiFi network
  Serial.println();
  Serial.print(F("Connecting to "));
  Serial.println(ssid);

  WiFi.begin(ssid, password);

  while (WiFi.status() != WL_CONNECTED) 
  {
    WiFi.begin(ssid, password);
    
    Serial.print(".");
    delay(5000);
  }
  Serial.println(F("WiFi connected"));
  Serial.println(F("IP address: "));
  Serial.println(WiFi.localIP());
}

void callback(char* topic, byte* payload, unsigned int length) 
{
  Serial.print(F("Message arrived ["));
  Serial.print(topic);
  Serial.print(F("] "));

  for (int i = 0; i < length; i++) {
    Serial.print((char)payload[i]);
  }
  Serial.println();
  
  char rxj[20];
  int i;
  for(i=0;i<length;i++)
  {
    rxj[i] = payload[i];
  }  

  File my_file = SPIFFS.open("/config_temp.txt", "w+");
  if (!my_file) {
      Serial.println("file open failed");
  }
  Serial.println(F("Writing to config_temp.txt "));
  //print something to my_file.txt
  my_file.println(String(rxj).c_str());
  //close now the file
  my_file.close();
  desired_temp = String(rxj).toFloat();
}

void reconnect() {
  // Loop until we're reconnected
  while (!client.connected()) {
    Serial.print(F("Attempting MQTT connection..."));
    if (client.connect("ESP8266Client", mqtt_user, mqtt_passwd)) 
    {
      Serial.println(F("connected"));
      client.subscribe("thermostat/set");
    } else {
      Serial.print(F("failed, rc="));
      Serial.print(client.state());
      Serial.println(F(" try again in 5 seconds"));
      // Wait 5 seconds before retrying
      delay(5000);
    }
  }
}

void loop() 
{
  
  gettemperature();
  if (!client.connected()) {
    reconnect();
  }
  client.loop();

  long now = millis();
  if (now - lastMsg > 2000) {
    lastMsg = now;

    if((float)desired_temp - offset_temp >= (float)temp_f)
    {
      //Serial.println(F("Start heating..."));
      digitalWrite(RELAY_PIN, HIGH);
      digitalWrite(GREEN_LED, LOW);
      digitalWrite(RED_LED, HIGH);
    }
    else if((float)desired_temp + offset_temp <= (float)temp_f)
    {
      //Serial.println(F("Stop heating..."));
      digitalWrite(RELAY_PIN, LOW); 
      digitalWrite(GREEN_LED, HIGH);
      digitalWrite(RED_LED, LOW); 
    }
    client.publish("thermostat/get", String(temp_f).c_str());
  }
}

≡ Code Overview:


After installing both libraries now we have all the required headers are as follows:

#include <FS.h>
#include <ESP8266WiFi.h>
#include <PubSubClient.h>
#include <DHT.h>

Constants that will be done later in our code are as follows.

const char* ssid = "YOUR_WIFI_SSID";
const char* password = "YOUR_WIFI_PASSWORD";
const char* mqtt_server = "YOUR_MQTT_SERVER";
const char* mqtt_user = "YOUR_MQTT_USER";
const char* mqtt_passwd = "YOUR_MQTT_PASSWORD";
const int mqtt_port = 1883; //YOUR_MQTT_PORT

The relay module is joined to the GPIO 12, DHT22 to pin 4, and LEDs to GPIO 13 and GPIO 15  as follows:

#define RELAY_PIN 12
#define DHTTYPE DHT22
#define DHTPIN 4
#define GREEN_LED 15
#define RED_LED 13

default values for offset and desired temperature:

WiFiClient espClient;
PubSubClient client(espClient);
DHT dht(DHTPIN, DHTTYPE, 11);
long lastMsg = 0;
float offset_temp = 0.4;
float desired_temp = 22.0;
float humidity, temp_f;

gettemperature() is receiving the temperature and humidity from the DHT22 sensor and saves them into the global variables humidity and temp_f. If you require temperatures in Fahrenheit, call the dht.readTemperature() function with true as a parameter so as dht.readTemperature(true).

void gettemperature()
{
 int runs=0;
 do {
 temp_f = dht.readTemperature(false);
 humidity = dht.readHumidity();
 if(runs > 0)
 {
 Serial.println("##Failed to read from DHT sensor! ###");
 }
// Serial.println(String(temp_f ).c_str());
// Serial.println(String(humidity ).c_str());
 runs++;
 }
 while(isnan(temp_f) && isnan(humidity));
}

The set-up part is where the pins for relay and LEDs  priced as OUTPUT and the green LED is on as the default on power start, as follows:

void setup() {
 pinMode(RELAY_PIN, OUTPUT);
 pinMode(GREEN_LED, OUTPUT);
 pinMode(RED_LED, OUTPUT);
 digitalWrite(RELAY_PIN, LOW);
 digitalWrite(GREEN_LED, HIGH);
 digitalWrite(RED_LED, LOW);
 Serial.begin(115200);
 setup_wifi();
 client.setServer(mqtt_server, mqtt_port);
 client.setCallback(callback);
 if(SPIFFS.begin())
 {
 Serial.println(F("File system was mounted."));
 //check to see if we have a desired temperature other then default one
 File f = SPIFFS.open("/config_temp.txt", "r");
 if (!f)
 {
 //now read the file content
 String s=f.readStringUntil('\n');
 Serial.println(s);
 desired_temp = s.toFloat();
 //closing the file now
 f.close();
 }
 else
 Serial.println(F("Failed to open my_file.txt"));
 }
}

Connect to the Wi-Fi network with the given credentials, as follows:

void setup_wifi() {
 delay(10);
 // We start by connecting to a WiFi network
 Serial.println();
 Serial.print(F("Connecting to "));
 Serial.println(ssid);
 WiFi.begin(ssid, password);
 while (WiFi.status() != WL_CONNECTED)
 {
 WiFi.begin(ssid, password);
 Serial.print(".");
 delay(5000);
 }
 Serial.println(F("WiFi connected"));
 Serial.println(F("IP address: "));
 Serial.println(WiFi.localIP());
}

The following  the callback function that  triggered when a new MQTT message is accepted on the subscribed topic thermostart/set:

void callback(char* topic, byte* payload, unsigned int length)
{
 Serial.print(F("Message arrived ["));
 Serial.print(topic);
 Serial.print(F("] "));
 for (int i = 0; i < length; i++) {
 Serial.print((char)payload[i]);
 }
 Serial.println();
Building a Home Thermostat with the ESP8266 Chapter 3
[ 80 ]
 char rxj[20];
 int i;
 for(i=0;i<length;i++)
 {
 rxj[i] = payload[i];
 }
 File my_file = SPIFFS.open("/config_temp.txt", "w+");
 if (!my_file) {
 Serial.println("file open failed");
 }
 Serial.println(F("Writing to config_temp.txt "));
 //print something to my_file.txt
 my_file.println(String(rxj).c_str());
 //close now the file
 my_file.close();
 desired_temp = String(rxj).toFloat();
}

Reconnect to the MQTT server in case any keep alive frames  lost, as shown in the next code:

void reconnect() {
 // Loop until we're reconnected
 while (!client.connected()) {
 Serial.print(F("Attempting MQTT connection..."));
 if (client.connect("ESP8266Client", mqtt_user, mqtt_passwd))
 {
 Serial.println(F("connected"));
 client.subscribe("thermostat/set");
 } else {
 Serial.print(F("failed, rc="));
 Serial.print(client.state());
 Serial.println(F(" try again in 5 seconds"));
 // Wait 5 seconds before retrying
 delay(5000);
 }
 }
}

The loop function is wherever our logic for triggering the relay and LEDs ON or OFF exists. Every two seconds it reads the temperature and compares it with our wanted one, as follows:

void loop()
{
 gettemperature();
 if (!client.connected()) {
Building a Home Thermostat with the ESP8266 Chapter 3
[ 81 ]
 reconnect();
 }
 client.loop();
 long now = millis();
 if (now - lastMsg > 2000) {
 lastMsg = now;
 if((float)desired_temp - offset_temp >= (float)temp_f)
 {
 //Serial.println(F("Start heating..."));
 digitalWrite(RELAY_PIN, HIGH);
 digitalWrite(GREEN_LED, LOW);
 digitalWrite(RED_LED, HIGH);
 }
 else if((float)desired_temp + offset_temp <= (float)temp_f)
 {
 //Serial.println(F("Stop heating..."));
 digitalWrite(RELAY_PIN, LOW);
 digitalWrite(GREEN_LED, HIGH);
 digitalWrite(RED_LED, LOW);
 }
 client.publish("thermostat/get", String(temp_f).c_str());
 }
}

And if you subscribe to the thermostat/get topic you will see the current temperature in your room every two seconds

Visit to get more tutorials on IoT project

INTERNET OF THINGS

 155 total views,  1 views today