ESPHome and Pimoroni Pico Display

I bought a Pico Display from Pimoroni, and it comes with a library of software which is easy to use with plenty of examples of display possibilities, all coded in Micro Python.

However, when I decided to integrate the display into my Home Assistant set-up, things became much more complicated. I was delighted to find that ESPHome is now opening up to Pico/rpi2040 applications, but I wasted quite a bit of time at Web - ESPHome where the ESPHome Web recognised my Pico on the serial port and appeared to provision it. However, the provisioning took place with an incorrect ESP32 platform. I’m sure this is something which will soon be sorted out. In the meanwhile, the way forward is to use ESPHome (dev) in Home Assistant. You don’t need to have your 2040 attached. Go to ‘Add Device’ and select under Device Type the Raspberry Pi Pico W. This sets up the initial parameters. You can change the yaml code to reflect your needs (and especially to log in to your network). Make sure the Board type is showing up as the ‘rpipicow’. You then go to Install and select Manual Download. This creates a .uf2 file which you will use to flash your Pico via the usual method (connect to USB pressing the ‘boot’ button, drag the .uf2 file into the drive which shows up in your file manager window).

The Pimoroni Pico Display appears to have the ST7789 screen, similar to the one used in https://esphome.io/components/display/st7789v.html

I took the coding shown on the page above, and adjusted it for the pin numbers on the Pico-powered display. Crucially, the display platform is rp2040_pwm, since pwm provision has been thoughtfully made by the creators of the ESPHome 2040 API, although as yet the documentation makes no mention of it. Pwm is only necessary if you want to dim the RGB LED or the screen backlight.

esphome:
  name: picow
  friendly_name: picow


rp2040:
  board: rpipicow
  framework:
    # Required until https://github.com/platformio/platform-raspberrypi/pull/36 is merged
    platform_version: https://github.com/maxgerhardt/platform-raspberrypi.git

# Enable logging
logger:

# Enable Home Assistant API
api:
  encryption:
    key: "xxxxxxxxxxxxxxxxxxxxxxxxxx"

ota:
  password: "xxxxxxxxxxxxxxxxxxxxxx"

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

  manual_ip:
    static_ip: 192.168.1.136
    gateway: 192.168.1.1
    subnet: 255.255.255.0

  # Enable fallback hotspot in case wifi connection fails
  ap:
    ssid: "Picow Fallback Hotspot"
    password: "xxxxxxxxxxxxxxxx"

time:
  - platform: homeassistant
    id: ha_time

color:
  - id: my_red
    red: 100%
    green: 0%
    blue: 0%
  - id: my_yellow
    red: 100%
    green: 100%
    blue: 0%
  - id: my_green
    red: 0%
    green: 100%
    blue: 0%
  - id: my_blue
    red: 0%
    green: 0%
    blue: 100%
  - id: my_gray
    red: 50%
    green: 50%
    blue: 50%

font:
  - file: "fonts/helvetica.ttf"
    id: helvetica_48
    size: 48
  - file: "fonts/helvetica.ttf"
    id: helvetica_24
    size: 24
  - file: "fonts/helvetica.ttf"
    id: helvetica_12
    size: 12

binary_sensor:
  - platform: status
    name: "Node Status"
    id: system_status
  - platform: gpio
    pin:
      number: GPIO12
      inverted: true
      mode:
        input: true
        pullup: true
    name: "T-Display Button Input 0"
    id: tdisplay_button_input_0
  - platform: gpio
    pin:
      number: GPIO13
      inverted: true
    name: "T-Display Button Input 1"
    id: tdisplay_button_input_1
  - platform: gpio
    pin:
      number: GPIO14
      inverted: true
      mode:
        input: true
        pullup: true
    name: "X-button"
    id: x_button

  - platform: gpio
    pin:
      number: GPIO15
      inverted: true
      mode:
        input: true
        pullup: true
    name: "Y-button"
    id: y_button


output:
  - platform: rp2040_pwm
    pin: GPIO6
    id: gpio6
    inverted: true
    frequency: 100 Hz
  - platform: rp2040_pwm
    pin: GPIO7
    id: gpio7
    inverted: true
    frequency: 100 Hz
  - platform: rp2040_pwm
    pin: GPIO8
    id: gpio8
    frequency: 100 Hz
    inverted: true
# dimmable control of backlight
  - platform: rp2040_pwm
    pin: GPIO20
    id: backlight


light:
  - platform: monochromatic
    output: gpio6
    name: "Onboard LED-R"
  
  - platform: monochromatic
    output: gpio7
    name: "Onboard LED-G"
 
  - platform: monochromatic
    output: gpio8
    name: "Onboard LED-B"

  - platform: monochromatic
    output: backlight
    name: "Backlight"

spi:
  clk_pin: GPIO18
  mosi_pin: GPIO19

display:
  - platform: st7789v
    model: "TTGO TDisplay 135x240"
    cs_pin: GPIO17
    dc_pin: GPIO16
    reset_pin: GPIO23
    rotation: 270
    lambda: |-
      it.rectangle(0,  0, it.get_width(), it.get_height(), id(my_blue));
      it.rectangle(0, 20, it.get_width(), it.get_height(), id(my_blue));   // header bar

      it.strftime((240 / 2), (140 / 3) * 1 + 5, id(helvetica_24), id(my_gray), TextAlign::CENTER, "%d-%m-%Y", id(ha_time).now());
      it.strftime((240 / 2), (140 / 3) * 2 + 5, id(helvetica_48), id(my_gray), TextAlign::CENTER, "%H:%M:%S", id(ha_time).now());
      it.print(5, 5, id(helvetica_12), id(my_yellow), TextAlign::TOP_LEFT, "ESPHome");


      if (id(system_status).state) {
        it.print(235, 5, id(helvetica_12), id(my_green), TextAlign::TOP_RIGHT, "Online");
      }
      else {
        it.print(235, 5, id(helvetica_12), id(my_red), TextAlign::TOP_RIGHT, "Offline");
      }

      if (id(x_button).state) {
        it.print(40,30, id(helvetica_24), id(my_red), TextAlign:: TOP_LEFT, "Button X");
      }

      if (id(y_button).state) {
        it.print(40,30, id(helvetica_24), id(my_yellow), TextAlign:: TOP_LEFT, "Button Y");
      }
      

You will see that I have exposed the LED lights on the board as dimmable lights in Home Assistant, and have done the same for the backlight of the display. The four buttons are also taken into account, and could be exposed to HA as switches. Curently the buttons do very little, except to overwrite the display when X or Y are pressed for a second or two. I have not decided yet what to do with the buttons, but they are there for your project if you want to use them.

4 Likes

I have the same configuration but for some reasons I haven’t managed to get it to work.

Just to update on this in case it will help anyone else…

I have long tried to get a Piminori Pico Display Pack 2.8" working with ESPHome and constantly failed with a Raspberry Pi Pico W. I think the problem is a lack of memory on the Pico W.

Anyway, I have managed to get it to reliably work using a Raspberry Pi Pico 2 W (with the new RP2350 chip).

Note that at the time of writing the RP2350 is NOT officially supported by ESPHome.

I think the critical configuration is (this will show the time, synced from Home Assistant):

esphome:
  name: pico2w-1

rp2040:
  board: rpipico2w
  framework:
    platform_version: https://github.com/maxgerhardt/platform-raspberrypi.git#develop
    version: dev

# Enable logging
logger:
    level: DEBUG

# Enable Home Assistant API
api:
  encryption:
    key: REDACTED

ota:
  - platform: esphome
    password: REDACTED

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

time:
  - platform: homeassistant
    id: hatime

sensor:
  - platform: uptime
    type: seconds
    name: Uptime
    id: uptimesensor

output:
  - platform: rp2040_pwm
    pin: GPIO20
    id: backlight_pwm

light:
  - platform: monochromatic
    output: backlight_pwm     
    name: "Display Backlight"
    id: back_light
    restore_mode: ALWAYS_ON

spi:
  clk_pin: GPIO18
  mosi_pin: GPIO19

display:
  - platform: st7789v
    id: display_0
    model: "Custom"
    height: 320
    width: 240
    offset_height: 0
    offset_width: 0
    cs_pin: GPIO17
    dc_pin: GPIO16
    reset_pin: GPIO23
    rotation: 90
    update_interval: 1s
    lambda: |-
      // Display time with flashing :
      if (id(hatime).now().second % 2 == 0) {
        it.strftime(10, 10, id(font1), "%H:%M", id(hatime).now());
      } else {
        it.strftime(10, 10, id(font1), "%H %M", id(hatime).now());
      }

  
font:
  - file: "gfonts://Roboto"
    id: font1
    size: 20
    bpp: 8
1 Like

Like others I have struggled with this. I have eventually got the display to work with an original pico w.

It’s a little complicated as there are two available drivers( st7789v and ili9xxx) and two rendering engines ( lambda in display as in examples in this thread and lvgl).

As Steve suggests the issue is memory. I think memory is used both within the driver and in the rendering layer.

The solutions that I found worked. ( meaning no boot crash and display works - note that I haven’t tested for days or weeks of operation)

st7789v with the line
eightbitcolor: true

Added to the - platform st7789v section in the example at the top of the thread.

Or alternatively use ili9xxx as the platform and use lvgl as the render with the tag
buffer_size: 25%

In the lvgl section

1 Like