Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
ESPHome configuration example to create an animated clock using the Neopixel 60 LED ring
esphome:
# [...]
on_boot:
priority: -10
then:
# enable clock effect after boot
- light.turn_on:
id: light_ring
brightness: 100%
effect: Clock
globals:
- id: clock_brightness
type: int
restore_value: yes
initial_value: '255'
- id: clock_indicators_enabled
type: bool
restore_value: yes
initial_value: 'true'
switch:
- platform: template
name: "Clock Indicators"
lambda: !lambda |-
return id(clock_indicators_enabled);
turn_on_action:
globals.set:
id: clock_indicators_enabled
value: 'true'
turn_off_action:
globals.set:
id: clock_indicators_enabled
value: 'false'
light:
- id: light_ring
internal: False
platform: neopixelbus
type: GRB
variant: SK6812 # WS2812X
pin: RX #GPIO23
num_leds: 60
method: ESP8266_DMA
name: "NeoPixel Light"
color_correct: [50%, 50%, 50%]
effects:
- addressable_lambda:
name: "Clock"
update_interval: 32ms
lambda: |-
static boolean initialized;
static ESPColor clock_ring_colors [60];
if (initialized == false) {
std::fill_n(clock_ring_colors, it.size(), ESPColor::BLACK);
initialized = true;
}
auto time = id(sntp_time).now();
if (!time.is_valid()) {
return;
}
// calculate led indices
int second_idx = (int) (time.second * (it.size() / 60));
int minute_idx = (int) (time.minute * (it.size() / 60));
int hour_idx = (int) ((time.hour % 12) * (it.size() / 12));
int hour_inc_min_idx = hour_idx + (int) (((float) time.minute / 12) * (it.size() / 60));
// fade out old colors
for (int i = 0; i < it.size(); i++) {
ESPColor old_color = clock_ring_colors[i];
// fade out color
int amount = 5;
int red = old_color.red;
int green = old_color.green;
int blue = old_color.blue;
int white = old_color.white;
if (red < amount) { red = 0; } else { red -= amount; }
if (green < amount) { green = 0; } else { green -= amount; }
if (blue < amount) { blue = 0; } else { blue -= amount; }
ESPColor new_color = ESPColor(red, green, blue, 0);
clock_ring_colors[i] = new_color;
}
int indicator_brightness = id(clock_brightness) / 3;
ESPColor indicator_color = ESPColor(indicator_brightness, indicator_brightness, indicator_brightness);
// calculate colors
ESPColor second_color = ESPColor(id(clock_brightness), 0, 0);
ESPColor minute_color = ESPColor(0, id(clock_brightness), 0);
if (minute_idx == second_idx) {
minute_color += second_color;
}
ESPColor hour_color = ESPColor(0, 0, id(clock_brightness));
if (hour_inc_min_idx == minute_idx) {
// if seconds are also the same this will already contain the second color
hour_color += minute_color;
} else if (hour_inc_min_idx == second_idx) {
hour_color += second_color;
}
if (id(clock_indicators_enabled)) {
for (int i = 0; i < it.size(); i += (int) ((float) it.size() / 12)) {
clock_ring_colors[i] = indicator_color;
}
}
// set colors
clock_ring_colors[second_idx] = second_color;
clock_ring_colors[minute_idx] = minute_color;
clock_ring_colors[hour_inc_min_idx] = hour_color;
// apply colors to light
for (int i = 0; i < it.size(); i++) {
it[i] = clock_ring_colors[i];
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment