ESPHome with DHT22 and 128x32 OLED Display

Hi everyone,

I’m new to the community, although I have been using Home Assistant now for about a year. I have several home-built Temperature & Humidity sensors utilising the DHT22 and Wemos D1 Mini. These are working really well, but I have developed some small rechargeable units for areas where I have no power available, and I would like to use an OLED display in my enclosure for a quick reference rather than having to carry my phone or tablet everywhere with me.

My current YAML config is as follows:

esphome:
  name: dht22_lounge
  platform: ESP8266
  board: d1_mini

wifi:
  ssid: "************"
  password: "************"

  # Enable fallback hotspot (captive portal) in case wifi connection fails
  ap:
    ssid: "Dht22 Lounge Fallback Hotspot"
    password: "************"

captive_portal:

# Enable logging
logger:

# Enable Home Assistant API
api:
  password: "************"

ota:
  password: "************"

# DHT22 Config
sensor:
  - platform: dht
    model: DHT22
    pin: D2
    temperature:
      name: "Living Room Temperature"
    humidity:
      name: "Living Room Humidity"
    update_interval: 30s

My question is, what code do I need to add here to get the OLED display to also output the temp and humidity? I have it working standalone from an Arduino IDE Sketch, but haven’t a clue how to translate it to ESPHome.

Many thanks in advance,
Bret :slightly_smiling_face:

here my code
you need to replace the type of screen


i2c:
  sda: D2
  scl: D1
  scan: True 
  
time:
- platform: sntp
  id: my_time
  
sensor:
  - platform: dht
    pin: D7
    model: dht22
    temperature:
      id: temp
      name: "Station Bureau Température Ambiante"
    humidity:
      id: hum
      name: "Station Bureau Humidité Ambiante"
    update_interval: 30s 
  - platform: uptime
    name: "Station Bureau Uptime Sensor"
  - platform: wifi_signal
    name: "Station Bureau WiFi Signal"
    update_interval: 30s      
  - platform: homeassistant   # chauffage
    id: chauffage
    entity_id: sensor.bureau_temperature
  - platform: homeassistant   # force
    id: force
    entity_id: sensor.bureau_heating
    
binary_sensor:
  - platform: gpio
    pin: D5
    id : presence
    name: "Station Bureau PIR Sensor"
    device_class: motion    
    
display:
  - platform: lcd_pcf8574
    dimensions: 20x4
    address: 0x27
    lambda: |-
      it.strftime("%H:%M le %d.%m.%Y", id(my_time).now());
      it.printf(0, 1,"Temp : %.1fc", id(temp).state);
      it.printf(0, 2,"Hum  : %.1f  ", id(hum).state);
```

The code for your screen is

```
display:
  - platform: ssd1306_i2c
    model: "SSD1306 128x64"
    reset_pin: D0
    address: 0x3C
    lambda: |-
      it.print(0, 0, id(font), "Hello World!");
