issues icon indicating copy to clipboard operation
issues copied to clipboard

Support for SH1107

Open jenscski opened this issue 2 years ago • 23 comments

The problem

I was looking for support for the SH1107 OLED driver, and found a merged PR https://github.com/esphome/esphome/pull/2967, which actually was testing on the same HW I was searching for support on, the Adafruit FeatherWing OLED - 128x64 OLED.

But I was unable to make it work, the display is only showing white noise.

2022-01-05 08 24 07

I have supplied my full config.yaml, and I'm using the example from the PR

Which version of ESPHome has the issue?

Version: 2022.1.0-dev

What type of installation are you using?

pip

Which version of Home Assistant has the issue?

No response

What platform are you using?

ESP32

Board

featheresp32

Component causing the issue

ssd1306_i2c

Example YAML snippet

esphome:
  name: oled

esp32:
  board: featheresp32
  framework:
    type: arduino

# Enable logging
logger:

i2c:

display:
  - platform: ssd1306_i2c
    model: 'SH1107_128x64'
    rotation: 90
    flip_x: false
    flip_y: false
    offset_y: -30
    lambda: |-
      it.line(0, 0, 128, 64);
      // Draw the outline of a rectangle with the top left at [5,5], a width of 10 and a height of 10
      it.rectangle(5, 5, 10, 10);
      it.circle(118, 54, 5);

Anything in the logs that might be useful for us?

[08:18:47][I][logger:214]: Log initialized
[08:18:47][I][app:029]: Running through setup()...
[08:18:47][I][i2c.arduino:159]: Performing I2C bus recovery
[08:18:47][C][ssd1306_i2c:010]: Setting up I2C SSD1306...
[08:18:48][I][app:062]: setup() finished successfully!
[08:18:48][I][app:102]: ESPHome version 2022.1.0-dev compiled on Jan  5 2022, 08:18:12
[08:18:48][C][logger:233]: Logger:
[08:18:48][C][logger:234]:   Level: DEBUG
[08:18:48][C][logger:235]:   Log Baud Rate: 115200
[08:18:48][C][logger:236]:   Hardware UART: UART0
[08:18:48][C][i2c.arduino:037]: I2C Bus:
[08:18:48][C][i2c.arduino:038]:   SDA Pin: GPIO23
[08:18:48][C][i2c.arduino:039]:   SCL Pin: GPIO22
[08:18:48][C][i2c.arduino:040]:   Frequency: 50000 Hz
[08:18:48][C][i2c.arduino:043]:   Recovery: bus successfully recovered
[08:18:48][I][i2c.arduino:053]: Results from i2c bus scan:
[08:18:48][I][i2c.arduino:059]: Found i2c device at address 0x3C
[08:18:48][C][ssd1306_i2c:023]: I2C SSD1306
[08:18:48][C][ssd1306_i2c:023]:   Rotations: 90 °
[08:18:48][C][ssd1306_i2c:023]:   Dimensions: 128px x 64px
[08:18:48][C][ssd1306_i2c:024]:   Address: 0x3C
[08:18:48][C][ssd1306_i2c:025]:   Model: SH1107 128x64
[08:18:48][C][ssd1306_i2c:027]:   External VCC: NO
[08:18:48][C][ssd1306_i2c:028]:   Flip X: NO
[08:18:48][C][ssd1306_i2c:029]:   Flip Y: NO
[08:18:48][C][ssd1306_i2c:030]:   Offset X: 0
[08:18:48][C][ssd1306_i2c:031]:   Offset Y: 226
[08:18:48][C][ssd1306_i2c:032]:   Inverted Color: NO
[08:18:48][C][ssd1306_i2c:033]:   Update Interval: 1.0s

Additional information

No response

jenscski avatar Jan 05 '22 07:01 jenscski

I encountered similar problems, and decided to compare esphome/esphome#2967 to working examples (1 2), and to the chipset datasheet.

Findings:

  • Y offset readback of 226 is expected due to an underflow (it is treated as uint8_t, 256-30=226). However, 226 works because Display Offset register of SH1107 only cares about lower 7 bits, so sending 226 or 98 is equivalent. Adafruit code has offset 0x60=96, because esphome driver starts writing at column two - unsure why.
  • Incorrect SSD1306 write mode (not SH1106/SH1107 one) was used
  • Incorrect SH1107 starting line and charge pump commands were used, but POR defaults worked well already
  • OLED data is preserved over resets/power cycles, so old text will re-appear and give illusion of things working properly. Maybe that is what happened with @arunderwood in the original PR?

Notes regarding Adafruit module specifically:

  • Only short I2C cable worked, not 50cm one
  • Adafruit code suggest that external_vcc should be set to true. This makes sense since board schematic has 3.3V->12V boost circuit.

I have rolled up all the fixes into https://github.com/nikitakuklev/esphome/tree/sh1107_fix, and it works with the following config:

external_components:
  - source: github://nikitakuklev/esphome@sh1107_fix
    components: [ ssd1306_base, ssd1306_i2c ]

sensor:
  - platform: uptime
    name: Uptime Sensor
    id: uptime_sensor
    update_interval: 0.1s
    
display:
  - platform: ssd1306_i2c
    model: 'SH1107_128x64'
    rotation: 90
    flip_x: false
    flip_y: false
    offset_y: 96
    offset_x: 0
    external_vcc: true
    update_interval: 1.0s
    lambda: |-
      it.line(0, 0, 128, 64);
      it.rectangle(5, 5, 10, 10);
      it.circle(118, 54, 5);
      it.rectangle(0, 0, 128, 64);
      it.filled_circle(((int)id(uptime_sensor).state)*10 % 128, it.get_height() / 2, 10);

Will submit a PR, but first some independent testing would be appreciated (above config will pull the corrected files). You should see a circle moving across the screen.

nikitakuklev avatar Jan 17 '22 08:01 nikitakuklev

I can confirm, it fixed the problem. Thanks a loot!

randybb avatar Jan 17 '22 11:01 randybb

I can also confirm, it works.

Thanks

jenscski avatar Jan 17 '22 20:01 jenscski

Cool! Is this fix only for I2C? What about SPI OLED's? For me it's not working... only a small part of the screen.

IMG_3671

[17:37:11][C][logger:233]: Logger:
[17:37:11][C][logger:234]:   Level: DEBUG
[17:37:11][C][logger:235]:   Log Baud Rate: 115200
[17:37:11][C][logger:236]:   Hardware UART: UART0
[17:37:11][C][spi:097]: SPI bus:
[17:37:11][C][spi:098]:   CLK Pin: GPIO18
[17:37:11][C][spi:100]:   MOSI Pin: GPIO23
[17:37:11][C][spi:102]:   Using HW SPI: YES
[17:37:12][C][uptime.sensor:031]: Uptime Sensor 'Uptime Sensor'
[17:37:12][C][uptime.sensor:031]:   State Class: 'total_increasing'
[17:37:12][C][uptime.sensor:031]:   Unit of Measurement: 's'
[17:37:12][C][uptime.sensor:031]:   Accuracy Decimals: 0
[17:37:12][C][uptime.sensor:031]:   Icon: 'mdi:timer-outline'
[17:37:12][C][ssd1306_spi:019]: SPI SSD1306
[17:37:12][C][ssd1306_spi:019]:   Rotations: 90 °
[17:37:12][C][ssd1306_spi:019]:   Dimensions: 128px x 64px
[17:37:12][C][ssd1306_spi:020]:   Model: SH1107 128x64
[17:37:12][C][ssd1306_spi:021]:   CS Pin: GPIO14
[17:37:12][C][ssd1306_spi:022]:   DC Pin: GPIO27
[17:37:12][C][ssd1306_spi:023]:   Reset Pin: GPIO33
[17:37:12][C][ssd1306_spi:024]:   External VCC: YES
[17:37:12][C][ssd1306_spi:025]:   Flip X: NO
[17:37:12][C][ssd1306_spi:026]:   Flip Y: NO
[17:37:12][C][ssd1306_spi:027]:   Offset X: 0
[17:37:12][C][ssd1306_spi:028]:   Offset Y: 96
[17:37:12][C][ssd1306_spi:029]:   Inverted Color: NO
[17:37:12][C][ssd1306_spi:030]:   Update Interval: 1.0s
[17:37:12][C][web_server:162]: Web Server:
[17:37:12][C][web_server:163]:   Address: m5stack_hass.local:80
[17:37:12][D][sensor:113]: 'Uptime Sensor': Sending state 5.93100 s with 0 decimals of accuracy

