ESPHome and Seeed XIAO Round Display - will these work with ESPHome?

Sure thing - hope this helps.

I got most of it working - however there is no support for the TouchScreen used so that doesn’t work.

In this code, I read the CO2, temp etc of sensors in HA and then display from animated .gif files on the display. As I was not able to get the touchscreen working, I used pages and intervals to move to the next page automatically.

The result is really good, but as the board I am using (SeeedStudio XIAO C3) only has 4mb of memory - storing the GIF images was problematic. Hope this helps…

It would be awesome if the touchscreen could be made compatible with ESPHome as this round display is otherwise excellent.

substitutions:

change device name to match your desired name

device_name: “round-display-3”

change the below to be your WiFi SSID

ssid: “xxxx”

change the below to be your WiFi password

wifi_password: “xxxxx”
screenstart: ALWAYS_ON

screenstart: ALWAYS_OFF

Timeout for the screen

screensaver: 1 min
timez: Pacific/Auckland

dcpin: GPIO5 #checked okay
cspin: GPIO3 #checked okay
sckpin: GPIO8
mosipin: GPIO10

#TouchPanel
tp_int: GPIO20
sdapin: GPIO6 #checked
sclpin: GPIO7 #checked
bkpin: GPIO21 #with the KE Swith 2 on the ON position.

esphome:
name: $device_name
platformio_options:
board_build.flash_mode: dio

esp32:
board: esp32-c3-devkitm-1
variant: esp32c3
framework:
type: esp-idf

Enable logging

logger:
level: DEBUG #makes uart stream available in esphome logstream
logs:
component: ERROR

Enable Home Assistant API

api:
encryption:
key: “xxx”

ota:
password: “xxxx”

wifi:
ssid: $ssid
password: $wifi_password
use_address: xxxxx

Enable fallback hotspot (captive portal) in case wifi connection fails

ap:
ssid: “round-display-3”
password: $wifi_password
manual_ip:
# Set this to the IP of the ESP
static_ip: xxxxx
# Set this to the IP address of the router. Often ends with .1
gateway: xxxxxx
# The subnet of the network. 255.255.255.0 works for most home networks.
subnet: 255.255.255.0

captive_portal:

web_server:
port: 80
version: 2
include_internal: true

spi:
clk_pin: $sckpin
mosi_pin: $mosipin

i2c:
sda: $sdapin
scl: $sclpin
scan: true
id: i2c_bus1

time:

  • platform: homeassistant
    timezone: “$timez”
    id: esptime

qr_code:

  • id: website_qr
    value: “xxxxx”

output:

  • platform: ledc
    pin: $bkpin
    id: backlight_pwm

light:

  • platform: monochromatic
    output: backlight_pwm
    name: “Display Backlight”
    id: back_light
    restore_mode: ALWAYS_ON

text_sensor:

  • platform: homeassistant
    id: display_backlight
    entity_id: input_number.backlight_level
    internal: true
    on_value:
    then:
    - output.turn_on: backlight_pwm
    - output.set_level:
    id: backlight_pwm
    level: !lambda
    return atoi(id(display_backlight).state.c_str()) / 100.0;

display:

  • platform: ili9xxx
    model: GC9A01A
    auto_clear_enabled: True
    id: watchface
    cs_pin: $cspin
    dc_pin: $dcpin
    dimensions:
    height: 240
    width: 240
    update_interval: 0.1s
    pages:
    • id: page1
      lambda: |-
      it.printf(75,15, id(font_35), “Office:”);
      it.image(30, 65, id(co2), COLOR_ON, COLOR_OFF);
      it.printf(80,75, id(font_20), “CO2: %.0f ppm”, id(office_co2).state);
      it.image(30, 110, id(temperature), COLOR_ON, COLOR_OFF);
      it.printf(80,120, id(font_20), “Temp: %.0f °C”, id(office_temp).state);
      it.image(30, 160, id(heartrate), COLOR_ON, COLOR_OFF);
      it.printf(80,170, id(font_20), “BPM: %.0f”, id(heartrate_level).state);
      it.strftime(80,215, id(font_12), “%d-%m-%y %H:%M”, id(esptime).now());
    • id: page2
      lambda: |-
      it.printf(75,15, id(font_35), “Office:”);
      id(co2).next_frame();
      id(temperature).next_frame();
      it.image(30, 65, id(co2), COLOR_ON, COLOR_OFF);
      it.printf(80,75, id(font_20), “CO2: %.0f ppm”, id(office_co2).state);
      it.strftime(80,215, id(font_12), “%d-%m-%y %H:%M”, id(esptime).now());
    • id: page3
      lambda: |-
      it.qr_code(45, 45, id(website_qr), Color(255,255,255), 6);
    • id: page4
      lambda: |-
      it.printf(75,15, id(font_35), “Office:”);
      it.image(25, 65, id(wifi_image));
      it.printf(75,75, id(font_20), “Wifi dB: %.0f dB”, id(wifi_signal_db).state);
      it.image(25, 110, id(wifi_image));
      it.printf(75,120, id(font_20), “Wifi Signal %: %.1f%%”, id(wifi_signal_percent).state);
    • id: page5
      lambda: |-
      auto red = Color(255, 0, 0);
      it.circle(120,120,119, red);

sensor:

  • platform: homeassistant
    id: office_co2
    name: “Co2 Levels”
    entity_id: sensor.office_co2
    unit_of_measurement: “ppm”
    internal: True
  • platform: homeassistant
    id: office_temp
    name: “Temperature”
    unit_of_measurement: “°C”
    entity_id: sensor.garage_sensor_temperature
    internal: True
  • platform: homeassistant
    id: heartrate_level
    name: “Heartrate”
    unit_of_measurement: “bpm”
    entity_id: sensor.office_heartrate_level
    internal: True
  • platform: wifi_signal # Reports the WiFi signal strength/RSSI in dB
    name: “WiFi Signal dB”
    id: wifi_signal_db
    update_interval: 60s
    entity_category: “diagnostic”
  • platform: copy

    Reports the WiFi signal strength in %

    source_id: wifi_signal_db
    id: wifi_signal_percent
    name: “WiFi Signal Percent”
    filters:
    • lambda: return min(max(2 * (x + 100.0), 0.0), 100.0);
      unit_of_measurement: “%”
      entity_category: “diagnostic”
      device_class: “”

font:

  • file: “gfonts://Roboto”
    id: font_35
    size: 35
  • file: “gfonts://Roboto”
    id: font_25
    size: 25
  • file: “gfonts://Roboto”
    id: font_10
    size: 10
  • file: “gfonts://Roboto”
    id: font_12
    size: 12
  • file: “gfonts://Roboto”
    id: font_16
    size: 16
  • file: “gfonts://Roboto”
    id: font_24
    size: 24
  • file: “gfonts://Roboto”
    id: font_32
    size: 32
  • file: “gfonts://Roboto”
    id: font_20
    size: 20

animation:

  • file: “images/co2.gif”
    id: co2
    type: RGBA
  • file: “images/temperature.gif”
    id: temperature
    type: RGBA
  • file: “images/heart_rate.gif”
    id: heartrate
    type: RGBA

image:

interval:

  • interval: 0.1s
    then:
    animation.next_frame: co2
  • interval: 0.1s
    then:
    animation.next_frame: temperature
  • interval: 0.1s
    then:
    animation.next_frame: heartrate
  • interval: 5s
    then:
    • display.page.show_next: watchface
    • component.update: watchface
2 Likes