Problem with ESP32 Heltec V2 display

Hello all, new here hoping for some help.
I’ve used the esphome add-on to successfully integrate a couple of ESP32s and an ESP8266 so far. I’ve now tried to make use of a Heltec Lora board which has an SSD1306 OLED display. I create the yaml, upload and great, the display works as expected. The problem is if I power cycle the Heltec when it comes back online the display remains blank. If I re-upload the code it works again. I think the problem is to do with the way it initialises the I2C. On successful upload I get:

[16:47:09][C][i2c:028]: I2C Bus:
[16:47:09][C][i2c:029]: SDA Pin: GPIO4
[16:47:09][C][i2c:030]: SCL Pin: GPIO15
[16:47:09][C][i2c:031]: Frequency: 50000 Hz
[16:47:09][I][i2c:033]: Scanning i2c bus for active devices…
[16:47:09][I][i2c:040]: Found i2c device at address 0x3C

and on a reboot/power cycle I get

[18:03:43][C][i2c:028]: I2C Bus:
[18:03:43][C][i2c:029]: SDA Pin: GPIO4
[18:03:43][C][i2c:030]: SCL Pin: GPIO15
[18:03:43][C][i2c:031]: Frequency: 50000 Hz
[18:03:43][I][i2c:033]: Scanning i2c bus for active devices…
[18:03:43][I][i2c:049]: Found no i2c devices!

Is there a way (using esphome) to force the Heltec to initialise the I2C before it does anything else on boot?

Oh great you succeed. !!!

I’m very happy that you can make it possible to integrate with Heltec lora v2

I have same two boards,

but I feel sorry that I have no solution for your display error.

Nevertheless, can you share the Lora custom codes for me, If you can ?

I wish you shoot the trouble in display components now.

I was wondering if you ever made headway on this. Ordered this on accident and also getting the same thing with no display. I saw that some people were adding a resistor and this seemed to help.

@drrayl - Unfortunately no I didn’t make any progress but the resistor sounds like it might be worth a try. Do you have links to the info?

  • update - found the form, suggestion was to add 10k between 5v & pin4. Tried it but still doesn’t work!
    Thanks
    Alan

@minsuke - At this stage I was only exploring the display with esphome so haven’t any useful lora code to share as yet - sorry!

Bump Bump!

Has anyone looked at this recently?

Ok after a ton of reading and testing I am reasonably certain that the following is correct for i2c

# i2c config
i2c:
  sda: 21
  scl: 22
  scan: True
  id: bus_a

however from what I gather in arduino you still need to define a reset pin under the the display config. does anyone have any ideas here?

After re-reading the initial comment I came across this note below here:

Warning!: The I2C hardware interface consists of 2 lines: SDA and SCL.
          In Arduino board definitions the names 'SDA' and 'SCL' normally
          map to the corresponding GPIO pins of the I2C interface.
          However, for the Heltec Wifi LoRa 32 V2 board 'SDA' and 'SCL'
          are incorrectly defined!: SDA is defined as 21 and SCL as 22.
          But on the Heltec Wifi LoRa 32 V2 board GPIO21 is used for switching 
          VExt output instead and is not used for SDA.
          The V2 board uses GPIO4 for SDA and GPIO15 for SCL instead.

          When using the Wire (I2C) interface in Arduino, it by default will use 
          pin definitions 'SDA' and 'SCL' which for Wifi LoRa 32 V2 are 
          incorrect! *Any any sketch and any library* that initializes the 
          Wire interface by calling Wire.begin() without parameters
          (which is common) will use the wrong pins for SDA and SCL!

          As workaround you must explicitly call Wire.begin(SDA_OLED, SCL_OLED)
          AT THE START of setup() BEFORE initializing any libraries.
          This will configure the wire interface to use
          the correct GPIO pins for SDA (4) and SCL (15).
          If you omit this then the I2C (Wire) interface and its connected
          peripherals will not work and strange things may happen to VExt.

Not entirely sure how to config that in esphome though there is a way to do Custom I2C which may fix it: Custom I²C Device — ESPHome

I have the same issue with the OLED not turning on after reboot.

=====================================
Below was my original reply to cdrom1028

This is what I used to get it working:

# i2c config
i2c:
    sda: 4
    scl: 15
    scan: True

display:
  - platform: ssd1306_i2c
    model: "SSD1306 128x64"
    reset_pin: 16
    address: 0x3C

1 Like

Add a restart switch to your esphome config.

switch:
  - platform: restart
    name: "Restart ${friendly_name}"
    id: restart_switch

And I just discovered that if you invoke that restart switch via home assistant, the screen will come back :slight_smile:

1 Like

Since I wasted way too much time on this, decided to share my solution. You’re right that a restart solves the issue. The below code works for me:

esphome:
  name: ...
  platform: ESP32
  board: heltec_wifi_lora_32_V2
  on_boot:
    then:
      - lambda: |-
          if (!id(blue_display).is_on()) {
            id(node).turn_on();
          }

switch:
  - platform: restart
    id: node

1 Like

can you please share your complete config, as I’m just about to begin with the Helctec V2. Out of curiosity: anyone managed the LORA-part ?
Thanks for pointing an ESP-noop to the right direction…

Sure. I haven’t used the LORA part, I hooked a second display and use that for my car which doesn’t have a clock. The ESP display shows temperature from a xiaomi ble sensor sticked under the hood (it’s a rear engined electric Citroen C-Zero). You can see it in action here ESP based clock with dual display and temperature display - YouTube

