I am configuring EspHome (on ESP8266) as RGB controller for WS2812B LEDs (using platform: neopixelbus) with a few light effects and with local buttons for local control (while still integrated with HomeAssistant).
I am looking to use two buttons. One button for power on/off and second one for switching effects
I need help how to configure the ESPHomel config to allow me to switch to the next effect with the local button, essentially looping thru the list.
I can control the single button with single activity (e.g. on/off) but I am unable to make it work for single button to go iterate or loop thru a list of effects and select one of them.
I was unable to find this particular situation. I have seen local button solutions for on/off and for brightness up/down but not for effects.
Can you help with example or to point me in the right direction if this has been discussed?
Thanks in advance
Hi Miguel,
Thank you for the reply and the resource.
I have not used global variables and/or lambdas with EspHome and even after reading it and then looking at examples, I am unclear how to link and use those for my scenario. I read thru
Would you be able to provide a starter example that I hope to learn from and build further?
The below is not the actual code, it is for description.
light:
- platform: neopixelbus
type: grb
pin: GPIO3
num_leds: 121
name: "rgb_lights"
effects:
- Effect_1:
- Effect_2:
- Effect_3:
binary_sensor:
- platform: gpio
name: "effects" # push button for scrolling thru the pre-configured effects with each press
# the following is description of the desired outcome
on_click one:
id: rgb_lights
effect: Effect_1
on_click two:
id: rgb_lights
effect: Effect_2
on_click three:
id: rgb_lights
effect: Effect_2
#next click goes back to Effect_1#
I was also thinking about some loop in which while the button is pressed, the effects will change and once the button is released, the current effect to continue as selected.
I canāt try now, but, I think that should look that:
First, we add the global variable:
globals:
- id: actual_effect
type: int
restore_value: no
initial_value: '0'
And then, change the onClick
binary_sensor:
- platform: gpio
name: "effects" # push button for scrolling thru the pre-configured effects with each press
# the following is description of the desired outcome
on_click:
- lambda: |-
auto call = id(rgb_lights).turn_on();
if (id(actual_effect) == 0)
call.set_effect("Effect 1");
if (id(actual_effect) == 2)
call.set_effect("Effect 2"):
//Other effects
if (id(actual_effect) < 10) //Or your maximums effects
id(actual_effect) = 0;
else
id(actual_effect) += 1;
call.perform();
Thank you very much for the example code. It works and it does what i was looking to do.
Now I can scroll thru the number of pre-configured LED effects with the push of a local button.
For my case I had to modify the if/else loop as below to do what I needed.
//Other effects
if (id(actual_effect) < 10) //Or your maximums effects
id(actual_effect) += 1;
else
id(actual_effect) = 0;
call.perform();
The best part is that with your help and example I am learning.
I really appreciate your help. Thank You.
Hello everybody
Is it possible to trace the effect in progress?
I have an RGBW LED strip that illuminates the relaxation area of the house with different effects: massage, meditation, chakras ā¦
The module I built consists of two buttons to vary the brightness, a button to change the effect and a led that indicates the effect in progress, flashing a number of times for each effect.
The effect change is based on the example of MiguelAngelLV, thanks for the idea.
The problem is that if I change effect from the HA front-end, the value of the variable no longer matches the effect being executed.
I looked at the ESPhome API but couldnāt find anything, and before going through the code I was wondering if anyone knows a solution.
Thank you
I would like to make also a local switch, but it donāt work here. I have this error message and what I try it donāt work.
ERROR Error while reading config: Invalid YAML syntax:
while scanning a simple key
in "/config/esphome/sl-sofie.yaml", line 57, column 7:
auto call = id(rgb_lights).turn_ ...
^
could not find expected ':'
in "/config/esphome/sl-sofie.yaml", line 58, column 7:
if (id(actual_effect) == 0)
^
Please could you help me?
globals:
- id: actual_effect
type: int
restore_value: no
initial_value: '0'
binary_sensor:
- platform: gpio
pin:
number: D4
mode: INPUT_PULLUP
inverted: True
name: "Sofie effect switch"
on_click:
- lambda:
auto call = id(rgb_lights).turn_on();
if (id(actual_effect) == 0)
call.set_effect("Rainbow Effect With Custom Values");
if (id(actual_effect) == 1)
call.set_effect("Strobe Effect With Custom Values"):
if (id(actual_effect) < 1); //Or your maximums effects
id(actual_effect) += 1;
else
id(actual_effect) = 0;
call.perform();
Hi ,
I am sorry to ask but could someone explain why use all esphome mess to control ws2812b when you can use something like WLED ? What does esphome add here ?
I am not criticizing I am just asking because I use 4 esp32s with wled HA integration to control the ws2812b with lots of features beside the wled app .
I get the point to use esphome with DIY sensors but I am really having hard time understanding why use it with leds in the first place . I would appreciate your kind reply
Well in my case itās because the device Iām building (a nightlight with music for my son) has to do more than just the LEDās. Another advantage of using ESPHome is that you can program functionality that doesnāt require it to be connected, so it will even work if there is no network (for example if youāre not at home). Although I did just find out that switching between presets using a button is actually also possible in WLED, so for the other people in this thread it might actually be an option. Not for me though unless WLED can also send and receive UART commands.
For me the same reason. Iām building leds on the ceiling in my little daughter bedroom, for her is the local switch.
I would also read the temperature of my floorheatingdistributor who is in her room.
Thx for the tip of WLED, I will check it and maybe split the system in two ESPs.
Hello guys an thank you both for the explanation .
Since you have an MCU around , just try WLED and see for yourself , It is very simple to install and use . If you donāt like it then I promise you I will start using esphome for at least one of my leds and I will post my project result .
[edit : Now I had a chance to test fastled and neopixel , i take what I said back , Using ESPhome for led is not bad ( It is very bad ) compared to WLED , it reminds me of assembly language vs C++ ]
I was working on this today and while the solution presented in the thread works, it is very manual. I believe I found a better solution which just crawls available effects in a loop, feel free to use it. Just replace <YOUR_LIGHT_ID>. Works well for my use at least and no need to code a specific case for each defined effect.
binary_sensor:
(your existing config)
on_double_click:
then:
# add a small delay because on_click will always take precedence and strip will never turn off otherwise
- delay: 500ms
- light.toggle: <YOUR_LIGHT_ID>
on_click:
then:
- lambda: |-
static int effect_index = 0; // this value will persist across triggers
id(<YOUR_LIGHT_ID>).turn_on().set_effect(id(<YOUR_LIGHT_ID>).get_effects().at(effect_index)->get_name().c_str()).perform();
effect_index += 1;
if (effect_index >= id(<YOUR_LIGHT_ID>).get_effects().size()) {
effect_index = 0; // restart from the beginning once the last effect is reached
}
return;
I used this topic as a reference for my project, and it was very helpful! But I wanted some different features than what was shown here.
So, I have a single button, which when clicked turns on the lights, and the next click starts to cycle through the effects (dynamically). When it reaches the last effect, it returns to the default of the light on (effect āNoneā). To turn off the lights, simply double-click
In addition, I changed the way of identifying the single and double click, because this way I consider it to have a nicer āvisualā look.
The big difference in my function is that if you change the effect to HA, it will continue the sequence of effects from the one selected in the interface, and not start over from the beginning. This provides continuity in the integration.
I hope you like it! I only copied part of the button code, the rest I imagine each person has their own application. Remember to change the ID of your light, and also the ID of the pin that the button is connected to.
#Set a global variable
globals:
- id: effect_index
type: int
initial_value: "0"
#Physical button to control the lights
binary_sensor:
- platform: gpio
pin:
number: {{YOUR_BTN_PIN}}
mode: INPUT_PULLUP
inverted: True
internal: True
id: physical_btn
on_multi_click:
# double click
- timing:
- ON for at most 0.5s
- OFF for at most 0.7s
- ON for at most 0.5s
- OFF for at least 0.2s
then:
- delay: 500ms
- light.turn_off: {{YOUR_LIGHTS_ID}}
- lambda: |-
id(effect_index)=0;
# single click
- timing:
- ON for at most 1s
- OFF for at least 0.5s
then:
if:
condition:
- light.is_on: {{YOUR_LIGHTS_ID}}
then:
- lambda: |-
std::string actual_effect=id({{YOUR_LIGHTS_ID}}).get_effect_name();
static int total_effects=id({{YOUR_LIGHTS_ID}}).get_effects().size();
std::string this_effect="";
if(actual_effect=="None") {
id(effect_index)=0;
} else {
for(int i = 0; i <= total_effects; i++) {
this_effect=id({{YOUR_LIGHTS_ID}}).get_effects().at(i)->get_name().c_str();
if (this_effect==actual_effect) {
id(effect_index)=i+1;
break;
}
}
if (id(effect_index)==total_effects) {
id(effect_index)=-1;
}
}
if (id(effect_index)==-1) {
id({{YOUR_LIGHTS_ID}}).turn_on().set_effect("None").perform();
} else {
id({{YOUR_LIGHTS_ID}}).turn_on().set_effect(id({{YOUR_LIGHTS_ID}}).get_effects().at(id(effect_index))->get_name().c_str()).perform();
}
return;
else:
- light.turn_on: {{YOUR_LIGHTS_ID}}