SSD1306 / SH1106 OLED display

Overview

ManufacturerSolomon systech
NameSSD1306 or SH1106
DatasheetSSD1306.pdf
AdafruitMonochrome OLED breakouts, adafruit/Adafruit_SSD1306
Arduino referenceAdafruit SSD1306
ESPHome componentssd1306_i2c1 and display2
ESPHome configpackages/displays/ssd1306.yml3
Supply voltage, some breakout boards also support .

These OLED displays have two different chipsets -- the more comon SSD1306 or SH1106 which seems to be more common on the larger 1.3" models.

ESPHome config

Note

Both the SSD1306 and SH1106 displays are available with either I²C or SPI interfaces. But all of mine have I²C interfaces so this page only talks about the ssd1306_i2c component.

Using a display with an SPI interface should be very similar, apart from using the spi component instead of the i2c component.

For more info, see the [ssd1306 component in ESPHome](https://esphome.io/components/display/ssd1306#over-spi).

First set up an I²C bus first for the display:

i2c: - sda: ${sda_gpio_pin} scl: ${scl_gpio_pin} id: i2c_ssd1306

Most ESP32 boards have 2+ I²C interfaces that can be used with any available GPIO pins. Keep in mind that I²C uses the pins for both input and output, so avoid using any strapping pins.

Configure the ssd1306_i2c1 component for your display:

display: - platform: ssd1306_i2c id: ssd1306 # or 'SH1106' model: "SSD1306 128x64" address: 0x3C i2c_id: i2c_ssd1306 lambda: |- it.printf(0, 30, id(font_id), TextAlign::BASELINE_LEFT, "sudo.is");

Both the chipset model and dimensions are configured as a string in the model config item.

On/off switch

It is possible to turn off the display. While it is not exposed as a switch component in the ssd1306 component, the C++ API4 provides the turn_on(), turn_off() and is_on() functions.

We can use lambdas to call them, and template a switch component to control it and represent the state.

switch: - platform: template name: "${hostname} Display" id: ssd1306_switch_display internal: false disabled_by_default: false lambda: |- return id(ssd1306).is_on(); turn_on_action: - lambda: |- id(ssd1306).turn_on(); turn_off_action: - lambda: |- id(ssd1306).turn_off();

When turn_off() is called, the display gets fully powered off.

Brightness control

Note

The contrast config entry in the ssd1306 component is the initial contrast.

The C++ SSD1306 class API4 provides the functions set_contrast() and get_contrast(). Contrast basically works the same as brightness, so we can use that instead, with the same effect.

Template a number component to control the brightness/contrast by calling set_contrast:

number: - platform: template id: "ssd1306_contrast" name: "${hostname} Display" min_value: 0 max_value: 100 step: 0 entity_category: "" unit_of_measurement: "%" device_class: power_factor mode: slider update_interval: 5s lambda: |- float contrast = id(ssd1306).get_contrast(); return int(contrast*100); set_action: - lambda: |- id(ssd1306).set_contrast(x/100);

The get_contrast() function was added in my pull request esphome#6435 and was merged in ESPHome 2024.4.0.

It should also be possible to use a templated output component and then configure a light component using the monochromatic platform for a nicer presentation in Home Assistant.

Font

I've found that the font Noto Sans Mono looks good on this display.

SSD1306

Put the NotoSansMono-Regular.ttf file somewhere ESPHome can find it, and then configure2 the display to use it.

font: - file: "../fonts/NotoSansMono-Regular.ttf" id: notomono24 size: 24 display: - platform: ssd1306_i2c id: ssd1306 model: "SSD1306 128x64" address: 0x3C i2c_id: i2c_ssd1306 lambda: |- it.printf(127, 30, id(notomono24), TextAlign::BASELINE_LEFT, "sudo.is");

Unfortunately you need to specify a font entry for each font size you want to use.

References