7 seg WS2812 clock - help with saving colour

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]);
              }
            }
          }

I just built a clock and am using your code. I read this that says that due to the fact that ESP8266s don’t have persistent NVRAM, it can remember states across reboots but not over power loss.

I do have one question. Can you tell me how to make the dots stay on instead of blinking?

Thank you!!

Thank you!

Guys… how did you manage to compile this? I get tons of errors, despite i have framework marked to 2.7.4. It seems that fastled is not supported in latest esphoem anymore…?

I haven’t touched it since I posted, but it did compile back then. The clock functions currently, but with the mentioned colour saving fail. I just plugged it back in (it’s been on a shelf) and it booted up, got the time and is displaying it just fine (in all white).

@SoCalDave If you didn’t figure it out already, if you don’t want the dots flashing, just edit the part where it says:

 //Flash the dots - Dot LED addresses are fixed here.

Take out the “if” statement so the 2 lines starting with “it[10x]” are always run. This sets the dot colour. In this version, there’s 2 LEDs for the dots at position 100 and 101… In reality, these don’t exist. I don’t have dot LEDs, and I intentionally set the ID higher than the number of LEDs to keep it out of the way.

Did you perhaps try to compile with latest esphome? I gave up on esphome and ended up making a clock with Arduino instead. It’s not connected to HA, but since it’s just a clock it’s not needed to, anyway.