```
2 Likes

the Bus I2c need to be connected to D1 and D2 for a nodeMCU
For ESP8266 it’ may be D5 and D3

1 Like

here the explication for the code

1 Like

Hey Thomas,

Thank you so much for the advice, I am going to try this now and I’ll let you know how I get on. :slight_smile:

Many thanks,
Bret

1 Like

Hi Thomas,

I’ve not been able to compile this in ESPHome. My YAML is:

# Define OLED Settings
i2c:
  sda: D2
  scl: D1
  scan: True 
  
time:
- platform: sntp
  id: my_time

# DHT22 Sensor
sensor:
  - platform: dht
    model: DHT22
    pin: D4
    temperature:
      id: "temp"
      name: "Master Bedroom Temperature"
    humidity:
      id: "hum"
      name: "Master Bedroom Humidity"
    update_interval: 30s

# SSD1306 OLED Display    
display:
  - platform: ssd1306_i2c
    model: "SSD1306 128x32"
    reset_pin: D0
    address: 0x3C
    lambda: |-
      it.strftime("%H:%M le %d.%m.%Y", id(my_time).now());
      it.printf(0, 1,"Temp : %.1fc", id(temp).state);
      it.printf(0, 2,"Hum  : %.1f  ", id(hum).state);

It starts to compile OK, and the spews this:

src/main.cpp: In lambda function:
src/main.cpp:205:54: error: no matching function for call to 'esphome::display::DisplayBuffer::strftime(const char [18], esphome::time::ESPTime)'
       it.strftime("%H:%M le %d.%m.%Y", my_time->now());
                                                      ^
src/main.cpp:205:54: note: candidates are:
In file included from src/esphome.h:15:0,
                 from src/main.cpp:3:
src/esphome/components/display/display_buffer.h:223:8: note: void esphome::display::DisplayBuffer::strftime(int, int, esphome::display::Font*, int, esphome::display::TextAlign, const char*, esphome::time::ESPTime)
   void strftime(int x, int y, Font *font, int color, TextAlign align, const char *format, time::ESPTime time)
        ^
src/esphome/components/display/display_buffer.h:223:8: note:   candidate expects 7 arguments, 2 provided
src/esphome/components/display/display_buffer.h:235:8: note: void esphome::display::DisplayBuffer::strftime(int, int, esphome::display::Font*, int, const char*, esphome::time::ESPTime)
   void strftime(int x, int y, Font *font, int color, const char *format, time::ESPTime time)
        ^
src/esphome/components/display/display_buffer.h:235:8: note:   candidate expects 6 arguments, 2 provided
src/esphome/components/display/display_buffer.h:247:8: note: void esphome::display::DisplayBuffer::strftime(int, int, esphome::display::Font*, esphome::display::TextAlign, const char*, esphome::time::ESPTime)
   void strftime(int x, int y, Font *font, TextAlign align, const char *format, time::ESPTime time)
        ^
src/esphome/components/display/display_buffer.h:247:8: note:   candidate expects 6 arguments, 2 provided
src/esphome/components/display/display_buffer.h:258:8: note: void esphome::display::DisplayBuffer::strftime(int, int, esphome::display::Font*, const char*, esphome::time::ESPTime)
   void strftime(int x, int y, Font *font, const char *format, time::ESPTime time)
        ^
src/esphome/components/display/display_buffer.h:258:8: note:   candidate expects 5 arguments, 2 provided
src/main.cpp:206:49: error: no matching function for call to 'esphome::display::DisplayBuffer::printf(int, int, const char [13], float&)'
       it.printf(0, 1,"Temp : %.1fc", temp->state);
                                                 ^
src/main.cpp:206:49: note: candidates are:
In file included from src/esphome.h:15:0,
                 from src/main.cpp:3:
src/esphome/components/display/display_buffer.h:177:8: note: void esphome::display::DisplayBuffer::printf(int, int, esphome::display::Font*, int, esphome::display::TextAlign, const char*, ...)
   void printf(int x, int y, Font *font, int color, TextAlign align, const char *format, ...)
        ^
src/esphome/components/display/display_buffer.h:177:8: note:   candidate expects 6 arguments, 4 provided
src/esphome/components/display/display_buffer.h:189:8: note: void esphome::display::DisplayBuffer::printf(int, int, esphome::display::Font*, int, const char*, ...)
   void printf(int x, int y, Font *font, int color, const char *format, ...) __attribute__((format(printf, 6, 7)));
        ^
src/esphome/components/display/display_buffer.h:189:8: note:   candidate expects 5 arguments, 4 provided
src/esphome/components/display/display_buffer.h:200:8: note: void esphome::display::DisplayBuffer::printf(int, int, esphome::display::Font*, esphome::display::TextAlign, const char*, ...)
   void printf(int x, int y, Font *font, TextAlign align, const char *format, ...) __attribute__((format(printf, 6, 7)));
        ^
src/esphome/components/display/display_buffer.h:200:8: note:   candidate expects 5 arguments, 4 provided
src/esphome/components/display/display_buffer.h:210:8: note: void esphome::display::DisplayBuffer::printf(int, int, esphome::display::Font*, const char*, ...)
   void printf(int x, int y, Font *font, const char *format, ...) __attribute__((format(printf, 5, 6)));
        ^
src/esphome/components/display/display_buffer.h:210:8: note:   no known conversion for argument 3 from 'const char [13]' to 'esphome::display::Font*'
src/main.cpp:207:49: error: no matching function for call to 'esphome::display::DisplayBuffer::printf(int, int, const char [14], float&)'
       it.printf(0, 2,"Hum  : %.1f  ", hum->state);
                                                 ^
src/main.cpp:207:49: note: candidates are:
In file included from src/esphome.h:15:0,
                 from src/main.cpp:3:
src/esphome/components/display/display_buffer.h:177:8: note: void esphome::display::DisplayBuffer::printf(int, int, esphome::display::Font*, int, esphome::display::TextAlign, const char*, ...)
   void printf(int x, int y, Font *font, int color, TextAlign align, const char *format, ...)
        ^
src/esphome/components/display/display_buffer.h:177:8: note:   candidate expects 6 arguments, 4 provided
src/esphome/components/display/display_buffer.h:189:8: note: void esphome::display::DisplayBuffer::printf(int, int, esphome::display::Font*, int, const char*, ...)
   void printf(int x, int y, Font *font, int color, const char *format, ...) __attribute__((format(printf, 6, 7)));
        ^
src/esphome/components/display/display_buffer.h:189:8: note:   candidate expects 5 arguments, 4 provided
src/esphome/components/display/display_buffer.h:200:8: note: void esphome::display::DisplayBuffer::printf(int, int, esphome::display::Font*, esphome::display::TextAlign, const char*, ...)
   void printf(int x, int y, Font *font, TextAlign align, const char *format, ...) __attribute__((format(printf, 6, 7)));
        ^
src/esphome/components/display/display_buffer.h:200:8: note:   candidate expects 5 arguments, 4 provided
src/esphome/components/display/display_buffer.h:210:8: note: void esphome::display::DisplayBuffer::printf(int, int, esphome::display::Font*, const char*, ...)
   void printf(int x, int y, Font *font, const char *format, ...) __attribute__((format(printf, 5, 6)));
        ^
src/esphome/components/display/display_buffer.h:210:8: note:   no known conversion for argument 3 from 'const char [14]' to 'esphome::display::Font*'
*** [/data/dht22_test_oled/.pioenvs/dht22_test_oled/src/main.cpp.o] Error 1
========================= [FAILED] Took 17.35 seconds =========================

Any ideas? I’ve tried changing a number of different things. I’m guessing there are some defines missing, how does HA know how to deal with the OLED, as the Arduino code defines the screen resolution etc.

Many thanks,
Bret

For a start I don’t see any fonts defined. Read the docs.

1 Like

Thanks for the helpful comment Nick. I’m not sure if you treat all beginners with the same level of arrogance. As I stated in my original post, I have my OLED display working perfectly from my Sketch in the Arduino IDE, but the code looks quite a bit different on ESPHome. There are no #define’s for starters, no #include’s - not very intuitive for someone who hasn’t done it before.

I did read the documentation that Thomas kindly posted a link to, and I had already visited the same link but couldn’t work out how to write the code, hence posting on the community forum for advice.

4 Likes

The trouble is most people don’t read docs. The page I pointed to is off the esphome.io main page.

Appreciate that Nick, I’ve worked in IT for over 20 years so familiar with people who don’t read! :laughing:
The link you sent is the one I’m using, I’m going to try uploading some ttf’s and have another bash at it.

What’s confused me is my sketch doesn’t define fonts, so it must handle the display a different way. The code that Thomas kindly shared doesn’t define any fonts either. I’ve made loads of DHT22 room sensors but this is the first time I’ve ever used OLED. I can get the LED displays working but the OLEDs look nicer, and are tiny.

Cheers,
Bret

1 Like

Cheers to you too. I don’t know how it works without a font defined. One tip for esphome - if you want to use a component it also pays to read the core stuff, so for a display component, read display core. https://esphome.io/components/display/index.html

2 Likes

Did you manage to print out info on oled display?

Yes I did.

Would you mind sharing a code sample? :slight_smile:

1 Like

You mean other than the one on the esphome web page?

i2c:
  sda: 5
  scl: 4
  scan: true  
font:
  - file: "RobotoMono-Thin.ttf"
    id: font16
    size: 16
    
  - file: "RobotoMono-Thin.ttf"
    id: font8
    size: 8
    
  - file: "BebasNeue-Regular.ttf"
    id: font48
    size: 48
    
  - file: "RobotoMono-Thin.ttf"
    id: font14
    size: 14
  
    
time:
  - platform: homeassistant
    id: time1
    timezone: Pacific/Auckland
    on_time:
      - seconds: 0
        minutes: 0
        hours: 4
        days_of_week: MON-SUN
        then:
           - switch.toggle: restart_switch

display:
  - platform: ssd1306_i2c
    model: "SSD1306 128x64"
    reset_pin: 0
    address: 0x3C
    lambda: |-
      it.printf(64, 0, id(font8), TextAlign::TOP_CENTER, "%s", id(dssummary).state.c_str());
      it.strftime(0, 60, id(font48), TextAlign::BASELINE_LEFT, "%H:%M", id(time1).now());
       it.printf(127, 23, id(font14), TextAlign::TOP_RIGHT , "%.1f°", id(inside_temperature).state);

Thanks @nickrout, I am new to this but got it all working in the end :slight_smile:

1 Like

Did it work with a regular D1 board?

Hi, I tried to reconstruct the D1 mini plus DHT22 (which is an AM2302) plus SSD1306 Display.
I would like to user it in a small DIN rail fuse housing with small power adapter to show my values onsite in the garden house (here is the battery for photo voltaic) and also on my HA.

I set up the following (on my test board)
D1 mini is connected via USB (from HP DeskPro 400 Desktop)
Now first PIN of the D1 mini and then the target

  • +5V goes to DHT22-PIN1
  • GRD goes to DHT22-PIN4 and also SSD1306
  • D1+D2 goes to SSD1306 (I2C Interface)
  • D4 goes to DHT22-PIN2
  • DHT22 PIN1 4,7kOhm resistor to PIN2 (+5V to DATA)

I tried it with 3 x DHT22 (source code varying with model: DHT22, DHT22_TYPE2, AM2302) :frowning:
Change the DHT22 to DHT11 (code now: model: DHT11) :frowning:
Change the D1-mini… :frowning:

I get everytime NAN as values, in the log and on the display
The date & time are correct after 2-3 minutes.

What did I do wrong?

My Code:

esphome:
  name: sensor-th03
  friendly_name: sensor-th03
esp8266:
  board: d1_mini
# Enable logging
logger:
  level: DEBUG #WARN  #VERY_VERBOSE #
# Enable Home Assistant API
api:
  encryption:
    key: "mykey"
ota:
  password: "mypassword"
wifi:
  ssid: !secret wifi_ssid
  password: !secret wifi_password
  fast_connect: true
  manual_ip:  
    static_ip: 192.168.168.246
    gateway: 192.168.168.1
    subnet: 255.255.255.0
# Enable fallback hotspot (captive portal) in case wifi connection fails
  ap:
    ssid: "-Sensor-Th03 Fallback Hotspot"
    password: "myfallback"
captive_portal:
# Zeit holen für ESP
time:
  - platform: sntp
    id: sntp_time
    timezone: Europe/Berlin
    servers:
      - 0.pool.ntp.org
      - 1.pool.ntp.org
      - 2.pool.ntp.org
  - platform: homeassistant
    id: esptime

# Definiert die IO-Ports im I2C Protokoll
i2c:
  sda: D1
  scl: D2
  #scan: False

# Definiere Sensoren
sensor:
  - platform: dht
    model: DHT22
    pin: D4
    # address: 0x70
    temperature:
      name: "TH03 Temperature"
      id: sensor_th03_temp
      accuracy_decimals: 1
      filters:
      - lambda: return x - 0;
    humidity:
      name: "TH03 Humidity"
      id: sensor_th03_hum
      accuracy_decimals: 1
      filters:
      - lambda: return x - 0;
    update_interval: 10s

# Schriftarten für Display
font:
  - file: 'arial.ttf'
    id: font1
    size: 10
  - file: 'arial.ttf'
    id: font2
    size: 12  
  - file: 'arial.ttf'
    id: font3
    size: 14  
  - file: 'arialbd.ttf'
    id: font4
    size: 14

# Display und Darstellung
display:
  - platform: ssd1306_i2c
    model: "SH1306 128x64"
    reset_pin: D0
    address: 0x3C
    # filters:
    # - filter_out: nan
    lambda: |-
      // Print "LAW-sensor-th03" in top center.
      it.printf(64, 0, id(font1), TextAlign::TOP_CENTER, "LAW-sensor-th03");
      // Print time in HH:MM format
      it.strftime(0, 18, id(font3), TextAlign::LEFT, "%d.%m.%Y", id(sntp_time).now());
      it.strftime(127, 18, id(font3), TextAlign::RIGHT, "%H:%M", id(sntp_time).now());
      //it.strftime(0, 36, id(font3), TextAlign::LEFT, "%d.%m.%Y", id(esptime).now());
      //it.strftime(127, 36, id(font3), TextAlign::RIGHT, "%H:%M", id(esptime).now());
      // Print  temperature (from sensor)
      if (id(law_sensor_th03_temp).has_state()) {
        it.printf(0, 40, id(font3), TextAlign::LEFT, "T:");
        it.printf(64, 40, id(font4), TextAlign::RIGHT, "%3.1f°", id(law_sensor_th03_temp).state);
      }
      // Print humidity (from sensor)
      if (id(law_sensor_th03_hum).has_state()) {
        it.printf(68, 40, id(font3), TextAlign::LEFT, "H:");
        it.printf(127, 40, id(font4), TextAlign::RIGHT, "%3.1f", id(law_sensor_th03_hum).state);
      }

Somebody an idea?

You got any logs?

Also why the lambda

lambda: return x - 0;