How to run a stepper motor continuously and then stop it

I need to be able to run a stepper motor until I want to stop it, rather than use a target position.

I can probably achieve this in a convoluted way using the cover component but it’s not a very tidy or efficient solution. And my device isn’t a ‘cover’!

Am I missing a simpler way?

Having thought this through and worked on a couple of options, I’ve settled on the following utilising two scripts.

Not ideal due to the arbitrary target position, but at least gives on/off control.

binary_sensor:  
- platform: homeassistant                      # Manual feeding from HA
  name: "Manual feed"
  entity_id: input_boolean.manually_feed_fish #defined in homeassistant
  id: manual_fish_feeding
  on_press:
    then:
      - script.execute: run_motor
  on_release:
    then:
      - script.execute: stop_motor

script:
  - id: run_motor
    then:
      - stepper.set_target:
          id: feed_motor
          target: 500 # Can be set to any value that exceeds typical design run time

  - id: stop_motor
    then:
      - stepper.set_target:
          id: feed_motor
          target: !lambda return id(feed_motor).current_position;
      - stepper.report_position:
          id: feed_motor
          position: 0          
      - stepper.set_target:
          id: feed_motor
          target: 0

Just a quick note this is how I solved it so it really runs forever:

esphome:
  name: lamp
  on_loop:
    then:
      - stepper.report_position:
          id: image_rotation_stepper
          position: 0

globals:
  - id: motor_running
    type: bool
    restore_value: no
    initial_value: 'false'


stepper:
  - platform: uln2003
    id: image_rotation_stepper
    pin_a: GPIO18
    pin_b: GPIO14
    pin_c: GPIO27
    pin_d: GPIO21
    max_speed: 300 steps/s
    sleep_when_done: true

script:
  - id: start_motor
    then:
      - lambda: 'id(motor_running) = true;'
      - stepper.set_target:
             id: image_rotation_stepper
             target: 10
  - id: stop_motor
    then:
      - lambda: 'id(motor_running) = false;'
      - stepper.set_target:
             id: image_rotation_stepper
             target: 0
  
  - id: toggle_motor
    then:
      - if:
          condition:
            lambda: 'return id(motor_running) == false;'
          then:
            - script.execute: start_motor
          else:
            - script.execute: stop_motor

So I basically just reset the reported position back to 0 every time the loop runs.

2 Likes

thanks for this @paviro :slight_smile: can I ask how you then trigger the motor from homeassistant? to explain what I am trying to acheive, its running the motor for a catfeeder for x amounts of steps in the same direction each time I trigger an automation

I just use a switch:

switch:
  - platform: template
    name: "Rotation"
    id: rotation_switch
    icon: "mdi:rotate-360"
    lambda: |-
      if (id(motor_running)) {
        return true;
      } else {
        return false;
      }
    turn_on_action:
      - script.execute: start_motor
    turn_off_action:
      - script.execute: stop_motor

But my goal is continues rotation. Maybe a service would be nicer in your case.

1 Like