esphome:
  name: heltec
  platform: ESP32
  board: heltec_wifi_lora_32_V2
  on_boot:
    then:
      # Read the RTC time once when the system boots
      - ds1307.read_time:
      - delay: 5s
      # Reboot if the display didn't start. Reset daily counter (time) if needed.
      - lambda: |-
          if (!id(blue_display).is_on()) {
            id(node).turn_on();
          } else {
            if (id(last_start)!=id(esptime).now().day_of_year) {
              id(last_start) = id(esptime).now().day_of_year;
              id(day_counter) = 0;
            }
          }

image:
  - file: "logo.png"
    id: logo
#    resize: 100x100
    type: BINARY
#  - file: "mono_black.png"
#    id: czero
#    type: BINARY
    
switch:
  - platform: restart
    id: node

# Use phone hotspot to sync time if needed.
wifi:
  ssid: "Deyan's phone"
  password: "<your password>"
  reboot_timeout: 0s

# Enable logging
logger:
  level: DEBUG
  logs:
    esp32_ble_tracker: ERROR
    wifi: ERROR


text_sensor:
  - platform: template
    name: Uptime Human Readable
    id: uptime_human
    icon: mdi:clock-start

sensor:
  - platform: uptime
    name: Uptime Sensor
    id: uptime_sensor
    internal: true
    update_interval: 60s
    on_raw_value:
      then:
        - text_sensor.template.publish:
            id: uptime_human
            state: !lambda |-
              int seconds = round(id(uptime_sensor).raw_state);
              int days = seconds / (24 * 3600);
              seconds = seconds % (24 * 3600);
              int hours = seconds / 3600;
              seconds = seconds % 3600;
              int minutes = seconds /  60;
              seconds = seconds % 60;
              return (
                (days ? to_string(days) + "d " : "") +
                (hours ? to_string(hours) + "h " : "") +
                (to_string(minutes) + "m ")
              ).c_str();
        - lambda: |-
            if (round(id(uptime_sensor).raw_state) > 50){
              id(day_counter) ++;
            }
            
  - platform: pvvx_mithermometer
    mac_address: "A4:C1:38:18:00:2F"
    temperature:
      name: "PVVX Temperature"
      id: "outside_temp"
    humidity:
      name: "PVVX Humidity"
    battery_level:
      name: "PVVX Battery-Level"
      id: "outside_battery"
    battery_voltage:
      name: "PVVX Battery-Voltage"

globals:
  - id: prod
    type: int 
    restore_value: no
    initial_value: '0'
  - id: last_start
    type: int
    restore_value: yes
    initial_value: '0'
  - id: day_counter
    type: int
    restore_value: yes
    initial_value: '0'
  - id: counter
    type: int
    restore_value: no
    initial_value: '0'

preferences:
  flash_write_interval: 0s

esp32_touch:
  setup_mode: false

time:
  # This will sync the time if the ESP is connected to the hotspot.
  - platform: sntp
    id: esptimesntp
    on_time_sync:
      then:
        # ... and update the RTC when the synchronization was successful
        ds1307.write_time:
          id: esptime
  - platform: ds1307
    i2c_id: bus_b
    update_interval: never
    id: esptime

i2c:
  # Built-in display
  - id: bus_a
    sda: 4
    scl: 15
    scan: false
  # Second display
  - id: bus_b
    sda: 13
    scl: 14
    scan: false
esp32_ble_tracker:

display:

  - platform: ssd1306_i2c #white, second display
    i2c_id: bus_b
    model: "SSD1306 128x64"
    id: white_display
    rotation: 180
    address: 0x3C
    pages:
      - id: page11
        # Print the Citroen logo on the second screen until the built-in screen boots
        lambda: |-
          if (id(blue_display).is_on()){
            it.strftime(0, 45, id(font1), TextAlign::BASELINE_LEFT, "%H:%M", id(esptime).now());
          } else {
            it.image(32, 0, id(logo));
          }
  - platform: ssd1306_i2c
    i2c_id: bus_a
    model: "SSD1306 128x64"
    id: blue_display
    reset_pin: 16
    rotation: 180
#    i2c_id: bus_a
    address: 0x3C
    pages:
      - id: page1
        lambda: |-
          if (id(uptime_human).has_state()){
            it.printf(0, 22, id(font4), TextAlign::BASELINE_LEFT, "");
            if (id(day_counter) < 59) {
              it.printf(20, 22, id(font5), TextAlign::BASELINE_LEFT, "%im", id(day_counter));
            } else {
              it.printf(20, 22, id(font5), TextAlign::BASELINE_LEFT, "%i:%02dh", id(day_counter)/60, id(day_counter)%60);
            }
          }
          if (id(outside_temp).has_state()){
            it.printf(0, 52, id(font4), TextAlign::BASELINE_LEFT, "");
            it.printf(22, 52, id(font5), TextAlign::BASELINE_LEFT, "%.0f°", id(outside_temp).state);
          }

font:    
  - file: 'RobotoMono-Regular.ttf'
    id: font1
    size: 40
    glyphs: [
      "1",
      "2",
      "3",
      "4",
      "5",
      "6",
      "7",
      "8",
      "9",
      "0",
      ":",
    ]
    
#  - file: 'RobotoMono-Regular.ttf'
#    id: font2
#    size: 12

  - file: 'Tahoma.ttf'
    id: font5
    size: 22
    glyphs: [
      "1",
      "2",
      "3",
      "4",
      "5",
      "6",
      "7",
      "8",
      "9",
      "0",
      ":",
      "h",
      "m",
      " ",
      "°"
    ]

  - file: 'MaterialIcons-Regular.ttf'
    id: font4
    size: 15
    glyphs: [
      "", # battery
      "",      # piano
      "", #car
      "", #wifi_on
      "", #no wifi
      "", #car-home
      "", #temperature
      "" # clock
      ]