Greetings,
I am trying to adapt a 7-segment clock to be used with ESPHome. Eventually, I want to be able to use Home Assistant to update the brightness and color of each segment, but for now I am just trying to get basic functionality. Each LED ends up corresponding to a specific segment, and I believe I have the pixel mapper laid out correctly in my code.
Where I am getting stuck is when I go to have my lambda code turn on specific LEDs to illuminate specific segments that will display the time. I have tried a number of method after seeking advice from a few places, but none of them have worked so far and most end in compile errors (like my latest attempt below). Any help here would be appreciated.
light:
- platform: neopixelbus
type: GRB
pin: D4
num_leds: 25
name: "Clock LEDs"
id: clock_leds
variant: WS2812X
effects: [] # Disable built-in effects
script:
- id: update_led_colors
then:
- lambda: |-
auto now = id(sntp_time).now();
if (!now.is_valid()) return; // Ensure valid time
int hours = now.hour % 12;
if (hours == 0) hours = 12;
int minutes = now.minute;
// Function to get segment states for a digit
auto get_segments = [](int digit) -> std::vector<bool> {
switch(digit) {
case 0: return {true, true, true, false, true, true, true};
case 1: return {false, true, false, false, true, false, false};
case 2: return {true, true, false, true, false, true, true};
case 3: return {true, true, false, true, true, false, true};
case 4: return {false, true, true, true, true, false, false};
case 5: return {true, false, true, true, true, false, true};
case 6: return {true, false, true, true, true, true, true};
case 7: return {true, true, false, false, true, false, false};
case 8: return {true, true, true, true, true, true, true};
case 9: return {true, true, true, true, true, false, true};
default: return {false, false, false, false, false, false, false};
}
};
// Get segment states for each digit
auto hour_ones_segments = get_segments(hours % 10);
auto hour_tens_segments = get_segments(hours / 10);
auto minute_ones_segments = get_segments(minutes % 10);
auto minute_tens_segments = get_segments(minutes / 10);
// Update LEDs on the light strip
id(clock_leds)->addressable_lambda([=](auto &leds) {
// Turn off all LEDs
for (int i = 0; i < leds.size(); i++) {
leds[i] = Color::BLACK;
}
// Helper to map segments to LEDs
auto apply_segments = [&](int start_idx, const std::vector<bool> &segments) {
for (size_t i = 0; i < segments.size(); i++) {
if (segments[i]) {
leds[start_idx + i] = Color::WHITE; // Turn on segment in white
}
}
};
// Apply segments for each digit
apply_segments(0, hour_tens_segments);
apply_segments(7, hour_ones_segments);
apply_segments(14, minute_tens_segments);
apply_segments(21, minute_ones_segments);
});
The original project that I am attempting to use via ESPHome can be found here: