There must be a better way to do this. (Blink an LED 20 times)

Any tips- there must be a better way to do this. Lines 186 to 227 works, but it looks like lazy programming. I am interested in learning how to do something like a for-next loop in esphome where I could just repeat

 - switch.toggle: led5  
 - delay: 500ms

20 times?

I tried the code sample in the docs but the script never runs because I am calling it from another script. I am finding mixed information if a script can execute another script.

Thanks

Note: The packages are where I do the stuff common to all my device YAML files, like name:, board:, api:, ota: and network.

# This is part of our Halloween setup where the Trick or Treaters
# will press a button to get a prize delivered.
#
substitutions:
  device_name: prize-delivery
  friendly_name: prize_delivery

esphome:
  name: ${device_name}
  friendly_name: ${friendly_name}

  on_boot:
    priority: -100.0
    then:
      - script.execute: cycle_start

packages:
  wifi: !include common/wifi.yaml
  device_base: !include common/esp8266.yaml

#Override the package:
esp8266:
  board: d1_mini  


#======================================================
# The start button closes the relay which controls the motor
binary_sensor:
  - platform: gpio
    name: start_button
    pin:
      number: D4
      mode: input_pullup
      inverted: True
    id: button_start
    filters:
      - delayed_on: 100ms   # THIS DOES THE DEBOUNCE
    on_press:
      then:
        - delay: 500ms   #Make sure the home switch is off.
        - script.execute: cycle_start


  # Microswitch at the home position..
  # The switch closes when the motor is at the home (load) position.
  - platform: gpio
    name: home position
    pin:
      number: D2
      mode: input_pullup
      inverted: True
    id: button_home
    on_press:
      then:
        - switch.turn_off: led1
        - switch.turn_off: led2
        - switch.turn_off: led3
        - switch.turn_off: led4
        - switch.turn_off: led5
        - light.turn_on: ready
        - delay: 250ms              # Make sure the switch is "in the groove"
        - switch.turn_off: relay
        - delay: 500ms              # Make sure the "ready" light is on.
        - light.turn_on: ready


#Put a button on the device web page
button:
  - platform: template
    name: Start
    icon: "mdi:liquid-spot"
    on_press:
      then:
        - script.execute: cycle_start

switch:
  - platform: gpio
    name: motor relay
    pin:
      number: D1
      mode: output
    id: relay
    internal : false

  - platform: gpio
    name: ${device_name} led1
    pin:
      number: D0
      mode: output
    id: led1
    internal : false

  - platform: gpio
    name: ${device_name} led2
    pin:
      number: D6
      mode: output
    id: led2
    internal : false

  - platform: gpio
    name: ${device_name} led3
    pin:
      number: D7
      mode: output
    id: led3
    internal : false

  - platform: gpio
    name: ${device_name} led4
    pin:
      number: GPIO1
      mode: output
    id: led4
    internal : false

  - platform: gpio
    name: ${device_name} led5
    pin:
      number: GPIO3
      mode: output
    id: led5
    internal : false

light:
  - platform: status_led
    name: ${device_name} status
    id: ready
    pin: D5


script:
  - id: cycle_start
    then:
      - switch.turn_on: relay
      - light.turn_off: ready
      - delay: 250ms
      - switch.turn_on: led1
      - light.turn_off: ready
      - delay: 2s
      - switch.turn_on: led2
      - light.turn_off: ready
      - delay: 2s
      - switch.turn_on: led3
      - light.turn_off: ready
      - delay: 2s
      - switch.turn_on: led4
      - light.turn_off: ready
      - delay: 2s
      - switch.turn_on: led5
      - light.turn_off: ready
      #
      # Turn all the LEDs off
      - delay: 2s
      - switch.turn_off: led1
      - delay: 50ms
      - switch.turn_off: led2
      - delay: 50ms
      - switch.turn_off: led3
      - delay: 50ms
      - switch.turn_off: led4
      - delay: 50ms
#      - switch.turn_off: led5
      - delay: 50ms
      #
      # Blink LED5 20 times
      - switch.toggle: led5               # Toggle the LED state
      - delay: 500ms                      # Delay for 500 milliseconds
      - switch.toggle: led5  
      - delay: 500ms         
      - switch.toggle: led5  
      - delay: 500ms         
      - switch.toggle: led5  
      - delay: 500ms         
      - switch.toggle: led5  
      - delay: 500ms         
      - switch.toggle: led5  
      - delay: 500ms         
      - switch.toggle: led5  
      - delay: 500ms         
      - switch.toggle: led5  
      - delay: 500ms         
      - switch.toggle: led5  
      - delay: 500ms         
      - switch.toggle: led5  
      - delay: 500ms         
      - switch.toggle: led5  
      - delay: 500ms         
      - switch.toggle: led5  
      - delay: 500ms         
      - switch.toggle: led5  
      - delay: 500ms         
      - switch.toggle: led5  
      - delay: 500ms         
      - switch.toggle: led5  
      - delay: 500ms         
      - switch.toggle: led5  
      - delay: 500ms         
      - switch.toggle: led5  
      - delay: 500ms         
      - switch.toggle: led5  
      - delay: 500ms         
      - switch.toggle: led5  
      - delay: 500ms         
      - switch.toggle: led5  
      - delay: 500ms         
      - switch.turn_off: led5

repeat action

2 Likes

Try reading the documentation or even a search box.

1 Like

Why are you repeating (oh the irony) what’s already been said?

That’s incredibly rude.

I pointed it out, because you added no value with that post.

I mentioned the repeat action right below the link. Look again.

Thanks for the link. I did try various repeat techniques as mentioned in the docs. (The link in my post is the same as yours). Counted Repeat, While Loop, Repeat Until, but all had various issues. They all worked, but the timing was inconsistent.

Repeat, as you suggested, was the most consistent, but also had timing issues. I suspect that the timing mismatch comes from executing the blink script from another script. Sometimes the blinkr script never started. Sometimes it would start early by a few hundred ms. Calling the cycle and blinkr scripts in sequence had worse timing issues. Sometimes the second script would start milliseconds after the first, if it ran at all.

Since the long form using a single script works, I will leave it as it is. I was just curious if I had missed something in the docs.

:+1: I missed that link for some reason.

That’s interesting. I haven’t used this functionality myself, unfortunately.

I can only think, based on firmware programming that I’ve done on other chips, is that something’s blocking. Normally these kernals run a single thread with an interrupt with every cycle. Or the overhead of calling other functions introduces some overhead.

But, I have a (not so ideal) alternative: I have a non-ESP device with an LED that I also wanted to blink, but couldn’t change the firmware, so what I did instead is to make an automation on the HA side to run the loop and blink the LED. My blinking rate is the same as yours. This will split the control, so you should probably stick with what you have, but mentioning this nonetheless.

The device is a prize delivery mechanism for a Halloween prop. I won’t go into the mechanics here, but the delivery mechanism takes one minute to complete a rotation. From “start” button press to the physical delivery takes 25-seconds, then 35 seconds for the motor to rotate back to the “home” position where the next prize is prepared for delivery. The flashing LEDs are to keep the guest “entertained”.

@stevemann you know what, I think I have another way that will avoid your repeated inline statements.

You could have an automation that triggers every time the LED changes state (to on or off) and then delay before toggling the state. You’d need a separate variable/helper to do the counting and use that as a condition to terminate the ping-pong / flip-flop effect.

(The idea comes from building the classical flip-flop LED circuit with analogue electronics.)