Oled ssd1306 fails to initialize on first boot

Hi,
while testing one of my projects, I’ve noticed, that oled ssd1306 remains blank when ESP32 is first connected to power. After RST, display initializes successfully and everything works fine.

Question is, how to debug such issue?
Also, I’ve noticed, that calling update() method of oled display causes Guru Meditation Error: Core 1 panic with subsequent reboot.

I’m attaching yaml file and also the exception caused by calling display update().

esphome:
  name: bootfail
  platformio_options:
    upload_speed: 921600  
  on_boot:
    - priority: 0
      then:
        lambda: |-
            // turn on status led
            pinMode(22, OUTPUT);
            digitalWrite(22, LOW);
            delay(500); 
esp32:
  board: lolin32_lite
  framework:
    type: arduino

# Enable logging
logger:

  
font:
  - file: "fonts/Roboto-Thin.ttf"
    id: roboto
    size: 16
i2c:
  sda: GPIO16
  scl: GPIO17
  frequency: 800kHz

globals:
  - id: step
    type: int
    initial_value: "100000"
  - id: val
    type: int
    initial_value: "1000000"

display:
  - platform: ssd1306_i2c
    id: my_oled
    model: "SSD1306 128x32"
    update_interval: 50ms
    #auto_clear_enabled: false
    address: 0x3C
    lambda: |-
          it.printf(0, 0, id(roboto), "%d", id(val));
          it.printf(0, 16, id(roboto), "%d", (int)floor(log10(id(step))));


# A de-bounced GPIO is used to 'click'
binary_sensor:
  - platform: gpio
    id: rotary_encoder_btn
    pin:
      number: GPIO19
      mode:
        input: true
        pullup: true
    filters:
      - invert:
      - delayed_on: 10ms
      - delayed_off: 10ms
    on_press:
      lambda: |-
          id(my_oled).update();
