esphome matrix clock

This commit is contained in:
root
2026-05-24 18:02:18 +12:00
parent 7eb81efd93
commit dd4cee94d1
8 changed files with 21694 additions and 1674 deletions
+119 -21
View File
@@ -2,12 +2,19 @@
# TITLE: LED MATRIX 1
# zorruno.com layout v1.1 2026
# ESP32-C3 SuperMini MAX7219 LED matrix clock and scroll display.
#:########################################################################################:#
# REFERENCES:
# Original Project Reference https://github.com/RealDeco/matrixclock-esphome
# Fonts: https://github.com/RealDeco/matrixclock-esphome/tree/main/fonts
# 3D Printed Case (includes project notes in the 3mf files)
# https://github.com/RealDeco/matrixclock-esphome/tree/main/3DPrint
#:########################################################################################:#
# REPO:
# https://home.fox.co.nz/gitea/zorruno/zorruno-homeassistant/src/branch/master/esphome/esp-ledmatrix1.yaml
#:########################################################################################:#
# VERSIONS:
# V1.3 2026-05-24 Added native API action for Home Assistant direct scroll text commands.
# V1.2 2026-05-24 Added 1-15 brightness level slider and improved operation notes.
# V1.1 2026-05-23 Updated yaml to zorruno layout V1.1, cleaned comments, fixed SNTP time IDs,
# added current_mins fallback display, removed unused MQTT topic, and fixed
# blank scroll handling.
@@ -20,31 +27,50 @@
# - MOSI: GPIO8
# - CS: GPIO9
# - SCK: GPIO10
# - Power note: 4 MAX7219 modules may need a suitable external 5 V supply.
# - Power note: 4 MAX7219 modules needs a suitable external 5 V supply.
# - Keep ESP32-C3 GND and matrix power supply GND connected together.
#:########################################################################################:#
# FONTS:
# Dragon Font: https://www.freebestfonts.com/eight-bit-dragon-font
# 5x8 Font: https://developer.lasec.com.mx/armando/rpi-rgb-led-matrix/-/blob/master/fonts/5x8.bdf
#:########################################################################################:#
# OPERATION NOTES:
# - Displays the current time from common/sntp_common.yaml using id(sntp_time).
# - If SNTP is invalid, the display falls back to id(current_mins) from common/sntp_common.yaml.
# - 12h/24h display mode is selectable from Home Assistant or MQTT.
# - Display brightness is exposed as a Home Assistant light entity.
# - Brightness accepts values 0..15 where 0 turns the display off and 1..15 sets intensity.
# - Scroll Text is exposed as a Home Assistant text entity and clears itself after use.
# - Before any scroll starts, the clock slides down and off the display.
# - After scroll ends, the selected re-entry effect runs: Slide up, Slide down, or Pixel fall.
# - Pixel fall hides the clock until the effect finishes, avoiding a clock-under-particles look.
# - Scroll speed is adjustable using the Scroll Delay number entity.
# - Main display:
# - Shows a 32 x 8 LED matrix clock using the MAX7219 display component.
# - Uses common/sntp_common.yaml as the primary time source via id(sntp_time).
# - If SNTP is not valid, uses id(current_mins) as a fallback clock.
# - In fallback mode the colon stays solid, so it is obvious time is not fully synced.
#
# - Clock controls:
# - Clock format can be selected as 12h or 24h from Home Assistant or MQTT.
# - 12h mode draws a small A or P indicator at the far right of the display.
#
# - Brightness controls:
# - The Display light entity can turn the matrix on/off and set proportional brightness.
# - The Brightness Level number slider sets the exact MAX7219 intensity from 1 to 15.
# - MQTT brightness accepts 0 to turn the display off, or 1-15 to set exact intensity.
# - The 1-15 slider keeps the last non-zero brightness value when the display is off.
#
# - Scroll text controls:
# - Scroll Text is exposed as a Home Assistant text entity.
# - Native API action esphome.esp_ledmatrix1_scroll_text can scroll text directly from Home Assistant.
# - The text box clears itself after a valid scroll request is accepted.
# - Empty scroll requests are ignored and do not replay the previous message.
# - Scroll Delay controls the delay in milliseconds between scroll steps.
#
# - Scroll transitions:
# - Before scrolling, the clock always slides down and off the display.
# - After scrolling, the selected re-entry effect runs.
# - Available re-entry effects are Slide up, Slide down, and Pixel fall.
# - Pixel fall hides the clock until the particle effect finishes.
#:########################################################################################:#
# MQTT COMMANDS:
# - ${mqtt_command_topic}/scroll : Text payload to scroll once across the display.
# - ${mqtt_command_topic}/mode : Payload 12 or 24 to select clock format.
# - ${mqtt_command_topic}/bright : Payload 0 turns display off, 1-15 sets brightness.
# - ${mqtt_command_topic}/bright : Payload 0 turns display off, 1-15 sets exact brightness.
# - ${mqtt_status_topic}/status : Publishes online/offline status.
#:########################################################################################:#
# HOME ASSISTANT API ACTIONS:
# - esphome.esp_ledmatrix1_scroll_text
# data:
# message: "Text to scroll"
#:########################################################################################:#
# OFFLINE NOTES:
# a) Home Assistant offline, but WiFi/network and MQTT online:
# - Clock display should continue using SNTP if the NTP servers are reachable.
@@ -75,7 +101,7 @@ substitutions:
# Project Naming
project_name: "Generic.ESP32 Supermini"
project_version: "v1.1"
project_version: "v1.3"
# Passwords & Secrets
api_key: !secret esp-api_key
@@ -103,6 +129,7 @@ substitutions:
pin_sck: GPIO10
num_chips: "4"
scroll_delay_ms: "15" # ms between scroll steps
matrix_initial_brightness: "2" # Default MAX7219 intensity, 1-15.
y_offset: "0"
y_scroll_offset: "0"
@@ -176,6 +203,11 @@ esp32:
type: esp-idf
version: recommended
#esp8266:
# board: esp01_1m
# early_pin_init: false # Recommended false where switches are involved. Defaults to true.
# board_flash_mode: dout # Default is dout.
#:########################################################################################:#
# LOGGER: ESPHome Logging Enable
# https://esphome.io/components/logger.html
@@ -186,6 +218,37 @@ logger:
#esp8266_store_log_strings_in_flash: false
#tx_buffer_size: 64
#:########################################################################################:#
# API COMPONENT: Device-specific Home Assistant native API actions
# https://esphome.io/components/api.html
#:########################################################################################:#
api:
actions:
# Home Assistant action: esphome.esp_ledmatrix1_scroll_text
# Example HA data: { message: "Hello from Home Assistant" }
- action: scroll_text
variables:
message: string
then:
- lambda: |-
std::string s = message;
s.erase(std::remove(s.begin(), s.end(), '\r'), s.end());
s.erase(std::remove(s.begin(), s.end(), '\n'), s.end());
s.erase(std::remove_if(s.begin(), s.end(),
[](unsigned char c){ return c < 0x20; }), s.end());
// Ignore empty API scroll commands completely.
if (s.empty()) return;
// Keep the HA text entity visually in sync with this direct API action.
id(ha_scroll_text).publish_state(s.c_str());
id(scroll_text) = s;
id(scroll_x) = ${num_chips} * 8;
id(start_scroll_sequence).execute();
id(clear_scroll_text_box).execute();
#:########################################################################################:#
# GLOBALS:
# https://esphome.io/components/globals.html
@@ -218,11 +281,18 @@ globals:
restore_value: true
initial_value: '${scroll_delay_ms}'
# MAX7219 intensity: 0=OFF, 1..15=ON. Driven by the HA light entity.
# MAX7219 intensity: 0=OFF, 1..15=ON. Driven by the HA light and brightness slider.
- id: matrix_intensity
type: int
restore_value: false
initial_value: '2'
initial_value: '${matrix_initial_brightness}'
# Last non-zero brightness level selected by HA, MQTT, or the 1-15 slider.
# This allows the exact slider to keep its value when the display is switched off.
- id: matrix_last_nonzero_intensity
type: int
restore_value: true
initial_value: '${matrix_initial_brightness}'
# Brightness sync loop protection for HA light <-> MQTT brightness updates.
- id: suppress_mqtt_bright_sync
@@ -362,6 +432,9 @@ mqtt:
if (v == 0) {
id(matrix_light).turn_off().perform();
} else {
id(matrix_last_nonzero_intensity) = v;
id(matrix_brightness_number).publish_state((float) v);
auto call = id(matrix_light).turn_on();
call.set_brightness((float) v / 15.0f);
call.perform();
@@ -422,12 +495,35 @@ number:
- lambda: |-
id(scroll_delay_runtime) = (int) x;
- platform: template
id: matrix_brightness_number
name: "${friendly_name} Brightness Level"
icon: "mdi:brightness-6"
min_value: 1
max_value: 15
step: 1
restore_value: true
initial_value: ${matrix_initial_brightness}
optimistic: true
set_action:
- lambda: |-
int v = (int) lroundf(x);
if (v < 1) v = 1;
if (v > 15) v = 15;
id(matrix_last_nonzero_intensity) = v;
// Setting the exact brightness slider also turns the display on.
auto call = id(matrix_light).turn_on();
call.set_brightness((float) v / 15.0f);
call.perform();
#:########################################################################################:#
# OUTPUT COMPONENT:
# https://esphome.io/components/output/
#:########################################################################################:#
output:
# Template output lets the HA light slider control MAX7219 intensity.
# Template output lets the HA light and brightness slider control MAX7219 intensity.
- platform: template
id: matrix_brightness_out
type: float
@@ -445,6 +541,8 @@ output:
if (v > 15) v = 15;
id(matrix_intensity) = v;
id(matrix_last_nonzero_intensity) = v;
id(matrix_brightness_number).publish_state((float) v);
id(matrix).turn_on_off(true);
pub = v;
}
@@ -815,4 +913,4 @@ display:
int y2 = y + 5;
if (y1 >= 0 && y1 <= 7) it.draw_pixel_at(x_col, y1, Color::WHITE);
if (y2 >= 0 && y2 <= 7) it.draw_pixel_at(x_col, y2, Color::WHITE);
}
}