Do I need blocking code?

I have a timing problem that I can’t think of a fix except for blocking code.
My Halloween prop has a motor that starts running when the “Start Button” is pressed, and stops running when the “Home Button” (a magnetic door sensor) is closed.

The problem is that the magnet for the motor position sensor has a dead zone when the magnet glued to the PVC cylinder is positioned right over the sensor as in this photo. But in this position the sensor is off (open). Ten degrees in either direction turns the sensor on (closed).

When the start_button is closed, the motor starts turning the PVC cylinder, and the magnetic sensor is energized as the magnet rotates out of the dead zone, and that stops the motor prematurely. (One revolution takes 20 seconds).

I’ve tried stronger magnets, multiple magnets, moving the sensor closer, but nothing alleviates the problem of the magnetic sensor thinking that the cylinder is at home shortly after the rotation begins.

In the code below, I tried putting a delay of 6 seconds that should guarantee the motor runs for six seconds which would get the magnet far from the sensor. But it doesn’t do that. I don’t want to do blocking code, so does anyone have any ideas?

#======================================================
# 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   # DEBOUNCE
    on_press:
      then:
        - script.execute: cycle_start
        - delay: 6000ms   #Make sure the home switch is off


  # Magnetic door sensor 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
    filters:
      - delayed_on: 2500ms   #Debounce
    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 home switch is "ON"
        - switch.turn_off: relay
        - delay: 500ms              # Make sure the "ready" light is on.
        - light.turn_on: ready

Yeah sometimes it would be handy if delay; was blocking.

Maybe set a global using millis in the “on” code and loop checking that millis has increased by 6000 in the “off” code?

That would work, but I really don’t want to block. I’ll try this, however. Thanks.

You could try putting just a delay: 6s into a separate script, fire that off in or before your cycle_start and then wrap your home button on_press routine in an if block that uses script.is_running to query whether that timer script is still “running” (or rather, because it’s non-blocking, yielding async cycles). That way both the sensor must trigger and the timer must have expired.

1 Like

I hadn’t thought of using script.is_running. (Actually, I hadn’t heard of it). This would not give me the problems associated with blocking code.