Use WS2812B ring to display sensor value

Howdy, building on this thread, I want to use a 24 LED ring to display the value of power imported/exported to the grid.

I have this value as a sensor (via emoncms), either +ve or -ve depending on the direction of power flow.
Ideally, I’d like to use LEDs 1-12 in red to show import from grid, and 24-13 in green to show export to grid.

Reading the docs for ESPHome, I’m just getting myself confused, but stepping out what I need to do:

Getting the value into ESPHome is step 1, and it seems like I can either read the sensor value using ESPHome, or push it from HA.

I then need to use ESPHome to determine if value is +/-, and use light.addressable_set to … well, set the LEDs.

Has anyone done similar and have code I can work from? Am still reading the docs and testing, but thought I’d post here whilst I do the same just in case someone’s already done it!

The first piece, getting the data from HA is covered here I think https://esphome.io/components/sensor/homeassistant.html

Cheers, am using API and calling services from HA to push values to ESPHome, managed to get it working using an input_number to test values of 0-24:

ESPHome:

esphome:
  name: led_power_ring
  platform: ESP8266
  board: d1_mini

wifi:
  ssid: "Pretty fly for a Wifi"
  password: "REDACTED"

logger:

api:
  password: "REDACTED"
  services:
    - service: led_power_ring_update
      variables:
        led_power_ring_level: int
      then:
        - light.addressable_set:
            id: led_power_ring
            range_from: 0
            range_to: !lambda 'return led_power_ring_level;'
            red: 100%
            green: 0%
            blue: 0%
        - light.addressable_set:
            id: led_power_ring
            range_from: !lambda 'return led_power_ring_level;'
            range_to: 24
            red: 0%
            green: 0%
            blue: 0%

ota:
  password: "REDACTED"

light:
  - platform: fastled_clockless
    chipset: WS2812B
    pin: GPIO4
    num_leds: 24
    rgb_order: GRB
    name: "led_power_ring"
    id: led_power_ring

Automations.yaml (although created using the GUI)

- id: '1599970552549'
  alias: led_power_ring_update
  description: ''
  trigger:
  - entity_id: input_number.led_power_ring_value
    platform: state
  condition: []
  action:
  - data_template:
      led_power_ring_level: '{{states.input_number.led_power_ring_value.state | int
        }}'
    service: esphome.led_power_ring_led_power_ring_update
  mode: single

Next step is to use the real values of emoncms.solar (0-4800ish) to populate the LEDs.

To marmalade that value into the service call will requires some maths. Initially I’m thinking x/200 to make the min/max values of ±4800 fit…

That gives 0-24 - although I think according to the docs the lights are called 0 - 23 with 24 leds.

Whoops, you’re right - although it seems to currently work fine with 0-24 on the input_number, so will see what it does once I can get it to update based off the grid sensor.

Interesting, it seems to happily accept negative numbers (and goes counterclockwise fine)

However… positive numbers seem to +1 everything.

I’m not sure whether there’s a discrepancy between how the FastLED is setup (num_leds = 24) and how light.addressable_set wants to start at 0.

api:
  password: ""
  services:
    - service: led_power_ring_update
      variables:
        led_power_ring_level: int
      then:
        - if:
            condition:
             lambda: 'return led_power_ring_level < 0;'
            then: #red for negative 
              - light.addressable_set:
                  id: led_power_ring
                  red: 0%
                  green: 0%
                  blue: 0%
              - light.addressable_set:
                  id: led_power_ring
                  range_from: !lambda 'return led_power_ring_level;'
                  range_to: 24
                  red: 100%
                  green: 0%
                  blue: 0%
            else: #green for positive
              - light.addressable_set:
                  id: led_power_ring
                  red: 0%
                  green: 0%
                  blue: 0%
              - light.addressable_set:
                  id: led_power_ring
                  range_from: 0
                  range_to: !lambda 'return led_power_ring_level;'
                  red: 0%
                  green: 100%
                  blue: 0%

dropping in a -1 for lighting the green LEDs seems to fix it though.

              - light.addressable_set:
                  id: led_power_ring
                  range_from: 0
                  range_to: !lambda 'return led_power_ring_level - 1;'
                  red: 0%
                  green: 100%
                  blue: 0%

Got me stumped whether it’s something in my ham-fisted attempt at getting it to work, or is there actually a bug.

Moving on (stream-of-consciousness style) the next step is converting the -4800 <> +4800 value from emoncms_main into -24 <> +24.

  - platform: template
    sensors:
      led_power_ring_testvalue:
        value_template: "{{ '%0.0f' | format(states('sensor.emoncms_main') | int /200 | int) }}"
        friendly_name: led_power_ring_testvalue

… and in doing so, realised that the emoncms_main is actually positive for import from grid and negative for export, so my red/green above is flipped :rofl: