ESPHome Lambda functions and RGB LEDs

I’m trying to learn lambdas, and so I used some of the sample code. It did what was expected, but when I changed it to this, I didn’t get the results I was expecting:

      - lambda:
          name: colorcycle
          update_interval: 10s
          lambda: |-
            static int state = 0;
            auto call = id(strip).turn_on();
            call.set_transition_length(10000);
            if (state == 0) {
              call.set_rgb(0.20,0.20,0.20);
            } else if (state ==1) {
              call.set_rgb(0.0,1.0,0.0);
            } else if (state ==2) {
              call.set_rgb(0.0,0.0,1.0);
            } else if (state == 3) {
              call.set_rgb(1.0,0.0,0.0);
            }
            call.perform();
            state += 1;
            if (state == 4)
              state =0;

I was hoping that the ‘state = 0’ part would show a dim white (since the RGB values are set to .20, and not 1.0), but the LEDs still lit at 100%. I want to use custom RGB values. How would I go about getting that to work? The complete effect I would like is to have the light turn on, slowly transition to one RGB value, then to another, and another. After I"m done transitioning through my values, I want the light to end up in the off state.

Surely it would be easier to do from home assistant. Not everything has to run on your esp.

I think what @Egro is doing is creating a light effect. These would need to / be best done in the ESP so it simply shows up in HA as an effect, ‘colorcycle’.

I’ve only played around with the ESP light effects a little bit and not using lambda’s , so sorry I can’t help you there

I see what you mean. There was a thread about doing that, but I cannot find it again. It has come up a couple of times.

Use make_call instead of turn_on.

I modified my code with make_call() instead of turn_on(), and nothing really changed. I still do not get the expected results.

I also changed the call.set_rgb() line to 3 distinct lines, one for each color.

call.set_red(0.20);
call.set_green(0.20);
call.set_blue(0.20);

It still doesn’t perform as expected. I get bright white, not 20% white like I would expect.

Can you show me your code with make_call in it?

What I have found is that using turn_on will typically turn the light on full brightness. With make_call you have to specify everything. For example:

        // light update
        auto sun = id(biome_ledarray).make_call();
        sun.set_state(true); // turn the light on
        sun.set_brightness(brightness);
        if (color_temp) sun.set_color_temperature(color_temp);
        sun.set_transition_length(transition);
        sun.perform();

This is some of my code for a cwww light which will transition an led array from a given state to a new state specified by the provided brightness and color_temp . The set_state(true) is important to have the light be on.

Also remember brightness is different from color. Your set_red(0.20), etc is setting the color not the brightness.

This is the bit of code I believe you are after:

light:
  - platform: rgb
    id: strip
    name: "Test Strip"
    red: output_component1
    green: output_component2
    blue: output_component3
    effects:
      - lambda:
          name: colorcycle
          update_interval: 10s
          lambda: |-
            static int state = 0;
            auto call = id(strip).make_call();
            call.set_transition_length(10000);
            if (state == 0) {
              call.set_red(.20);
              call.set_green(.20);
              call.set_blue(.20);
            } else if (state ==1) {
              call.set_rgb(0.0,1.0,0.0);
            } else if (state ==2) {
              call.set_rgb(0.0,0.0,1.0);
            } else if (state == 3) {
              call.set_rgb(1.0,0.0,0.0);
            }
            call.perform();
            state += 1;
            if (state == 4)
              state =0;
            
          
output:
  - platform: esp8266_pwm
    #max_power: 0.50
    id: output_component1
    pin: 0
  - platform: esp8266_pwm
    #max_power: 0.50
    id: output_component2
    pin: 2
  - platform: esp8266_pwm
    #max_power: 0.50
    id: output_component3
    pin: 3

The ultimate outcome here is that I want to be able to send RGB values, and have them light the LED strip, without having to specify a brightness separately.
As sparkydave said, this is for a light effect, and can only be done properly on the ESP itself.

1 Like

Ok, so what happens with the above code exactly?

My observations from working with esphome is that if I was transitioning the light say from low to half brightness and used turn_on then the light would first go immediately to full bright and then dim to half bright instead of from low to half bright. By using make_call that transition to full brightness did not happen. Second if the light was off and I wanted it to go to say half bright if I did not specify set_state(true) the light would not turn on at all. Also you can not adjust the brightness of the light by specifying a different color. So (0.2,0.2,0.2) at full brightness will be a very bright gray that is probably not different than bright white.

I think at least you need to add set_state(true) to your code. Also if you don’t set brightness then likely it will always be full unless somewhere else in your yaml you set it to something else.

What the code does it cycles the light from white to green, to blue, to red, and back to white.

What I expected is for the white to be less bright, since I’m only calling for 20% brightness, and not 100%.

What I"m looking to achieve at the end of it all is to be able to enter RGB values, and have the light cycle through them. I’m trying to achieve an artificial sunset/sunrise sort of thing, where the light will transition from off, to dark blue/purple, to kinda dim red, then yellow, then full brightness (or the reverse for sunset).

I only heard of ESPHome about a week ago, and I’m still figuring out what it can and can’t do.

I hate to be a nag about this point but let me try again, you are not sending out 20% brightness. You are sending out 20% blue (or red or green). The following is directly from the ESPHome Light Component documentation:

Note

The red , green and blue values only control the color of the light, not its brightness! If you assign 50% to all RGB channels it will be interpreted as 100% on. Only use brightness to control the brightness of the light.

In other words if you send out 50% of each color the light will still be 100% on unless you change the brightness.

Yes micque, I saw that in the code notes.
I did resolve my issue tho! Here’s what I had to do:

  1. Took each target RGB value and plugged it into an HSV calculator, from which I captured the V, in percent. RGB 172,116,183 converted to HSV 290, 37, 72
  2. Converted each value in the RGB to a percent. RGB 172,116,183 converts to .67 .45 .72

The step of the lambda that needed that RGB value converted to -

call.set_rgb(0.67, 0.45, 0.72);
call.set_brightness(0.72);

So, that sorted my issue! I went through the above steps for each of the transition RGB values I needed, and the code now works as expected. Kinda clunky, but at least it works.

If there is a better way of doing it, I’d be glad to know!

Well boo. It still doesn’t quite work.

It worked the first time, but subsequent calls do nothing unless I reboot the ESP. :frowning:

At least I got the color situation sorted.

Seems that effects constantly loop. I need a better way. :frowning:

Thanks for the help, all. Back to the drawing board.

Constantly looping is the idea of effects and was what I thought you were trying to achieve… :wink: Maybe if you just want it to occur once, create it as a script

2 Likes

I tried this effect on my platform: fastled_spi chipset: WS2801 and platform: fastled_clockless chipset: WS2812B and the transition took only 1s, but I think the intention is that the colors seamlessly change into each other…