esphome matrix clock
This commit is contained in:
+119
-21
@@ -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);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user