ESP32 C3 72x40 OLED - ESPHOME

Hello

has anybody made this screen work using ESPHOME code?

can you please share your code? I’ve been trying for hours and coundt find the way to do it, I get always 100% lit scren

thanks!

2 Likes

At least post what you have done on yaml.
Does your I2C find the display address?

Sorry, you are completly right

My current code work, but just by trial and error about the offsets, rotation and possition:

# LCD bus I2C
i2c:
  sda: GPIO5
  scl: GPIO6
  scan: true
  id: bus_a

display:
  - platform: ssd1306_i2c
    model: "SH1107 128x128"
    rotation: 180
    update_interval: 60s  
    offset_y: 0
    offset_x: 0
    address: 0x3C
    lambda: |-
      it.print(25, 11, id(my_font), "ESP32-C3 OLED");


font:
  - file: "fonts/roboto.ttf" 
    id: my_font
    size: 12

that code works, shows and I can update the info in screen but if I use the more correct (according to the screen resolution) code:

display:
  - platform: ssd1306_i2c
    model: "SSD1306 72x40"
    rotation: 0
    update_interval: 1s  # Se refresca cada 60 segundos (toma aprox. 1s)
    offset_y: 0
    offset_x: 0
    address: 0x3C
    lambda: |-
      // Imprime "Hello World" en la posición (0,0)
      it.print(0, 0, id(my_font), "ESP32_72x40");

no matter what I write on the message, the screen shows the info I uploaded with the previous code (keeps showing ESP32-C3 OLED)

Then your upload didn’t complete.
You probably got some errors when complied?

What about:
# Imprime "Hello World" en la posición (0,0)

Finally I found a solution that works for me,

in case it helps someone else:

# LCD bus I2C
i2c:
  sda: GPIO5
  scl: GPIO6
  scan: true
  id: bus_a
  frequency: 800kHz

display:
  - platform: ssd1306_i2c
    model: "sh1106 128x64"
    rotation: 0
    update_interval: 60s  
    offset_y: 0
    offset_x: 0
    invert: True  # Optional
    address: 0x3C
    lambda: |-
      it.print(27, 9, id(my_font), "27x9");


font:
  - file: "fonts/roboto.ttf"   ## Choose your font from the esphome fonts folder
    id: my_font
    size: 12
6 Likes

Thanks a lot @poseido. I finally got mine working, after finding your post.


If someone wishes to update the text from HA, here is how I do it. Just create an input_text helper named “OLED Display”.

# LCD bus I2C
i2c:
  sda: GPIO5
  scl: GPIO6
  scan: true
  id: bus_a
  frequency: 800kHz

# Display settings
display:
  - platform: ssd1306_i2c
    model: "sh1106 128x64"
    id: my_display
    rotation: 0
    update_interval: 60s  
    offset_y: 0
    offset_x: 0
    invert: false
    address: 0x3C
    lambda: |-
      it.printf(30, 18, id(my_font), "%s", id(oledtext).state.c_str());

# Font
font:
  - file: "gfonts://Roboto"
    id: my_font
    size: 16


text_sensor:
  - platform: homeassistant
    name: "oledtext"
    entity_id: input_text.oled_display
    id: oledtext
    on_value:
      then:
        - component.update: my_display
    

5 Likes

Actually, the proper config should be like below. Just posting it in a case that someone else like me would stumble upon this post.

Don’t forget to set up your font.

# I2C minimum settings
i2c:
  sda: GPIO5
  scl: GPIO6
  scan: true
  id: bus_i2c

# OLED SSD1306 72x40 Display settings
display:
  - platform: ssd1306_i2c
    model: "SSD1306 72x40"
    id: my_display
    rotation: 0
    update_interval: 1s  
    offset_y: 0
    offset_x: 0
    invert: true
    address: 0x3C
    lambda: |-
      it.printf(0, 0, id(my_font_12), "TEXT", id(uptime_human).state.c_str());

This way you have no issues with offsets or x/y starting points.

5 Likes

@kamilzierke
Did you run this code on your device? For me this is not getting the correct offsets. When running the code from above, this looks much better.
I´m wondering if I got another hardware revision than you.

Using this wasn’t working for me either but there is an easy way to display text centered. This way you can use rotate with no fiddling. offset_x seem have to have no effect as where offset_y was working.

sensor:
  - platform: homeassistant
    id: outside_temp
    entity_id: sensor.akkuweather_realfeel_temperature

i2c:
  sda: GPIO5
  scl: GPIO6
  scan: true
  id: bus_i2c
  frequency: 800kHz

display:
  - platform: ssd1306_i2c
    #model: "SSD1306 72x40"
    model: "SH1106_128x64"
    rotation: 180
    update_interval: 1s
    lambda: |-
      it.printf(it.get_width()/2, it.get_height()/2, id(my_font), TextAlign::CENTER, "%.0f°C", id(outside_temp).state);

font:
  - file: 'gfonts://Inter'
    id: my_font
    size: 24
1 Like

This works for me :tada:
However not the first time I tried it.
Not sure exactly what changed, but I did unplug and re-plug power, so maybe that was required to initialise it properly after trying other configs that didn’t work.

How you are programming this ESP32 C3 72x40 OLED board , if i connect it with usb i can see only usb jtag flasing in serial ports and cant connect …

it has to be the push the button on connecting thig… some devices need one of the buttons to be pusshed so they enter on flashing mode

Mine keeps saying “Abrobot” on the display

I got it working and showing the time

i2c:
  id: bus_i2c
  sda: GPIO5
  scl: GPIO6
  scan: true
  frequency: 800kHz

time:
  - platform: homeassistant
    id: home_time

display:
  - platform: ssd1306_i2c
    model: "SSD1306 72x40"
    rotation: 0
    update_interval: 60s  
    offset_y: 0
    offset_x: 0
    invert: false  # Optional
    address: 0x3C
    lambda: |-
      it.strftime(5, 9, id(my_font), "%H:%M", id(home_time).now());

      
font:
  - id: my_font
    file: "fonts/arial.ttf"
    size: 25
1 Like

Will it work with this device and screen: https://aliexpress.com/item/1005005973391614.html (ESP32 C3 & LVGL 1.44" LCD ST7735) ?
Does anyone know?

Hi guys - I’ve got this working and taken it a whole lot further -code below. I have the display running showing the time and date - and at the bottom - a horizontal line. I also have BLE tracking running in the background… and both the blue led and display have on-off buttons in the web server…

All works prefectly - BUT the display and the LED default to OFF after power cycle… I want them to stay where they were before the cycle - gemini-cli and I have just spent 3 hours tackling this and eventually I told Gemini to give up as it was getting no-where.

If anyone knows the answer I’d really appreciate it.

Here’s the code - I’ve doctored my encryption key but the rest is a direct copy from the working unit.

Oh I used a font I had handy in the esphome folder…

esphome:
  name: abrobot
  friendly_name: abrobot

esp32:
  board: esp32-c3-devkitm-1
  framework:
    type: esp-idf

# Enable logging
#logger:
#    level: INFO

logger:
  level: DEBUG


# Enable Home Assistant API
api:
  encryption:
    key: "hmm my key"

ota:
  - platform: esphome
    password: "8e8a00104edd428a298fdd1940bfebb4"

wifi:
  ssid: !secret wifi_ssid
  password: !secret wifi_password

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

captive_portal:

web_server:
  port: 80

i2c:
  id: bus_i2c
  sda: GPIO5
  scl: GPIO6
  scan: true
  frequency: 800kHz

globals:
  - id: display_on
    type: bool
    restore_value: yes
    initial_value: 'true'

time:
  - platform: sntp
    id: current_time

display:
  - platform: ssd1306_i2c
    id: ssd1306_display
    model: "SSD1306 72x40"
    rotation: 0
    update_interval: 1s
    lambda: |-
      if (id(display_on)) {
        it.strftime(4, 1, id(font1), "%H:%M", id(current_time).now());
        it.strftime(7, 23, id(font2), "%d/%m/%y",id(current_time).now());
        if (id(current_time).now().second % 2 == 0) {
          it.horizontal_line(0, 39, 72);
          }
      }
font:
  - id: font1
    file: "fonts/Roboto-Black.ttf"
    size: 25
  - id: font2
    file: "fonts/Roboto-Black.ttf"
    size: 13

output:
  - platform: gpio
    pin:
      number: GPIO8
      inverted: true
    id: gpio_8

light:
  - platform: binary
    name: "Onboard LED"
    output: gpio_8
    restore_mode: ALWAYS_OFF

switch:
  - platform: template
    name: "Display Toggle"
    id: display_toggle
    lambda: |-
      if (id(display_on)) {
        return true;
      } else {
        return false;
      }
    turn_on_action:
      - globals.set:
          id: display_on
          value: 'true'
    turn_off_action:
      - globals.set:
          id: display_on
          value: 'false'

esp32_ble_tracker:
  scan_parameters:
    interval: 1100ms
    window: 1100ms
    active: true
  on_ble_advertise:
    then:
      - lambda: |-
          static std::map<std::string, unsigned long> last_display_time;
          unsigned long current_time = millis();
          std::string mac = x.address_str();

          if (last_display_time.find(mac) == last_display_time.end() || (current_time - last_display_time[mac] >=  20000)) 
          {
                ESP_LOGI("ble_adv", "Device: %s RSSI: %d", mac.c_str(), x.get_rssi());
                last_display_time[mac] = current_time;
              }


bluetooth_proxy:
  active: true
  connection_slots: 3
2 Likes

ChatGPT came up with the same non-working nonsense for power up defaults.

THANKYOU. Just purchased a handful of these to play with!

Thanking you for your code I reused, I am glad to help with some purely human contribution: use “restore_mode” to decide default behaviour after restart

The default should be ALWAYS_OFF, that would explain your switch’s behaviour. Switch Component - ESPHome - Smart Home Made Simple
image
BTW Not all components consider restore_mode . Check the documentation of the specific component to understand how this feature works for a particular component or device.

I used an Integer instead of boolean but the concept is yours. Cheers and sorry for my poorMAN english

These seem to vary a bit

Mine is as follows:

display:
  - platform: ssd1306_i2c
    # 72x40 - viewable window is 26,24 to 97,63
    model: "SH1106_128x64"
    rotation: 0
    update_interval: 1s  
    offset_y: 0
    offset_x: 0
    invert: false
    address: 0x3C

Trying to use SSD1306 72x40 doesn’t work. I tried the other chip model variants but none of them worked either

To confound matters further, it appears that the viewport position can be scrolled around the display

The stock firmware displays the following at startup

ESP32-C3
EGG
THE.EGG

Really what’s needed is the ability to override the X/Y resolution as well as setting origin point offset (this is done in various epaper drivers)

This is going to be “fun” to deal with