Learn how to display temperature and humidity readings from a DHT11/DHT22 sensor in an SSD1306 OLED display using an ESP32 or an ESP8266 with Arduino IDE.
The idea of using the OLED display with the ESP32 or ESP8266 is to ilustrate how you can create a physical user interface for your boards.
Project Overview
In this project we’ll use an I2C SSD1306 128×64 OLED display as shown in the following figure.
The temperature and humidity will be measured using the DHT22 temperature and humidity sensor (you can also use DHT11).
If you’re not familiar with the DHT11/DHT22 sensor, we recommend reading the following guide:
Parts required
For this tutorial you need the following components:
- 0.96 inch OLED display
- ESP32 or ESP8266 (read ESP32 vs ESP8266)
- DHT22 or DHT11 temperature and humidity sensor
- Breadboard
- 10k Ohm resistor
- 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!
Schematic
The OLED display we’re using communicates via I2C communication protocol, so you need to connect it to the ESP32 or ESP8266 I2C pins.
By default, the ESP32 I2C pins are:
- GPIO 22: SCL
- GPIO 21: SDA
If you’re using an ESP8266, the default I2C pins are:
- GPIO 5 (D1): SCL
- GPIO 4 (D2): SDA
Follow the next schematic diagram if you’re using an ESP32 board:
Recommended reading: ESP32 Pinout Reference Guide
If you’re using an ESP8266 follow the next diagram instead.
In this case we’re connecting the DHT data pin to GPIO 14, but you can use any other suitable GPIO.
Recommended reading: ESP8266 Pinout Reference Guide
Installing Libraries
Before uploading the code, you need to install the libraries to write to the OLED display and the libraries to read from the DHT sensor.
Installing the OLED libraries
There are several libraries available to control the OLED display with the ESP8266. In this tutorial we’ll use the libraries from adafruit: the Adafruit_SSD1306 library and the Adafruit_GFX library. Follow the next steps to install these libraries:
1. Open your Arduino IDE and go to Sketch > Include Library > Manage Libraries. The Library Manager should open.
2. Type “SSD1306” in the Search box and install the SSD1306 library from Adafruit.
3. After installing the SSD1306 library from Adafruit, type “GFX” in the search box and install the library.
Installing the DHT Sensor libraries
To read from the DHT sensor we’ll use the libraries from Adafruit.
1. Open your Arduino IDE and go to Sketch > Include Library > Manage Libraries. The Library Manager should open.
2. Search for “DHT” on the Search box and install the DHT library from Adafruit.
3. After installing the DHT library from Adafruit, type “Adafruit Unified Sensor” in the search box. Scroll all the way down to find the library and install it.
Installing the ESP boards
We’ll program the ESP32/ESP8266 using Arduino IDE, so you must have the ESP32/ESP8266 add-on installed in your Arduino IDE. If you haven’t, follow the next tutorial first that fits your needs:
- Install the ESP32 Board in Arduino IDE (Windows instructions)
- Install the ESP32 Board in Arduino IDE (Mac OS X and Linux instructions)
- Install the ESP8266 Board in Arduino IDE
Finally, restart your Arduino IDE.
Code
After installing the necessary libraries, you can copy the following code to your Arduino IDE and upload it to your ESP32 or ESP8266 board.
/*********
Rui Santos
Complete project details at https://randomnerdtutorials.com
*********/
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <Adafruit_Sensor.h>
#include <DHT.h>
#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 64 // OLED display height, in pixels
// Declaration for an SSD1306 display connected to I2C (SDA, SCL pins)
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, -1);
#define DHTPIN 14 // Digital pin connected to the DHT sensor
// Uncomment the type of sensor in use:
//#define DHTTYPE DHT11 // DHT 11
#define DHTTYPE DHT22 // DHT 22 (AM2302)
//#define DHTTYPE DHT21 // DHT 21 (AM2301)
DHT dht(DHTPIN, DHTTYPE);
void setup() {
Serial.begin(115200);
dht.begin();
if(!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
Serial.println(F("SSD1306 allocation failed"));
for(;;);
}
delay(2000);
display.clearDisplay();
display.setTextColor(WHITE);
}
void loop() {
delay(5000);
//read temperature and humidity
float t = dht.readTemperature();
float h = dht.readHumidity();
if (isnan(h) || isnan(t)) {
Serial.println("Failed to read from DHT sensor!");
}
// clear display
display.clearDisplay();
// display temperature
display.setTextSize(1);
display.setCursor(0,0);
display.print("Temperature: ");
display.setTextSize(2);
display.setCursor(0,10);
display.print(t);
display.print(" ");
display.setTextSize(1);
display.cp437(true);
display.write(167);
display.setTextSize(2);
display.print("C");
// display humidity
display.setTextSize(1);
display.setCursor(0, 35);
display.print("Humidity: ");
display.setTextSize(2);
display.setCursor(0, 45);
display.print(h);
display.print(" %");
display.display();
}
How the code works
Let’s take a quick look on how the code works.
Importing libraries
The code starts by including the necessary libraries. The Wire, Adafruit_GFX and Adafruit_SSD1306 are used to interface with the OLED display. The Adafruit_Sensor and the DHT libraries are used to interface with the DHT22 or DHT11 sensors.
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <Adafruit_Sensor.h>
#include <DHT.h>
Create a display object
Then, define your OLED display dimensions. In this case, we’re using a 128×64 pixel display.
#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 64 // OLED display height, in pixels
Then, initialize a display object with the width and height defined earlier with I2C communication protocol (&Wire).
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, -1);
The (-1) parameter means that your OLED display doesn’t have a RESET pin. If your OLED display does have a RESET pin, it should be connected to a GPIO. In that case, you should pass the GPIO number as a parameter.
Create a DHT object
Then, define the DHT sensor type you’re using. If you’re using a DHT22 you don’t need to change anything on the code. If you’re using another sensor, just uncomment the sensor you’re using and comment the others.
//#define DHTTYPE DHT11 // DHT 11
#define DHTTYPE DHT22 // DHT 22 (AM2302)
//#define DHTTYPE DHT21 // DHT 21 (AM2301)
Initialize a DHT sensor object with the pin and type defined earlier.
DHT dht(DHTPIN, DHTTYPE);
setup()
In the setup(), initialize the serial monitor for debugging purposes.
Serial.begin(115200);
Initialize the DHT sensor:
dht.begin();
Then, initialize the OLED display.
if(!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) { // Address 0x3D for 128x64
Serial.println(F("SSD1306 allocation failed"));
for(;;);
}
In this case, the address of the OLED display we’re using is 0x3C. If this address doesn’t work, you can run an I2C scanner sketch to find your OLED address. You can find the I2C scanner sketch here.
Add a delay to give time for the display to initialize, clear the display and set the text color to white:
delay(2000);
display.clearDisplay();
display.setTextColor(WHITE)
In the loop() is where we read the sensor and display the temperature and humidity on the display.
Get temperature and humidity readings from DHT
The temperature and humidity are saved on the t and h variables, respectively. Reading temperature and humidity is as simple as using the readTemperature() and readHumidity() methods on the dht object.
float t = dht.readTemperature();
float h = dht.readHumidity();
In case we are not able to get the readings, display an error message:
if (isnan(h) || isnan(t)) {
Serial.println("Failed to read from DHT sensor!");
}
If you get that error message, read our troubleshooting guide: how to fix “Failed to read from DHT sensor”.
Display sensor readings on the OLED display
The following lines display the temperature on the OLED display.
display.setTextSize(1);
display.setCursor(0,0);
display.print("Temperature: ");
display.setTextSize(2);
display.setCursor(0,10);
display.print(t);
display.print(" ");
display.setTextSize(1);
display.cp437(true);
display.write(167);
display.setTextSize(2);
display.print("C");
We use the setTextSize() method to define the font size, the setCursor() sets where the text should start being displayed and the print() method is used to write something on the display.
To print the temperature and humidity you just need to pass their variables to the print() method as follows:
display.print(t);
The “Temperature” label is displayed in size 1, and the actual reading is displayed in size 2.
To display the º symbol, we use the Code Page 437 font. For that, you need to set the cp437 to true as follows:
display.cp437(true);
Then, use the write() method to display your chosen character. The º symbol corresponds to character 167.
display.write(167);
A similar approach is used to display the humidity:
display.setTextSize(1);
display.setCursor(0, 35);
display.print("Humidity: ");
display.setTextSize(2);
display.setCursor(0, 45);
display.print(h);
display.print(" %");
Don’t forget that you need to call display.display() at the end, so that you can actually display something on the OLED.
display.display();
Recommended reading: ESP32 with DHT11/DHT22 Temperature and Humidity Sensor using Arduino IDE
Demonstration
The following figure shows what you should get at the end of this tutorial. Humidity and temperature readings are displayed on the OLED.
Troubleshooting
If your DHT sensor fails to get the readings or you get the message “Failed to read from DHT sensor”, read our DHT Troubleshooting Guide to help you solve that problem.
If you get the “SSD1306 allocation failed” error or if the OLED is not displaying anything in the screen, it can be one of the following issues:
Wrong I2C address
The I2C address for the OLED display we are using is 0x3C. However, yours may be different. So, make sure you check your display I2C address using an I2C scanner sketch.
SDA and SCL not connected properly
Please make sure that you have the SDA and SCL pins of the OLED display wired correctly. If you’re using:
- ESP32: connect SDA pin to GPIO 21 and SCL pin to GPIO 22
- ESP8266: connect SDA pin to GPIO 4 (D2) and SCL pin to GPIO 5 (D1)
Wrapping Up
We hope you’ve found this tutorial about displaying sensor readings on the OLED display useful. The OLED display is a great way to add a user interface to your projects. If you like this project, you may also like to know how to display sensor readings in your browser using an ESP Web Server:
- ESP32 DHT Web Server (Arduino IDE)
- ESP8266 DHT Web Server (Arduino IDE)
- ESP32/ESP8266 DHT Web Server (MicroPython)
You can learn more about the ESP32 and ESP8266 with our courses:
Thanks for reading.
It might be useful to do a version of this using the BME280 sensor. Although more expensive than the DHT sensors, the BME is much more accurate and reliable.
I started with the BME280 and found that there was a problem with using on the ESP8266. It was a few years ago and the problem may have been resolved but I’m thinking it was a data transfer rate issue. I wish I could post pictures here. I have an arduino nano clone running the bme280 and a RTC module with an analog TFT displaying an analog clock with time, temp and date. Also, I have an ESP8266 with a DHT11 pulling its time from the web to display an analog clock on a tiny oled. Most of my projects I use is RandomNerd – some I pilfer from others. The analog clock I got from rinkydink (I think).
Great stuff – thanks – keep it coming.
Thank you for following our work.
Regards,
Sara
Project worked the first time I tried it!
Great job, Rui and Sara!
Very cool project ! How do i connect it to my wifi ?
Hi.
You can follow one of these tutorials:
https://randomnerdtutorials.com/esp8266-dht11dht22-temperature-and-humidity-web-server-with-arduino-ide/
https://randomnerdtutorials.com/esp32-dht11-dht22-temperature-humidity-web-server-arduino-ide/
Regards,
Sara
I have been on the seen before ESP 🙂 I want to get back on track. This ESP8266 is a WIFI thing. Could you do this project with one ESP8266 outside in the wind and snow and another indoor with a LCD screen to retrieve this info?
Kind regards
Leslie
Thanks for the project suggestion, but I don’t have any tutorials on that exact subject.
Hello! For web server with esp32 that you have published on your website: you can access the web’s data only from the local network or from all internet??
Thanks
With this example you can only access the ESP32 data locally. However, you can open a port in your router to make the web server available from anywhere.
thanks you for the project , i am starting with esp8266 and i really need help on a personal project.
i want the servo motor to be controlled by an LDR and a esp8266.
thanks for the help.
You’re welcome! Thanks for the project suggestion, but I don’t have any tutorials on that exact subject.
Rui and Sara!
I have just started with Arduino and ESP8266 this Random Nerd Tutorials
as education för beginners as me.
Keep up going with more useful stuff. THANKS
Thanks 😀
Another great project-If I want to use a BME280 do I need to wire it to diferent gpios to the oled or is the address definition sufficient ?
Hi Peter.
You can use the same pins.
Or you can also create another I2C instance for the sensor.
You can read all about this here: https://randomnerdtutorials.com/esp32-i2c-communication-arduino-ide/
Regards,
sara
I come across the function isnan in the code and I couldn’t find what it does.
Can you explain it please?
Thank you.
It verifies that the temperature and humidity have been well received and formatted.
Sorry to bother you. I google it and found the answer.
Please ignore my post before.
Thank you.
Guess I have a slow OLED display. I could see text, but it was all over the display. Sometimes it was readable, sometimes not. So I added a slight delay at the bottom above display.display();
display.print(” %”);
delay(1000); // <<<<< added this line to make display readable
display.display();
}
Hi Jim.
Thanks for sharing that.
Other readers might be struggling with the same issue.
Regards,
Sara
How hard is it to change the readout from Celsius to Fahrenheit?
Thanks, LT
Hi.
To get temperature in Fahrenheit degrees, replace the following line
temp = dht.readTemperature();
with
temp = dht.readTemperature(true);
Regards,
Sara
Works great!
Thanks LT
Perfect! What would us “newbies” do without this site???? lol
😀
Hi Sara und Rui,
this was a perfect project for me.
I build a ESP8266 with DHT22 and a Telegram Bot.
When i send a Codeword from Mobilephone via Telegram to my Bot he will send me the Temperature and Humidity.
Then i found this OLED Display and your Website and then i have copy your code into my Telegram Bot Code and it works perfectly.
I get all time the Data on Display and when i want to my Telegram Bot.
Thank you for this.
Daniel
That’s great!
Regards,
Sara
I recommend use this sketch
Hi Sara & Rui,
Thanks for the project.
I plugged all the components, loaded the libraries into Arduino IDE, but when I’m trying to verify the copied and pasted sketch , i have an error message.
( i choose Generic ESP8266 for the board, and the correct USBport).
Any ideas how to help me ?
Thank you in advance
Hi.
What is the exact error that you get?
Regards,
Sara
Hi,
The error messages are :
WARNING : Category ‘Network’ in library 1wIP_enc28j60 is not valid. Setting to ‘uncategorized’
WARNING : Category ‘Network’ in library 1wIP_w5500 is not valid. Setting to ‘uncategorized’
Regards
That library is an Ethernet Library which I don’t think is used in that project…
Hi,
Actually the full error message is :
WARNING: Category ‘Network’ in library lwIP_PPP is not valid. Setting to ‘Uncategorized’
WARNING: Category ‘Network’ in library lwIP_enc28j60 is not valid. Setting to ‘Uncategorized’
WARNING: Category ‘Network’ in library lwIP_w5500 is not valid. Setting to ‘Uncategorized’
WARNING: Category ‘Network’ in library lwIP_w5500 is not valid. Setting to ‘Uncategorized’
Build options changed, rebuilding all
Multiple libraries were found for “DHT.h”
In file included from C:\Users\p******\Documents\Arduino\libraries\Adafruit_GFX_Library\Adafruit_GrayOLED.cpp:20:
Used: C:\Users\p******\Documents\Arduino\libraries\DHT_sensor_library
C:\Users\p******\Documents\Arduino\libraries\Adafruit_GFX_Library\Adafruit_GrayOLED.h:30:10: fatal error: Adafruit_I2CDevice.h: No such file or directory
Not used: C:\Users\p******\Documents\Arduino\libraries\Grove_Temperature_And_Humidity_Sensor
30 | #include <Adafruit_I2CDevice.h>
| ^~~~~~~~~~~~~~~~~~~~~~
compilation terminated.
Any help would be appreciated, as i am a beginner 🙂
Thank you
Hi Pascual it may not be my place to say this but this is what I think you should do.
Start a new project in IDE , delete the lines at the top that come with a new file.
Go to the project in RNT below the code is a button “raw code” click on that and the code opens in a new page. Copy and paste that into your new project.
You cannot copy code off a web page as you can get all sorts of weird errors.
Hope that helps Iain.
Code…this fixes degree & percent symbols…
Also configures for multi displays…
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 64 // OLED display height, in pixels
// Declaration for an SSD1306 display connected to I2C (SDA, SCL pins)
Adafruit_SSD1306 Display1(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, -1);
Adafruit_SSD1306 Display2(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, -1);
void setup() {
if(!Display1.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
Serial.println(F(“SSD1306 allocation failed”));
for(;;);
}
delay(10);
Display1.cp437(true);
Display1.clearDisplay();
Display1.setTextColor(WHITE,BLACK);
if(!Display2.begin(SSD1306_SWITCHCAPVCC, 0x3D)) {
Serial.println(F("SSD1306 allocation failed"));
for(;;);
}
delay(10);
Display1.cp437(true);
Display2.clearDisplay();
Display2.setTextColor(WHITE,BLACK);
}
void loop() {
// Correction: 248 is code for Degree Symbol…not 167
Display1.write(248);
// Correction: 37 is code for Percent Symbol…
Display1.write(37);
}
Is there a way to update changes in the temperature & humidity without issuing the
display.clearDisplay(); command?
How could I clear just a row, or any previous values at a location specified by the
display.setCursor(column, row); command?
Thanks for any assistance
Can you please tell me which software do you use to draw the above circuits..??
Hi.
It’s fritzing.
Regards,
Sara
Is it version 0.9.3b or any other version..?
Hi Sara and Rui, thanks for the nice project. But why everything works and shows how it is powered by a cable with a plug connected to the programming. Note!!, and the display does not show anything when the voltage of 3.3 V or 5 V is connected to the ESP 32 board.
Tiles and display as in your photos. Thanks for the good advice on this problem.