Config:

display:
  - platform: ssd1306_spi
    model: 'SH1107_128x64'
    rotation: 90
    flip_x: false
    flip_y: false
    offset_y: 96
    offset_x: 0
    reset_pin: 33
    external_vcc: true
    cs_pin: 14
    dc_pin: 27
    lambda: |-
      it.line(0, 0, 128, 64);
      it.rectangle(5, 5, 10, 10);
      it.circle(118, 54, 5);
      it.rectangle(0, 0, 128, 64);
      it.filled_circle(((int)id(uptime_sensor).state)*10 % 128, it.get_height() / 2, 10);

rpaludo avatar Jan 18 '22 20:01 rpaludo

What hardware are you using? Link to product?

jenscski avatar Jan 18 '22 20:01 jenscski

What hardware are you using? Link to product?

Old version of M5 Stick:

https://docs.m5stack.com/en/core/m5stick

It uses: OLED Screen 1.3 inch, 64 x 128, SH1107

rpaludo avatar Jan 18 '22 20:01 rpaludo

Looks like the SPI implementation needs an small update. If you are lucky, perhaps @nikitakuklev can fix in the branch.

jenscski avatar Jan 18 '22 21:01 jenscski

I don't have a SPI module to test, so just copied I2C changes into SPI component. @rpaludo, can you see if these work? You will need to modify config to include:

external_components:
  - source: github://nikitakuklev/esphome@sh1107_fix
    components: [ ssd1306_base, ssd1306_i2c, ssd1306_spi ]

nikitakuklev avatar Jan 18 '22 23:01 nikitakuklev

All right! It worked like a charm. Thanks @nikitakuklev and @jenscski.

M5 Stick

rpaludo avatar Jan 19 '22 19:01 rpaludo

I can confirm this fixes the static screen for my esp8266 huzzah with Adafruit FeatherWing OLED screen as well. I do get a red x in the yaml for the offset_y with the message "value must be at most 32", but it allows installing and works properly only with 96. Not sure if that is expected or not.

image

image

c0bra99 avatar Jan 25 '22 22:01 c0bra99

Which YAML editor are you using? This probably happens because there is a change in the external_components library.

rpaludo avatar Jan 25 '22 22:01 rpaludo

It's the default editor that pops up when you click the "EDIT" button in ESPHome inside of Home Assistant. I'm using ESPHome version 2022.1.2, with Home Assistant version 2021.12.10

Interesting, I went back to get another screenshot and now the red x is gone. I had saved/closed the editor multiple times while changing the lambda around and the red x stayed there. I think doing a new browser window may have fixed it?

Probably safe to disregard that issue, everything is working great for me so far.

c0bra99 avatar Jan 25 '22 23:01 c0bra99

The red x issue was probably due it not fetching files before first compilation - part of patch changes offset limits (it was -32 to 32 before).

I came upon another issue with Adafruit module specifically - when using I2C connector, it sometime takes several tries to get the screen working from a cold power up. I suspect it has something to do with SH1107 power-up sequence requirements, the APX803 reset circuit on OLED board (150ms delay from power on before SH1107 is released from reset), and lack of direct reset pin control (unlike in case of soldered shield). The issue seems random, and was not fixable with artificial command delays/slow I2C frequency. A viable but ugly fix was adding:

  on_boot:
    priority: -100
    then:
      - lambda: |-  
          App.feed_wdt();
          delay(500);
          // disp is oled id
          id(disp).setup();
          id(disp).setup();
          id(disp).setup();
          id(disp).setup();
          id(disp).setup();

However, since things work for everyone else it is prudent to proceed - will make a pull request on the weekend.

nikitakuklev avatar Jan 26 '22 02:01 nikitakuklev

Has this been fixed? Planning to buy a SH1107 display.

nstrelow avatar Jun 25 '22 10:06 nstrelow

@nikitakuklev Where you able to submit your fixes to the main repo?

I am trying to get the M5Stack OLED SH1107 working. It's I2C.

https://docs.m5stack.com/en/unit/oled

nstrelow avatar Jul 09 '22 08:07 nstrelow

@nstrelow I am trying to get the M5 Stack SH1107 OLED display but all I get is the random dots all over. I tried a few of the code sample above but it doesn't even compile. Should it work or is it not fully supported yet?

Based on this https://esphome.io/components/display/ssd1306.html?highlight=sh1107 I thought it would work.

alexruffell avatar Jul 28 '22 05:07 alexruffell

@alexruffell I couldn't get it working, the M5 display works a bit different apparently. The code above with the -96 is also not working.

nstrelow avatar Jul 28 '22 07:07 nstrelow

That is weird - is anything different between above M5 stick that was reported as working and yours? Different revision?

I will rebase my patches as potential fix, but won't have time for proper pull request until a few week from now.

nikitakuklev avatar Jul 28 '22 08:07 nikitakuklev

@nikitakuklev At the web page provided by @nstrelow ( https://docs.m5stack.com/en/unit/oled ) there are schematics, a library and code samples but none for ESP. Maybe those may help.

alexruffell avatar Jul 28 '22 17:07 alexruffell

@nikitakuklev I haven't tried your fix for the Adafruit module, maybe that works. It'll try at some point.

One thing that definitly didn't work, was the offset_y: 96, were it complained it could only offset up to 32.

nstrelow avatar Jul 28 '22 22:07 nstrelow

Ok, I can set the offset_y: 96, just the editor complains.

But I get the following error on compile on the newest esphome. Probably a rebase is needed. @nikitakuklev did you find the time? 😁

src/esphome/components/ssd1306_base/ssd1306_base.cpp: In member function 'virtual void esphome::ssd1306_base::SSD1306::setup()':
src/esphome/components/ssd1306_base/ssd1306_base.cpp:120:12: warning: enumeration value 'SH1107_MODEL_128_64' not handled in switch [-Wswitch]
     switch (this->model_) {
            ^
Compiling /data/m5stack-atom-speaker-kit/.pioenvs/m5stack-atom-speaker-kit/src/esphome/components/web_server_base/web_server_base.cpp.o
Compiling /data/m5stack-atom-speaker-kit/.pioenvs/m5stack-atom-speaker-kit/src/esphome/components/wifi/wifi_component.cpp.o
Compiling /data/m5stack-atom-speaker-kit/.pioenvs/m5stack-atom-speaker-kit/src/esphome/components/wifi/wifi_component_esp32_arduino.cpp.o
Compiling /data/m5stack-atom-speaker-kit/.pioenvs/m5stack-atom-speaker-kit/src/esphome/components/wifi/wifi_component_esp8266.cpp.o
Compiling /data/m5stack-atom-speaker-kit/.pioenvs/m5stack-atom-speaker-kit/src/esphome/components/wifi/wifi_component_esp_idf.cpp.o
Compiling /data/m5stack-atom-speaker-kit/.pioenvs/m5stack-atom-speaker-kit/src/esphome/core/application.cpp.o
Compiling /data/m5stack-atom-speaker-kit/.pioenvs/m5stack-atom-speaker-kit/src/esphome/core/color.cpp.o
Compiling /data/m5stack-atom-speaker-kit/.pioenvs/m5stack-atom-speaker-kit/src/esphome/core/component.cpp.o
Compiling /data/m5stack-atom-speaker-kit/.pioenvs/m5stack-atom-speaker-kit/src/esphome/core/component_iterator.cpp.o
Compiling /data/m5stack-atom-speaker-kit/.pioenvs/m5stack-atom-speaker-kit/src/esphome/core/controller.cpp.o
Compiling /data/m5stack-atom-speaker-kit/.pioenvs/m5stack-atom-speaker-kit/src/esphome/core/entity_base.cpp.o
Compiling /data/m5stack-atom-speaker-kit/.pioenvs/m5stack-atom-speaker-kit/src/esphome/core/helpers.cpp.o
Compiling /data/m5stack-atom-speaker-kit/.pioenvs/m5stack-atom-speaker-kit/src/esphome/core/log.cpp.o
Compiling /data/m5stack-atom-speaker-kit/.pioenvs/m5stack-atom-speaker-kit/src/esphome/core/scheduler.cpp.o
Compiling /data/m5stack-atom-speaker-kit/.pioenvs/m5stack-atom-speaker-kit/src/esphome/core/util.cpp.o
Compiling /data/m5stack-atom-speaker-kit/.pioenvs/m5stack-atom-speaker-kit/src/main.cpp.o
Generating partitions /data/m5stack-atom-speaker-kit/.pioenvs/m5stack-atom-speaker-kit/partitions.bin
Compiling /data/m5stack-atom-speaker-kit/.pioenvs/m5stack-atom-speaker-kit/lib528/AsyncTCP-esphome/AsyncTCP.cpp.o
Compiling /data/m5stack-atom-speaker-kit/.pioenvs/m5stack-atom-speaker-kit/lib64d/WiFi/ETH.cpp.o
Compiling /data/m5stack-atom-speaker-kit/.pioenvs/m5stack-atom-speaker-kit/lib64d/WiFi/WiFi.cpp.o
Compiling /data/m5stack-atom-speaker-kit/.pioenvs/m5stack-atom-speaker-kit/lib64d/WiFi/WiFiAP.cpp.o
Compiling /data/m5stack-atom-speaker-kit/.pioenvs/m5stack-atom-speaker-kit/lib64d/WiFi/WiFiClient.cpp.o
Archiving /data/m5stack-atom-speaker-kit/.pioenvs/m5stack-atom-speaker-kit/lib528/libAsyncTCP-esphome.a
Compiling /data/m5stack-atom-speaker-kit/.pioenvs/m5stack-atom-speaker-kit/lib64d/WiFi/WiFiGeneric.cpp.o
src/main.cpp: In function 'void setup()':
src/main.cpp:895:38: error: invalid new-expression of abstract class type 'esphome::ssd1306_i2c::I2CSSD1306'
   disp = new ssd1306_i2c::I2CSSD1306();
                                      ^
In file included from src/esphome.h:62:0,
                 from src/main.cpp:3:
src/esphome/components/ssd1306_i2c/ssd1306_i2c.h:10:7: note:   because the following virtual functions are pure within 'esphome::ssd1306_i2c::I2CSSD1306':
 class I2CSSD1306 : public ssd1306_base::SSD1306, public i2c::I2CDevice {
       ^
In file included from src/esphome.h:17:0,
                 from src/main.cpp:3:
src/esphome/components/display/display_buffer.h:373:23: note: 	virtual esphome::display::DisplayType esphome::display::DisplayBuffer::get_display_type()
   virtual DisplayType get_display_type() = 0;
                       ^

nstrelow avatar Aug 08 '22 19:08 nstrelow

I've done a rebase on the current esphome dev branch, with a couple of additional quick fixes. It's available here: https://github.com/bekriebel/esphome/tree/sh1107_fix. This is working for me, but I'm seeing the initial startup issue sometimes occurring. The on_boot fix doesn't seem to fix it for me, though.

bekriebel avatar Oct 11 '22 17:10 bekriebel

@bekriebel Awesome I am FINALLY seeing something on my screen. Thanks so much 🥳

nstrelow avatar Oct 12 '22 18:10 nstrelow

Thank you to nikitakuklev and bekriebel; your fixes did the trick for me

grape-nuts avatar Nov 13 '22 10:11 grape-nuts

I finally got my M5 Stack SH1107 display to work! Thank you!

image

This is the code I had to use, note the offset_x is set to 32 otherwise the rectangle was half off the screen. It took a bit of open/close/refresh of esphome for it to stop complaining about the offset_y: 96 setting.

i2c:
  - id: bus_a
    sda: 33
    scl: 32
    scan: true

external_components:
  - source: github://bekriebel/esphome@sh1107_fix
    components: [ ssd1306_base, ssd1306_i2c ]

display:
  - platform: ssd1306_i2c
    model: 'SH1107_128x64'
    rotation: 90
    flip_x: false
    flip_y: false
    offset_y: 96
    offset_x: 32
    external_vcc: true
    update_interval: 1.0s
    lambda: |-
      it.line(0, 0, 128, 64);
      it.rectangle(5, 5, 10, 10);
      it.circle(118, 54, 5);
      it.rectangle(0, 0, 128, 64);
      it.filled_circle(((int)id(uptime_sensor).state)*10 % 128, it.get_height() / 2, 10);

sensor:
  - platform: uptime
    name: Uptime Sensor
    id: uptime_sensor
    update_interval: 0.1s

EDIT: Is there any chance this fix will make it to the standard distribution of esphome?

alexruffell avatar Nov 27 '22 02:11 alexruffell

Also got a 128x128 SH1107 display working with this fix. Thank you @nikitakuklev and @bekriebel! :)

Only had to include a few small tweaks to the code to add SH1107_MODEL_128_128 definition, specifying the correct height and width. Made an extra commit from @bekriebel branch, https://github.com/jacobparra/esphome/tree/sh1107_fix

Here is the config used. offset_y set to 0, but offset_x value seems to not affect (tried with 32 and 96).

i2c:
  scan: true
  sda: GPIO26
  scl: GPIO27

external_components:
  - source: github://jacobparra/esphome@sh1107_fix
    components: [ ssd1306_base, ssd1306_i2c ]

display:
  - platform: ssd1306_i2c
    model: 'SH1107_128x128'
    rotation: 0
    flip_x: false
    flip_y: false
    offset_y: 0
    offset_x: 0
    external_vcc: true
    update_interval: 1.0s
    lambda: |-
      it.line(0, 0, 128, 128);
      it.rectangle(5, 5, 10, 10);
      it.circle(118, 54, 5);
      it.rectangle(0, 0, 128, 128);
      it.filled_circle(((int)id(uptime_sensor).state)*10 % 128, it.get_height() / 2, 10);

sensor:
  - platform: uptime
    name: Uptime Sensor
    id: uptime_sensor
    update_interval: 0.1s

PXL_20221212_192209158

BTW, display tested is from TZT 1.5 inch OLED 4pin. In the back it reads 1.5" GME128128-01-IIC ver:2.0, Dots:128*128, IC:SH1107

Following @alexruffell comment, maybe the whole fix could make it to esphome repo.

jacobparra avatar Dec 12 '22 19:12 jacobparra

Has anyone tried to use this with PicoW? I bought a Waveshare 1.3 OLED, using above configuration with i2c without any luck. Any ideas, suggestions?

gurselt avatar Apr 20 '23 04:04 gurselt

@bekriebel and @nikitakuklev confirming this (rebased) fix works with ESPHome 2023.5.5 on a FeatherS2 with FeatherWing OLED - 128x64.

Please make a PR to the main ESPHome repo for this.

nagyrobi avatar Jun 06 '23 17:06 nagyrobi

@bekriebel @jacobparra @nikitakuklev this patch broke today with the release of ESPHome 2023.6.0. Screen is all white.

nagyrobi avatar Jun 22 '23 08:06 nagyrobi

Definitely Broken! See the attached image...

@bekriebel @jacobparra @nikitakuklev this patch broke today with the release of ESPHome 2023.6.0. Screen is all white.

0

zeb146146 avatar Jun 22 '23 10:06 zeb146146