I’m trying to use a rotary encoder to control a WS2812 LED ring (12 LEDs), where the number of LEDs lit should correspond to the encoder position. Essentially, if the encoder is at step 6, the first 6 LEDs should be on, and the rest should be off.
I’ve attempted to define each LED as a seperate partitioned light segment. This allowed me to control each LED manually, but the rotary encoder failed to update them dynamically.
I used a lambda function inside on_value to loop through the LEDs and turn on the correct number based on the encoder position:
on_value:
then:
- lambda: |-
int volume = id(volume_level).state;
id(circular_led).clear_effects();
id(circular_led).addressable_set_range(0, volume, Color(255, 255, 255)); // Turn on LEDs up to volume level
id(circular_led).addressable_set_range(volume, 12, Color(0, 0, 0)); // Turn off LEDs beyond volume level
id(circular_led).update();
The log shows the encoder registering changes but the LEDs do not change.
I found this forum post where they use homeassistant.service calls within ESPHome to update the lights. However, its unclear if this is the best way, as it may introduce latency compared to direction ESPHome control.
Should I be using addressable_light instead of light? I feel like my issue may be that I haven’t defined the LED ring properly in ESPHome. Has anyone successfully used addressable_set_range() for this kind of setup? My implementation seem to have no effect.