In this project you’re going to learn how to build a sensor node with an ESP8266 that publishes the temperature and humidity once a day to a free service called Thing Speak.
Watch the Video Tutorial and Project Demo
This guide is available in video format (watch below) and in written format (continue reading).
Prerequisites
Before proceeding with this tutorial we recommend taking a look at these resources:
- Getting Started with ESP8266 Wi-Fi
- ESP8266 Deep Sleep with Arduino IDE
- ESP8266 Wi-Fi Button – DIY Amazon Dash Button Clone
- ESP8266 DHT11/DHT22 Temperature and Humidity Web Server
If you like ESP8266 and you want to learn more about it. I recommend downloading my course: Home Automation using ESP8266.
Parts required
For this project, you’ll need these components:
- ESP8266 – read Best ESP8266 Wi-Fi Development Boards
- DHT11 temperature and humidity sensor
- 4.7k Ohm resistor
- Breadboard
- Jumper wires
You can use the preceding links or go directly to MakerAdvisor.com/tools to find all the parts for your projects at the best price!
Schematics
The circuit is very easy to assemble and no soldering is required, simply follow the next diagram.
Preparing Arduino IDE
Note: you should have the ESP8266 add-on in the Arduino IDE installed.
After having the circuit ready, open your Arduino IDE and install two Arduino libraries. Go to Sketch > Include library > Manage libraries…
Search for DHT (or download here). Press the “Install” button.
Note: you may also need to install the Adafruit Sensor library.
Then, you’ll also have to search for ESP Daily Task and install that library (or download here).
Thing Speak
For this project we’ll be using ThingSpeak.com. Thing Speak allows you to publish your sensor readings to their website and display them in a plot with time stamps. Then, you can access your readings from anywhere in the world.
It’s worth saying that this project can be easily modified to publish the values to your home automation hub or another application instead of Thing Speak.
The main concept I want to show you with this project is how you can put your ESP8266 constantly in deep sleep mode, publishing a value every 24 hours.
Creating New Channel
If you don’t have an account on Thing Speak you’ll have to create one. After your account is ready, sign in and open the “Channels” tab.
Press the create “New Channel” button:
Type a name for your channel, add a description, and enable a second field. Field 1 will receive the Humidity readings and Field 2 the Temperature readings. Once you’ve completed all these fields, save your channel.
Customizing Chart
These charts can be customized, go to your Private View tab and press the edit icon:
You can give each chart a title, for example the first chart will be called Humidity % and my second chart will be called Temperature ºC.
You can also customize the background color, x and y axis, and much more, as you can see. When you’re done, press the “Save” button.
Write API Key
In order to publish values with the ESP8266, you need the Write API Key. Open the “API Keys” tab and copy the Write API Key to a safe place because you’ll need it in a moment.
Uploading Code
Go back to your Arduino IDE and copy the code below:
/*
* ESP8266 Daily Task
* Rui Santos
* Complete Project Details https://randomnerdtutorials.com
*/
#include <ESP8266WiFi.h>
#include <ESPDailyTask.h>
#include "DHT.h"
// Uncomment one of the lines below for whatever DHT sensor type you're using!
#define DHTTYPE DHT11 // DHT 11
//#define DHTTYPE DHT21 // DHT 21 (AM2301)
//#define DHTTYPE DHT22 // DHT 22 (AM2302), AM2321
// Replace with your SSID and Password
const char* ssid = "REPLACE_WITH_YOUR_SSID";
const char* password = "REPLACE_WITH_YOUR_PASSWORD";
// Replace with your unique Thing Speak WRITE API KEY
const char* apiKey = "REPLACE_WITH_YOUR_ThingSpeak_WRITE_API_KEY";
const char* resource = "/update?api_key=";
// Thing Speak API server
const char* server = "api.thingspeak.com";
// Set this for what time your daily code should run
ESPDailyTask dailyTask(11*60 + 15); // 11:15am
// DHT Sensor
const int DHTPin = 5;
// Initialize DHT sensor.
DHT dht(DHTPin, DHTTYPE);
// Temporary variables
static char temperatureTemp[7];
static char humidityTemp[7];
void setup() {
// Initializing serial port for debugging purposes
Serial.begin(115200);
delay(10);
dailyTask.sleep1Day();
// put your daily code here...
dht.begin();
initWifi();
makeHTTPRequest();
// and back to sleep once daily code is done
dailyTask.backToSleep();
}
void loop() {
// sleeping so wont get here
}
// Establish a Wi-Fi connection with your router
void initWifi() {
Serial.print("Connecting to: ");
Serial.print(ssid);
WiFi.begin(ssid, password);
int timeout = 10 * 4; // 10 seconds
while(WiFi.status() != WL_CONNECTED && (timeout-- > 0)) {
delay(250);
Serial.print(".");
}
Serial.println("");
if(WiFi.status() != WL_CONNECTED) {
Serial.println("Failed to connect, going back to sleep");
}
Serial.print("WiFi connected in: ");
Serial.print(millis());
Serial.print(", IP address: ");
Serial.println(WiFi.localIP());
}
// Make an HTTP request to Thing Speak
void makeHTTPRequest() {
// Sensor readings may also be up to 2 seconds 'old' (its a very slow sensor)
float h = dht.readHumidity();
// Read temperature as Celsius (the default)
float t = dht.readTemperature();
// Read temperature as Fahrenheit (isFahrenheit = true)
float f = dht.readTemperature(true);
// Check if any reads failed and exit early (to try again).
if (isnan(h) || isnan(t) || isnan(f)) {
Serial.println("Failed to read from DHT sensor!");
strcpy(temperatureTemp,"Failed");
strcpy(humidityTemp, "Failed");
return;
}
else {
// Computes temperature values in Celsius + Fahrenheit and Humidity
float hic = dht.computeHeatIndex(t, h, false);
// Comment the next line, if you prefer to use Fahrenheit
dtostrf(hic, 6, 2, temperatureTemp);
float hif = dht.computeHeatIndex(f, h);
// Uncomment the next line, if you want to use Fahrenheit
//dtostrf(hif, 6, 2, temperatureTemp);
dtostrf(h, 6, 2, humidityTemp);
// You can delete the following Serial.print's, it's just for debugging purposes
Serial.print("Humidity: ");
Serial.print(h);
Serial.print(" %\t Temperature: ");
Serial.print(t);
Serial.print(" *C ");
Serial.print(f);
Serial.print(" *F\t Heat index: ");
Serial.print(hic);
Serial.print(" *C ");
Serial.print(hif);
Serial.print(" *F");
Serial.print("Humidity: ");
Serial.print(h);
Serial.print(" %\t Temperature: ");
Serial.print(t);
Serial.print(" *C ");
Serial.print(f);
Serial.print(" *F\t Heat index: ");
Serial.print(hic);
Serial.print(" *C ");
Serial.print(hif);
Serial.println(" *F");
}
Serial.print("Connecting to ");
Serial.print(server);
WiFiClient client;
int retries = 5;
while(!!!client.connect(server, 80) && (retries-- > 0)) {
Serial.print(".");
}
Serial.println();
if(!!!client.connected()) {
Serial.println("Failed to connect, going back to sleep");
}
Serial.print("Request resource: ");
Serial.println(resource);
client.print(String("GET ") + resource + apiKey + "&field1=" + humidityTemp + "&field2=" + temperatureTemp +
" HTTP/1.1\r\n" +
"Host: " + server + "\r\n" +
"Connection: close\r\n\r\n");
int timeout = 5 * 10; // 5 seconds
while(!!!client.available() && (timeout-- > 0)){
delay(100);
}
if(!!!client.available()) {
Serial.println("No response, going back to sleep");
}
while(client.available()){
Serial.write(client.read());
}
Serial.println("\nclosing connection");
client.stop();
}
Preparing your code
There are 3 variables that you need to change. Add your SSID and password so that your ESP is able to establish a communication with your router:
// Replace with your SSID and Password const char* ssid = "REPLACE_WITH_YOUR_SSID"; const char* password = "REPLACE_WITH_YOUR_PASSWORD";
Enter your Thing Speak Write API key in this variable:
// Replace with your unique Thing Speak WRITE API KEY
const char* apiKey = "REPLACE_WITH_YOUR_ThingSpeak_WRITE_API_KEY";
Understanding the code
Now we can take a closer look at the code. The setup() function starts by initializing the Serial port.
void setup() { // Initializing serial port for debugging purposes Serial.begin(115200); delay(10);
Then, it calls the ESP daily task function to determine whether 24 hours have passed or not since the last reading. If not, the ESP goes back to deep sleep mode.
dailyTask.sleep1Day();
However, if 24 hours have passed since the last reading, the code will proceed. So, it will initialize the DHT sensor, connect to the Wi-Fi router and make an HTTP GET request to Thing Speak in order to publish the readings.
// put your daily code here... dht.begin(); initWifi(); makeHTTPRequest();
Once the readings are published, the ESP goes back to deep sleep mode.
// and back to sleep once daily code is done dailyTask.backToSleep(); }
There’s nothing in the loop() function, because your ESP is constantly in deep sleep mode and wakes itself up.
void loop() { // sleeping so wont get here }
Other changes – different sensor and degrees Fahrenheit
Note that If you’re using a different sensor than the DHT11, you can comment and uncomment the right DEFINE line to use your sensor.
// Uncomment one of the lines below for whatever DHT sensor type you're using! #define DHTTYPE DHT11 // DHT 11 //#define DHTTYPE DHT21 // DHT 21 (AM2301) //#define DHTTYPE DHT22 // DHT 22 (AM2302), AM2321
There’s also another important thing you can change. By default this code publishes the temperature in degrees Celsius, but if you comment the variable highlighted in red and uncomment the variable highlighted in green it will publish the temperature in degrees Fahrenheit .
// Computes temperature values in Celsius + Fahrenheit and Humidity float hic = dht.computeHeatIndex(t, h, false); // Comment the next line, if you prefer to use Fahrenheit dtostrf(hic, 6, 2, temperatureTemp); float hif = dht.computeHeatIndex(f, h); // Uncomment the next line, if you want to use Fahrenheit //dtostrf(hif, 6, 2, temperatureTemp);
Once you’ve made all the changes, you can upload the code to your ESP board.
Testing the Project
Finally, open the Arduino IDE serial monitor at a baud rate of 115200. You can test your project and simulate each hour passing. Simply remove the wire that connects the RESET pin to D0 (GPIO 16), and then you just have to press the RESET button to simulate each hour passing.
So, you need to press 24 times to publish a reading. The counter variable increases every time you press the reset button. Once you reset the ESP8266 24 times, it will publish the readings to Thing Speak.
As you can see the Humidity and Temperature have been successfully published and plotted in the chart in real time.
After testing the circuit, you should reconnect the wire from RESET to D0. The ESP will wake up every hour, but it will only publish a value every 24 hours.
Wrapping Up
I hope this project was useful. Now, you know how to apply the daily task concept to any project.
This is an excerpt from my Home Automation using ESP8266 eBook. If you like ESP8266 and you want to learn more about it. I recommend downloading my course: Home Automation using ESP8266.
I hope this guide was useful. Thanks for reading!
Many thanks for the example. One question. Why three !!! (!!!client.available()) ?
Hi.
The !!! means the same as one exclamation mark (!) – this means “NOT”.
The key idea behind it is to improve visibility for the programmer.
Thanks 🙂
Hello, Sara.
I’m trying to use ESP8266 to send a push notification via GCM (Google Cloud Message). When I use Client.Connect to send a POST message the method returno FALSE and I do not know why this error occurs. Would you help me?
I’m using this library:
github.com/beegee-tokyo/GCM-ESP8266
Hi Rafael.
I’ve never used ESP8266 with GCM, so I can’t tell you why that happens.
Alternatively, you can also try using IFTTT ifttt.com/
Olá Rui e Sara
Obrigado pelo excelente tutorial e parabéns pela ótima qualidade do site.
Gostaria de montar este mesmo circuito porém para enviar ao ThingSpeak temperatura e umidade a cada hora. Seria possível?
Olá Miguel.
Sim, é possível. Mas não com este exemplo.
Para isso, teria que juntar a forma de fazer publish das leituras (como é feita neste tutorial) e depois usar deep sleep: https://randomnerdtutorials.com/esp8266-deep-sleep-with-arduino-ide/ para publicar a cada 60 minutos.
Muito obrigado Sara. Vou tentar.
By the void makeHTTPRequest, the comment says “// Make an HTTP request to the Node-RED software”, but I thought the goal here was to WRITE to ThingSpeak. Is the comment wrong? Also, does the code “client.print(String(GET “) + response + apiKey {bla bla bla}” write the values to ThingSpeak? I was expecting a POST, and don’t see how the variable “h” and “t” got mapped to &field1 and $field2, or to humidityTemp or temperatureTemp. Can you explain a bit further? Thanks!
Hi
I found everything in your book on homeautomation. All is well.
Thank you.
Peter
Thanks 🙂
Hello Sara, this tutorial (and other on this site) is great, your coding is very elegant.
Thank you!
Hi Luca.
You’re welcome! 🙂
how to make 1 hr data upload instead of 24hrs
Hi. In this example we use the ESPDailyTask library that allows us to publish a reading every 24hours.
To get data every hour, it is better to use deep sleep.
Take a look at our ESP8266 Deep Sleep tutorial here: https://randomnerdtutorials.com/esp8266-deep-sleep-with-arduino-ide/
I hope this helps 🙂
Hello Sara
> Note: you may also need to install the Adafruit Sensor library.
Once downloaded what might this library be called when it is listed in the Library Manager?
Hi.
I don’t think that library shows up in the Library Manager.
You have to install it manually.
can we use the same code for arduino uno and esp8266 01 combination
Hi Raj.
What do you mean?
I get an error:
error: pll_cal exceeds 2ms!!!
.error: pll_cal exceeds 2ms!!!
Many times
Hi Adrian.
Can you try erase ESP32 flash and then upload the code again?
To erase flash, you can follow some of the steps in this tutorial: https://randomnerdtutorials.com/flashing-micropython-firmware-esptool-py-esp32-esp8266/
1. Installing esptool.py in your computer
2. Erasing ESP32 Flash Memory
I hope this helps.
Regards,
Sara
hi there Sara
how do you make it update every 15 minutes,
and can you use an esp 32 ?
tks Matthew
Hi Matthew.
This project uses the daily task library. So, it will repeat the task daily.
If you want to update every 15 minutes, I recommend using deep sleep with timer wake up.
You can read our tutorial about deep sleep with timer wake up with the ESP32: https://randomnerdtutorials.com/esp32-timer-wake-up-deep-sleep/
I hope this helps.
Regards,
Sara
hi there how do I make it update every 15 minutes
can I use an esp 32 instead?
will this work with the esp32?
im getting data on srial monitor but not getting data on thingspeak kindly give me an idea what should i do
Hi.
Double-check your configurations on Thingspeak and make sure you are using the right API key.
Regards,
Sara
Hello
How can I change from days to hours?
Hi Sara & Rui, thanks a lot for the great tutorials!
It seems that ThingSpeak slightly changed their setup and the above code now fails. This seems to be related to the spaces in front of the values passed to the field1/field2.
I overcame the problem by wrapping the humidityTemp and temperatureTemp by
String(float(humidityTemp))
Hi.
Thanks for sharing that.
At the moment, I recommend using this example instead: https://randomnerdtutorials.com/esp8266-nodemcu-thingspeak-publish-arduino/
Regards,
Sara
Thanks a lot – yes, much simpler with the ThingsSpeak.h functions. Thanks for sharing! 🙏
Just related to my previous post…it should have been
String(atof(humidityTemp))