Turn on fastled LED strip in a row (lightsaber)

There should be a very simple solution to my problem here …

I have a 100 LED strip which works great with ESPhome so far.

Now I simply want to add four buttons, which turn the strip on or off from each end with a minimal delay between the individual LEDs (it should take around 2s to completely turn on the whole strip) - so it looks something like a lightsaber
I am sure there is an effect for something as basic as that, but I can’t find it anywhere in the documentation … or I don’t know where to look for…

could someone point me in the right direction?! :smiley:

partition the led strip Light Partition — ESPHome then turn them on one partition at a time, with a small delay.

I doubt creating 100 Partitions and adding scripts controlling them will work… I tried to do something similar, but it’s too much to handle for the ESP8266 I use and it results in a boot-loop

I had the hope there was a simple effect that does this (like you can set a duration for turning the light on/off)

Sorry for late response but if you still have no way figured out, here you go:

esphome:
  name: lamp-livingroom

esp32:
  board: esp32dev

switch:
  - platform: template
    name: "Lamp Livingroom"
    id: led_switch
    optimistic: true
    turn_on_action:
      - if:
          condition:
            light.is_off: led_master
          then:
            - light.turn_on:
                id: led_master
                effect: "Wipe In"
                red: 100%
                green: 71%
                blue: 62%
                brightness: 100%
    turn_off_action:
      - if:
          condition:
            light.is_on: led_master
          then:
            - light.turn_on:
                id: led_master
                effect: "Wipe Out"
            - delay: 2s
            - light.turn_off: led_master

light:
  - platform: fastled_clockless
    id: led_master
    chipset: WS2812B
    pin: GPIO13
    num_leds: 50
    rgb_order: GRB
    name: "Lamp Livingroom (Master)"
    effects:
      - addressable_lambda:
          name: "Wipe In"
          update_interval: 20ms
          lambda: |-
            static int x = 0;
            if (initial_run) {
              x = 0;
              it.all() = ESPColor(0,0,0);
            }
            if (x < it.size()) {
              it[x] = current_color;
              x += 1;
            }

      - addressable_lambda:
          name: "Wipe Out"
          update_interval: 20ms
          lambda: |-
            static int x = 0;
            if (initial_run) {
              x = it.size();
            }
            if (x > 0) {
              x -= 1;
              it[x] = ESPColor(0,0,0);
            }

Maybe these lines are able to solve your problem!

3 Likes

Can’t you just do that with the color wipe effect? Just use a single color. You can also reverse the effect to wipe out.

With the code i‘ve posted above it will stay at the configured color (within the template switch turn_on_action) until you turn the switch/light off and then it will wipe in the opposite direction then when turned on.
Currently got a spare ESP laying in front of me so I’ll try the default effect you mentioned above and edit my post in some minutes accordingly to my results.

Sorry for late response. Couldn’t get it to work to result in the same effect like i posted with lambda.

omg - how did I not see your response?!

Thanks so much - it’s exactly what I wanted to do!

I tried looking at your lambda, but honestly, I don’t understand anything that’s going on there.
I’m trying to make the exact same thing, but in the opposite direction. So starting with the last LED turning them on, and starting with the first LED turning them off.

Edit: ok, I think I’ve got it:

    effects:

    - addressable_lambda:
        name: "Wipe up on"
        update_interval: 20ms
        lambda: |-
          static int x = 0;
          if (initial_run) {
            x = 0;
            it.all() = ESPColor(0,0,0);
          }
          if (x < it.size()) {
            it[x] = current_color;
            x += 1;
          }

    - addressable_lambda:
        name: "Wipe up off"
        update_interval: 20ms
        lambda: |-
          static int x = 0;
          if (initial_run) {
            x = 0;
          }
          if (x < it.size()) {
            x += 1;
            it[x] = ESPColor(0,0,0);
          }   

    - addressable_lambda:
        name: "Wipe down off"
        update_interval: 20ms
        lambda: |-
          static int x = 0;
          if (initial_run) {
            x = it.size();
          }
          if (x > 0) {
            x -= 1;
            it[x] = ESPColor(0,0,0);
          }   

    - addressable_lambda:
        name: "Wipe down on"
        update_interval: 20ms
        lambda: |-
          static int x = 0;
          if (initial_run) {
            x = it.size();
            it.all() = ESPColor(0,0,0);
          }
          if (x > 0) {
            it[x] = current_color;
            x -= 1;
          }

I did it purely by trail and error, but it seems to do exactly what I want :smiley:

Thanks again!!!

Your configuration is working perfectly since days. Thanks again!

I do have a bonus question though: is there a way to make it more smooth? Sending a transition length doesn’t seem to do anything and I haven’t found a way to define it directly in the lambda :thinking:

By smooth you mean faster?
I’m trying to do exactly the same thing, did you find a solution?

@Farnsworth @bitman glad to hear that the solution is working for both of you.

To change the speed of this effect try decreasing/increasing the update_interval to a lower value.

Hope this helps!

@Meaxl That’s what I tried, but it’s not working as expected.
I have for example a code where a single led is traveling up and down the strip. Changing the update_interval from 20ms to 1ms indeed makes it go faster, but not as fast as 1 led per millisecond… which makes it impossible to create a “lightsaber” effect…
I must be missing something else

Do you want the effect in total to be faster?
Or light up multiple leds at the same time?

Checkout this example smaller time periods.

some_config_option:
  some_time_option: 1000us  # 1000 microseconds = 1ms, maybe use this time period to get even below 1ms
  some_time_option: 1000ms  # 1000 milliseconds
  some_time_option: 1.5s  # 1.5 seconds
  some_time_option: 0.5min  # half a minute
  some_time_option: 2h  # 2 hours

@Meaxl but the update_interval doesn’t accept anything less than 1ms…
Is there another parameter that would cause the effect to run faster?

Maybe you could try adding this option, documented here

call.set_transition_length(1000);

But i actually don’t know if it could work with this and also have no clue how to use it, never used this.

1ms is really too slow for your application?

but it should be 1 LED each ms if you change the update_interval to 1ms :thinking:
If I understand that lambda correctly, each update_interval the next LED gets turned on/off

I tried like this:

    - addressable_lambda:
        name: "Wipe up on"
        update_interval: 20ms
        lambda: |-
          static int x = 0;
          call.set_transition_length(1000);
          if (initial_run) {
            x = 0;
            it.all() = ESPColor(0,0,0);
          }
          if (x < it.size()) {
            it[x] = current_color;
            x += 1;
          }

but ESPHome says:

           error: 'call' was not declared in this scope
           call.set_transition_length(1000);if (initial_run) {
       ^

Ok, no error when I do this:

    - addressable_lambda:
        name: "Wipe up on"
        update_interval: 20ms
        lambda: |-
          static int x = 0;
          auto call = id(ledstrip).turn_on();
          call.set_transition_length(1000);
          if (initial_run) {
            x = 0;
            it.all() = ESPColor(0,0,0);
          }
          if (x < it.size()) {
            it[x] = current_color;
            x += 1;
          }

but no transition for each led - they still turn on instantly one after the other

According to the information given at the Lambda Effect for update_interval.

I’m assuming that the total amount of time needed until the effect was running exactly one complete cycle (from off, to all leds in) is defined within update_interval.

  • update_interval (Optional, Time): The interval with which the lambda code is executed. A value of 0ms means that the lambda is always executed, without a cool-down. Defaults to 0ms.

As for [transition_length](Light Component — ESPHome)

Correspons to the moment you turn a lightbulb on and change it to some random effect. The time needed for this change is defined in here

  • slowly dim up within 10s, stay there
  • light on 100% Brightness, start effect twinkle with 10s transition_length, will need 10s to smoothly fade out bricht light and smoothly transition to twinkle
  • transition_length (Optional, Time, templatable): The length of the transition if the light supports it.

This is all information i discovered myself but sadly all projects i were using this lightsaber effect are no longer in use. So there is no chance i could troubleshoot this by myself.

Hope you’ll find a solution soon!