INFO Reading configuration bootfail.yaml...
INFO Starting log output from COM13 with baud rate 115200
[12:14:35][D][binary_sensor:036]: 'rotary_encoder_btn': Sending state ON
[12:14:35]Guru Meditation Error: Core  1 panic'ed (StoreProhibited). Exception was unhandled.
[12:14:35]
[12:14:35]Core  1 register dump:
[12:14:35]PC      : 0x400d4240  PS      : 0x00060c30  A0      : 0x800d21f5  A1      : 0x3ffb25a0
WARNING Decoded 0x400d4240: esphome::ssd1306_base::SSD1306::fill(esphome::Color) at W:\projects\active\esphome\data\.esphome\build\bootfail/src/esphome/components/ssd1306_base/ssd1306_base.cpp:334 (discriminator 2)
[12:14:35]A2      : 0x3ffb96a0  A3      : 0x00000000  A4      : 0x00000000  A5      : 0x3f400184
[12:14:35]A6      : 0x3f400f21  A7      : 0x3f408191  A8      : 0x00000000  A9      : 0x3ffb2580
[12:14:35]A10     : 0x00000200  A11     : 0x00000080  A12     : 0x00000024  A13     : 0x3f400184
[12:14:35]A14     : 0x3ffb2bb0  A15     : 0x00000000  SAR     : 0x00000004  EXCCAUSE: 0x0000001d
[12:14:35]EXCVADDR: 0x00000000  LBEG    : 0x400868bd  LEND    : 0x400868cd  LCOUNT  : 0xffffffed
[12:14:35]
[12:14:35]
[12:14:35]Backtrace:0x400d423d:0x3ffb25a00x400d21f2:0x3ffb25c0 0x400d2625:0x3ffb25e0 0x400d416a:0x3ffb2600 0x400d6ae1:0x3ffb2620 0x400d6ace:0x3ffb2640 0x400f9bf7:0x3ffb2660 0x400f9c2b:0x3ffb2680 0x400d6b63:0x3ffb26a0 0x400d1b12:0x3ffb26c0 0x400d1e0d:0x3ffb26f0 0x400d1de2:0x3ffb2710 0x400d1e14:0x3ffb2740 0x400d1e28:0x3ffb2760 0x400d69a3:0x3ffb2780 0x400d4a4e:0x3ffb27d0 0x400d6c56:0x3ffb2800 0x400d985d:0x3ffb2820
WARNING Found stack trace! Trying to decode it
WARNING Decoded 0x400d423d: esphome::ssd1306_base::SSD1306::fill(esphome::Color) at W:\projects\active\esphome\data\.esphome\build\bootfail/src/esphome/components/ssd1306_base/ssd1306_base.cpp:334 (discriminator 2)
WARNING Decoded 0x400d21f2: esphome::display::Display::clear() at W:\projects\active\esphome\data\.esphome\build\bootfail/src/esphome/components/display/display.cpp:16
WARNING Decoded 0x400d2625: esphome::display::Display::do_update_() at W:\projects\active\esphome\data\.esphome\build\bootfail/src/esphome/components/display/display.cpp:508
WARNING Decoded 0x400d416a: esphome::ssd1306_base::SSD1306::update() at W:\projects\active\esphome\data\.esphome\build\bootfail/src/esphome/components/ssd1306_base/ssd1306_base.cpp:230
WARNING Decoded 0x400d6ae1: std::_Function_handler<void (), setup()::{lambda()#2}>::_M_invoke(std::_Any_data const&) at W:\projects\active\esphome\data\.esphome\build\bootfail/bootfail.yaml:66
 (inlined by) _M_invoke at c:\users\jimmy\.platformio\packages\toolchain-xtensa-esp32\xtensa-esp32-elf\include\c++\8.4.0\bits/std_function.h:297
WARNING Decoded 0x400d6ace: std::function<void ()>::operator()() const at c:\users\jimmy\.platformio\packages\toolchain-xtensa-esp32\xtensa-esp32-elf\include\c++\8.4.0\bits/std_function.h:687
 (inlined by) esphome::LambdaAction<>::play() at W:\projects\active\esphome\data\.esphome\build\bootfail/src/esphome/core/base_automation.h:174
WARNING Decoded 0x400f9bf7: esphome::Action<>::play_complex() at W:\projects\active\esphome\data\.esphome\build\bootfail/src/esphome/core/automation.h:125
WARNING Decoded 0x400f9c2b: esphome::ActionList<>::play() at W:\projects\active\esphome\data\.esphome\build\bootfail/src/esphome/core/automation.h:203
WARNING Decoded 0x400d6b63: esphome::Automation<>::trigger() at W:\projects\active\esphome\data\.esphome\build\bootfail/src/esphome/core/automation.h:241
 (inlined by) esphome::Trigger<>::trigger() at W:\projects\active\esphome\data\.esphome\build\bootfail/src/esphome/core/automation.h:98
 (inlined by) esphome::binary_sensor::PressTrigger::PressTrigger(esphome::binary_sensor::BinarySensor*)::{lambda(bool)#1}::operator()(bool) const at W:\projects\active\esphome\data\.esphome\build\bootfail/src/esphome\components\binary_sensor/automation.h:26
 (inlined by) std::_Function_handler<void (bool), esphome::binary_sensor::PressTrigger::PressTrigger(esphome::binary_sensor::BinarySensor*)::{lambda(bool)#1}>::_M_invoke(std::_Any_data const&, bool&&) at c:\users\jimmy\.platformio\packages\toolchain-xtensa-esp32\xtensa-esp32-elf\include\c++\8.4.0\bits/std_function.h:297
WARNING Decoded 0x400d1b12: std::function<void (bool)>::operator()(bool) const at c:\users\jimmy\.platformio\packages\toolchain-xtensa-esp32\xtensa-esp32-elf\include\c++\8.4.0\bits/std_function.h:687
 (inlined by) esphome::CallbackManager<void (bool)>::call(bool) at W:\projects\active\esphome\data\.esphome\build\bootfail/src/esphome/core/helpers.h:492
 (inlined by) esphome::binary_sensor::BinarySensor::send_state_internal(bool, bool) at W:\projects\active\esphome\data\.esphome\build\bootfail/src/esphome/components/binary_sensor/binary_sensor.cpp:41
WARNING Decoded 0x400d1e0d: esphome::binary_sensor::Filter::output(bool, bool) at W:\projects\active\esphome\data\.esphome\build\bootfail/src/esphome/components/binary_sensor/filter.cpp:17
WARNING Decoded 0x400d1de2: esphome::binary_sensor::Filter::input(bool, bool) at W:\projects\active\esphome\data\.esphome\build\bootfail/src/esphome/components/binary_sensor/filter.cpp:25
WARNING Decoded 0x400d1e14: esphome::binary_sensor::Filter::output(bool, bool) at W:\projects\active\esphome\data\.esphome\build\bootfail/src/esphome/components/binary_sensor/filter.cpp:19
WARNING Decoded 0x400d1e28: std::_Function_handler<void (), esphome::binary_sensor::DelayedOnFilter::new_value(bool, bool)::{lambda()#1}>::_M_invoke(std::_Any_data const&) at W:\projects\active\esphome\data\.esphome\build\bootfail/src/esphome/components/binary_sensor/filter.cpp:42
 (inlined by) _M_invoke at c:\users\jimmy\.platformio\packages\toolchain-xtensa-esp32\xtensa-esp32-elf\include\c++\8.4.0\bits/std_function.h:297
WARNING Decoded 0x400d69a3: std::function<void ()>::operator()() const at c:\users\jimmy\.platformio\packages\toolchain-xtensa-esp32\xtensa-esp32-elf\include\c++\8.4.0\bits/std_function.h:687
 (inlined by) esphome::Scheduler::call() at W:\projects\active\esphome\data\.esphome\build\bootfail/src/esphome/core/scheduler.cpp:234
WARNING Decoded 0x400d4a4e: esphome::Application::loop() at W:\projects\active\esphome\data\.esphome\build\bootfail/src/esphome/core/application.cpp:69
WARNING Decoded 0x400d6c56: loop() at W:\projects\active\esphome\data\.esphome\build\bootfail/bootfail.yaml:57
WARNING Decoded 0x400d985d: loopTask(void*) at C:/Users/jimmy/.platformio/packages/[email protected]/cores/esp32/main.cpp:50
[12:14:35]
[12:14:35]
[12:14:35]
[12:14:35]
[12:14:35]ELF file SHA256: 0000000000000000
[12:14:35]
[12:14:35]Rebooting...
[12:14:35]ets Jun  8 2016 00:22:57
[12:14:35]
[12:14:35]rst:0xc (SW_CPU_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)
[12:14:35]configsip: 0, SPIWP:0xee
[12:14:35]clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
[12:14:35]mode:DIO, clock div:2
[12:14:35]load:0x3fff0030,len:1184
[12:14:35]load:0x40078000,len:13132
[12:14:35]load:0x40080400,len:3036
[12:14:35]entry 0x400805e4
[12:14:35][I][logger:156]: Log initialized
[12:14:35][I][app:029]: Running through setup()...
[12:14:35][I][i2c.arduino:218]: Performing I2C bus recovery
[12:14:35][C][ssd1306_i2c:010]: Setting up I2C SSD1306...
[12:14:35][I][app:062]: setup() finished successfully!
[12:14:35][D][binary_sensor:034]: 'rotary_encoder_btn': Sending initial state OFF
[12:14:35][I][app:100]: ESPHome version 2024.5.2 compiled on May 24 2024, 12:13:53
[12:14:35][C][logger:185]: Logger:
[12:14:35][C][logger:186]:   Level: DEBUG
[12:14:35][C][logger:188]:   Log Baud Rate: 115200
[12:14:35][C][logger:189]:   Hardware UART: UART0
[12:14:35][C][i2c.arduino:071]: I2C Bus:
[12:14:35][C][i2c.arduino:072]:   SDA Pin: GPIO16
[12:14:35][C][i2c.arduino:073]:   SCL Pin: GPIO17
[12:14:35][C][i2c.arduino:074]:   Frequency: 800000 Hz
[12:14:35][C][i2c.arduino:086]:   Recovery: bus successfully recovered
[12:14:35][I][i2c.arduino:096]: Results from i2c bus scan:
[12:14:35][I][i2c.arduino:102]: Found i2c device at address 0x3C
[12:14:36][C][gpio.binary_sensor:015]: GPIO Binary Sensor 'rotary_encoder_btn'
[12:14:36][C][gpio.binary_sensor:016]:   Pin: GPIO19
[12:14:36][C][ssd1306_i2c:023]: I2C SSD1306
[12:14:36][C][ssd1306_i2c:023]:   Rotations: 0 °
[12:14:36][C][ssd1306_i2c:023]:   Dimensions: 128px x 32px
[12:14:36][C][ssd1306_i2c:024]:   Address: 0x3C
[12:14:36][C][ssd1306_i2c:025]:   Model: SSD1306 128x32
[12:14:36][C][ssd1306_i2c:027]:   External VCC: NO
[12:14:36][C][ssd1306_i2c:028]:   Flip X: YES
[12:14:36][C][ssd1306_i2c:029]:   Flip Y: YES
[12:14:36][C][ssd1306_i2c:030]:   Offset X: 0
[12:14:36][C][ssd1306_i2c:031]:   Offset Y: 0
[12:14:36][C][ssd1306_i2c:032]:   Inverted Color: NO
[12:14:36][C][ssd1306_i2c:033]:   Update Interval: 0.050s

It’s probably some kind of hardware issue. If I replace 128x32 oled module with 128x64 module, esphome can find the display module on i2c bus correctly even on first boot.

I’ve 3pcs 128x32 oled modules and they all behave the same way, on first boot, display remains blank, probably because it’s not detected during i2c scan.

If you know how to make 128x32 oled work even on first boot, plz. let me know.

Do you use these modules in your project? If so, can I ask where did you purchase them and how they are marked?

The modules I’m trying to make work are marked as
DIY MORE
OLED-091
www.diymore.cc

I have a SD1306 128x32 OLED display. I bought it several years ago, and don’t remember from where. It’s just marked 0.91 OLED.

I created a quick basic configuration and it seems to work just fine.

i2c:
  sda: GPIO18
  scl: GPIO19
  scan: True
  frequency: 800kHz

font:
  - file:
      type: gfonts
      family: Roboto
      weight: 900
    id: my_font
    size: 20

display:
  - platform: ssd1306_i2c
    id: my_display
    model: "SSD1306 128x32"
    address: 0x3C
    lambda: |-
      it.print(0, 0, id(my_font), "Hello World!");

button:
  - platform: template
    name: "Update Display"
    on_press:
      then:
        - lambda: |-
            id(my_display).update();
            ESP_LOGD("custom", "Updated Display");

Partial log:

[20:27:36][C][i2c.arduino:071]: I2C Bus:
[20:27:36][C][i2c.arduino:072]:   SDA Pin: GPIO18
[20:27:36][C][i2c.arduino:073]:   SCL Pin: GPIO19
[20:27:36][C][i2c.arduino:074]:   Frequency: 800000 Hz
[20:27:36][C][i2c.arduino:086]:   Recovery: bus successfully recovered
[20:27:36][I][i2c.arduino:096]: Results from i2c bus scan:
[20:27:36][I][i2c.arduino:102]: Found i2c device at address 0x3C
[20:27:36][C][ssd1306_i2c:023]: I2C SSD1306
[20:27:36][C][ssd1306_i2c:023]:   Rotations: 0 °
[20:27:36][C][ssd1306_i2c:023]:   Dimensions: 128px x 32px
[20:27:36][C][ssd1306_i2c:024]:   Address: 0x3C
[20:27:36][C][ssd1306_i2c:025]:   Model: SSD1306 128x32
[20:27:36][C][ssd1306_i2c:027]:   External VCC: NO
[20:27:36][C][ssd1306_i2c:028]:   Flip X: YES
[20:27:36][C][ssd1306_i2c:029]:   Flip Y: YES
[20:27:36][C][ssd1306_i2c:030]:   Offset X: 0
[20:27:36][C][ssd1306_i2c:031]:   Offset Y: 0
[20:27:36][C][ssd1306_i2c:032]:   Inverted Color: NO
[20:27:36][C][ssd1306_i2c:033]:   Update Interval: 1.0s
[20:27:36][C][captive_portal:088]: Captive Portal:
[20:27:36][C][mdns:115]: mDNS:
[20:27:36][C][mdns:116]:   Hostname: sd1306-test
[20:27:36][C][ota:096]: Over-The-Air Updates:
[20:27:36][C][ota:097]:   Address: sd1306-test.local:3232
[20:27:36][C][ota:100]:   Using Password.
[20:27:36][C][ota:103]:   OTA version: 2.
[20:27:36][C][api:139]: API Server:
[20:27:36][C][api:140]:   Address: sd1306-test.local:6053
[20:27:36][C][api:144]:   Using noise encryption: NO
[20:27:37][D][api:102]: Accepted 10.9.8.82
[20:27:37][D][api.connection:1321]: Home Assistant 2024.5.4 (10.9.8.82): Connected successfully
[20:27:51][D][button:010]: 'Update Display' Pressed.
[20:27:51][D][custom:052]: Updated Display

still not working with ssd1306 modules I’ve got, but I’ve managed to figure out workaround. Simply check the state of component one second after boot, and if it’s marked as failed, then trigger reboot.

  on_boot:
    - priority: 0
      then:
        - script.execute: oled_init_reboot
globals:
  # counts reboots due to failure to initialize display
  - id: boot_count
    type: uint16_t
    restore_value: true
    initial_value: "0"
switch:
  - platform: restart
    id: restart1
script:
  - id: oled_init_reboot
    mode: single
    then:
      - delay: 1s    
      - lambda: |-
          int display_state = id(my_display).get_component_state() & 0xff;
          int bcount = id(boot_count);
          ESP_LOGD("custom", "display state=%d boot_count=%d", display_state, bcount);
          if (display_state == 1) {
            if (bcount>0) {
              id(boot_count) = 0;
            }
          } else if (display_state == 3 && bcount<10) {
            id(boot_count) = bcount + 1;
            id(restart1).turn_on();
          }