OK, so I’m intending to make a large 7 segment digital clock with WS2812 LEDs. Much of the hard part was already made by someone else and posted on Thingiverse. I’ve modified the code a bit to match things like my slightly different wiring and I wanted 12 hour instead of 24, so my version is included here.
Everything is working quite well, except for one minor issue… The colours don’t seem to save. I can set the colours in Home Assistant to whatever I want, but if I reboot the clock, it always starts up white.
Can anyone see what it is I’ve got wrong? I’m fairly sure it’s going to be something really silly, but I just can’t see it.
substitutions:
device_name: Shelf Clock Prototype
preferences:
flash_write_interval: 5min
esphome:
name: shelf-clock-proto
friendly_name: ${device_name}
on_boot:
- light.turn_on:
id: led_strip
brightness: 50%
red: 50%
green: 50%
blue: 0%
effect: "${device_name} Time effect"
esp8266:
board: esp01_1m
framework:
version: 2.7.4
restore_from_flash: true
# Enable logging
logger:
# Enable Home Assistant API
api:
encryption:
key: "removed"
reboot_timeout: 0s
ota:
password: "removed"
wifi:
ssid: !secret wifi_ssid
password: !secret wifi_password
# Enable fallback hotspot (captive portal) in case wifi connection fails
ap:
ssid: "Test Fallback Hotspot"
password: "removed"
globals:
- id: hours_red_value
type: int
restore_value: yes
initial_value: '0'
- id: hours_green_value
type: int
restore_value: yes
initial_value: '0'
- id: hours_blue_value
type: int
restore_value: yes
initial_value: '0'
- id: minutes_red_value
type: int
restore_value: yes
initial_value: '0'
- id: minutes_green_value
type: int
restore_value: yes
initial_value: '0'
- id: minutes_blue_value
type: int
restore_value: yes
initial_value: '0'
- id: dots_red_value
type: int
restore_value: yes
initial_value: '0'
- id: dots_green_value
type: int
restore_value: yes
initial_value: '0'
- id: dots_blue_value
type: int
restore_value: yes
initial_value: '0'
output:
#======== Hours ============
- platform: template
id: hours_red_output
type: float
write_action:
lambda: |-
id(hours_red_value) = 255.0 * state;
- platform: template
id: hours_green_output
type: float
write_action:
- lambda: |-
id(hours_green_value) = 255.0 * state;
- platform: template
id: hours_blue_output
type: float
write_action:
lambda: |-
id(hours_blue_value) = 255.0 * state;
#========= Minutes ===========
- platform: template
id: minutes_red_output
type: float
write_action:
lambda: |-
id(minutes_red_value) = 255.0 * state;
- platform: template
id: minutes_green_output
type: float
write_action:
lambda: |-
id(minutes_green_value) = 255.0 * state;
- platform: template
id: minutes_blue_output
type: float
write_action:
lambda: |-
id(minutes_blue_value) = 255.0 * state;
#========= dots ===========
- platform: template
id: dots_red_output
type: float
write_action:
lambda: |-
id(dots_red_value) = 255.0 * state;
- platform: template
id: dots_green_output
type: float
write_action:
lambda: |-
id(dots_green_value) = 255.0 * state;
- platform: template
id: dots_blue_output
type: float
write_action:
lambda: |-
id(dots_blue_value) = 255.0 * state;
time:
- platform: sntp
id: sntp_time
timezone: "Australia/Sydney"
servers:
- 0.pool.ntp.org
- 1.pool.ntp.org
- 2.pool.ntp.org
light:
- platform: rgb
name: "${device_name} hours lights"
id: hours_lights
restore_mode: RESTORE_DEFAULT_ON
red: hours_red_output
green: hours_green_output
blue: hours_blue_output
- platform: rgb
name: "${device_name} minutes lights"
id: minutes_lights
restore_mode: RESTORE_DEFAULT_ON
red: minutes_red_output
green: minutes_green_output
blue: minutes_blue_output
- platform: rgb
name: "${device_name} dots lights"
id: dots_lights
red: dots_red_output
green: dots_green_output
blue: dots_blue_output
#--------- LED strip ----------------
- platform: fastled_clockless
id: led_strip
name: "Led strip"
internal: True
pin: GPIO0
num_leds: 30
chipset: WS2812B
rgb_order: GRB
effects:
- addressable_lambda:
name: "${device_name} Time effect"
update_interval: 5000ms
lambda: |-
const int ledsInDigitCount = 7;
const int digitsCount = 4;
//Array of which LEDs need to be on for a given digit. 0-9
int digitsLeds[10][ledsInDigitCount] = {
{1,1,1,1,1,1,0}, //0
{1,1,0,0,0,0,0}, //1
{1,0,1,1,0,1,1},
{1,1,1,0,0,1,1},
{1,1,0,0,1,0,1},
{0,1,1,0,1,1,1},
{0,1,1,1,1,1,1},
{1,1,0,0,0,1,0},
{1,1,1,1,1,1,1}, //8
{1,1,1,0,1,1,1} //9
};
//LED address of each digit's first LED - HHMM
int ledOffsets[digitsCount] = {21 , 14, 7, 0};
//Get the time from sntp
auto time = id(sntp_time).now();
//Create array of colour values to use.
int colors[4][3] = {
{id(hours_red_value), id(hours_green_value), id(hours_blue_value)},
{id(hours_red_value), id(hours_green_value), id(hours_blue_value)},
{id(minutes_red_value), id(minutes_green_value), id(minutes_blue_value)},
{id(minutes_red_value), id(minutes_green_value), id(minutes_blue_value)}
};
//Do some maths to get each digit - 12 hour time
int values[digitsCount] = {};
values[0] = 1; //Preset the hour digits to 12 for the case of being 0 hours
values[1] = 2; //This saves doing extra maths and just throwing away the answer
int twelvehour = time.hour % 12;
if(twelvehour > 0) {
values[0] = twelvehour / 10;
values[1] = twelvehour % 10;
}
values[2] = time.minute / 10;
values[3] = time.minute % 10;
//Clear all LEDs (I think). This may actually not be needed since the digit updates are also writing zeroes to the LEDs, right?
it.all() = Color(0,0,0);
//Flash the dots - Dot LED addresses are fixed here.
//Should probably be moved to a constant and perhaps changed to a loop to make it possible to use a variable number of LEDs as the dots
if ((time.second % 2) > 0) {
it[100] = Color(id(dots_red_value), id(dots_green_value), id(dots_blue_value));
it[101] = Color(id(dots_red_value), id(dots_green_value), id(dots_blue_value));
}
// Loop over digits - start from "1 - values[0]" so that we skip over the leading zero on the hours
for (int valueI = 1 - values[0]; valueI < digitsCount; valueI++) {
int ledsOffset = ledOffsets[valueI];
int timeValue = values[valueI];
int *color = colors[valueI];
int *leds = digitsLeds[timeValue];
for (int ledI = 0; ledI < ledsInDigitCount; ledI++) {
if(leds[ledI] > 0) {
int ledIndex = ledI + ledsOffset;
it[ledIndex] = Color(color[0], color[1], color[2]);
}
}
}