Skip to content

Instantly share code, notes, and snippets.

@vigonotion
Created June 8, 2026 17:41
Show Gist options
  • Select an option

  • Save vigonotion/6b7a015ce1708455abfc7de811be75a5 to your computer and use it in GitHub Desktop.

Select an option

Save vigonotion/6b7a015ce1708455abfc7de811be75a5 to your computer and use it in GitHub Desktop.
ESPHome config for the meeple traffic light project
# Example ESPHome configuration for a "Traffic Light" style HUB75 LED matrix display.
esphome:
name: traffic-light
on_boot:
- priority: -200
then:
- script.execute: cycle_start
esp32:
board: esp32-s3-devkitc-1
flash_size: 8MB
cpu_frequency: 240MHz
framework:
type: esp-idf
advanced:
compiler_optimization: PERF
execute_from_psram: false # Disable when using quad PSRAM
enable_idf_experimental_features: true
sdkconfig_options:
CONFIG_ESP32S3_DATA_CACHE_LINE_64B: y
psram:
mode: quad
speed: 80MHz
# Enable logging
logger:
# Enable the Home Assistant API (add an encryption key here if you want one)
api:
ota:
- platform: esphome
password: "REPLACE_WITH_YOUR_OTA_PASSWORD"
wifi:
ssid: "REPLACE_WITH_YOUR_WIFI_SSID"
password: "REPLACE_WITH_YOUR_WIFI_PASSWORD"
power_save_mode: none
fast_connect: true
# Fallback hotspot in case the wifi connection fails
ap:
ssid: "esph traffic-light"
password: "REPLACE_WITH_YOUR_AP_PASSWORD"
time:
- platform: homeassistant
id: time_ha
text_sensor:
- platform: wifi_info
ssid:
id: wifi_ssid
binary_sensor:
- platform: status
id: api_connected
sensor:
- platform: uptime
id: device_uptime
update_interval: 60s
button:
- platform: restart
icon: mdi:power-cycle
name: "ESP Reboot"
entity_category: "diagnostic"
# HUB75 LED matrix panel (single 64x64 panel)
display:
- platform: hub75
id: matrix
panel_width: 64
panel_height: 64
layout_cols: 1
board: adafruit-matrix-portal-s3
bit_depth: 4
clock_phase: false
latch_blanking: 1
clock_speed: 8MHZ
auto_clear_enabled: false
double_buffer: false
update_interval: never
# Matrix display power / brightness controls, exposed to Home Assistant
switch:
- platform: template
name: "Power"
id: power
icon: "mdi:power"
restore_mode: RESTORE_DEFAULT_ON
optimistic: true
turn_on_action:
- lvgl.resume:
- hub75.set_brightness:
id: matrix
brightness: !lambda return id(brightness).state;
turn_off_action:
- lvgl.pause:
- hub75.set_brightness:
id: matrix
brightness: 0
number:
- platform: template
name: "Brightness"
id: brightness
icon: "mdi:brightness-6"
min_value: 1
max_value: 255
step: 1
optimistic: true
restore_value: true
initial_value: 128
on_value:
then:
- if:
condition:
switch.is_on: power
then:
- hub75.set_brightness:
id: matrix
brightness: !lambda return x;
# How long the "walk" image is shown, in seconds
- platform: template
name: "Walk Duration"
id: num_walk_duration
min_value: 1
max_value: 300
step: 1
initial_value: 3
unit_of_measurement: s
optimistic: true
restore_value: true
# How long the "stop" image is shown, in seconds
- platform: template
name: "Stop Duration"
id: num_stop_duration
min_value: 1
max_value: 300
step: 1
initial_value: 6
unit_of_measurement: s
optimistic: true
restore_value: true
# The two images that are cycled on the display
image:
- file: img/meeple-walk.png
id: img_walk
type: rgb565
transparency: alpha_channel
- file: img/meeple-stop.png
id: img_stop
type: rgb565
transparency: alpha_channel
lvgl:
rotation: 180
buffer_size: 25%
disp_bg_color: black
bg_color: black
text_color: white
theme:
obj:
pad_all: 0
border_width: 0
radius: 0
bg_opa: TRANSP
text_color: white
pages:
- id: page_walk
widgets:
- image:
align: TOP_LEFT
src: img_walk
- id: page_stop
widgets:
- image:
align: TOP_LEFT
src: img_stop
# Cycle between the "walk" and "stop" pages, each shown for a configurable duration
script:
- id: cycle_start
mode: single
then:
- script.execute: ampel_stop
- id: ampel_walk
mode: single
then:
- lvgl.page.show: page_walk
- delay: !lambda "return id(num_walk_duration).state * 1000;"
- script.execute: ampel_stop
- id: ampel_stop
mode: single
then:
- lvgl.page.show: page_stop
- delay: !lambda "return id(num_stop_duration).state * 1000;"
- script.execute: ampel_walk
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment