Page 1 of 1

Stepper motors with PIO

Posted: Sat Apr 03, 2021 6:24 am
by Leonti
Hi!

I'm trying to write my first PIO program to control stepper motors.
I'd like to be able to tell it how many steps to make and what would be a delay between steps.
After hours and hour of reading docs and watching Youtube videos I'm still not able to write a working program.

Here is what I have so far:

Code: Select all

import time
import rp2
from machine import Pin

@rp2.asm_pio(set_init=rp2.PIO.OUT_LOW)
def stepper():
  pull()
  mov(x, osr) # delay

  pull()
  mov(y, osr) # steps

  label("step")
  set(pins, 1)
  label("delay")
  set(pins, 0)
#  irq(rel(0)) # <- runs continously
  jmp(x_dec, "delay")
#  irq(rel(0)) # <- only a single invocation
  jmp(y_dec, "step")

def turn(sm):
  print("irq")

# at 10_000Hz, 1 tick is 100us
sm = rp2.StateMachine(0, stepper, freq=10000, set_base=Pin(25))

sm.irq(turn)
sm.active(1)
sm.put(2)
sm.put(3)

time.sleep(1)
sm.active(0)
Here is the intention of this code:
1. Read delay between pulses and put it in x
2. Read a number of steps and put it in y
3. Have a loop "step" and iterate until y is zero with "jump(y_dec, "step")"
4. For each step set pin to HIGH and then have a waiting loop for the duration specified in x

I'm invoking an interrupt for debugging and I'm confused by the results.
If I put it inside of the "delay" loop it would just execute continuously until the state machine is stopped. I would expect it to finish after x has become 0.
If I put it inside of the "step" loop it's only executed once. I expected it to be executed 4 times because of sm.put(3)

What am I doing wrong here?
Also, is there a way to keep a copy of x so I can reset it in each "step" back to its original value after it reaches 0?

Cheers,
Leonti

Re: Stepper motors with PIO

Posted: Sat Apr 03, 2021 7:07 am
by Roberthh
You can MOV X to ISR and back. ISR is not used. like:

Code: Select all

import time
import rp2
from machine import Pin

@rp2.asm_pio(set_init=rp2.PIO.OUT_LOW)
def stepper():
  pull()
  mov(isr, osr) # delay

  pull()
  mov(y, osr) # steps

  label("step")
  mov(x, isr)
  set(pins, 1)
  label("delay")
  set(pins, 0)
#  irq(rel(0)) # <- runs continously
  jmp(x_dec, "delay")
#  irq(rel(0)) # <- only a single invocation
  jmp(y_dec, "step")

def turn(sm):
  print("irq")

# at 10_000Hz, 1 tick is 100us
sm = rp2.StateMachine(0, stepper, freq=10000, set_base=Pin(25))

sm.irq(turn)
sm.active(1)
sm.put(2)
sm.put(3)

time.sleep(1)
sm.active(0)
You can also swap the pulling of step and delay (delay second), such that you can always reload the X value from the OSR. Just mov(x, osr) does not clear the value of osr. Like:

Code: Select all

import time
import rp2
from machine import Pin

@rp2.asm_pio(set_init=rp2.PIO.OUT_LOW)
def stepper():
  pull()
  mov(y, osr) # steps

  pull()  # get delay, but keep it in osr
 
  label("step")
  mov(x, osr)  # get delay from OSR
  set(pins, 1)
  label("delay")
  set(pins, 0)
#  irq(rel(0)) # <- runs continously
  jmp(x_dec, "delay")
#  irq(rel(0)) # <- only a single invocation
  jmp(y_dec, "step")

def turn(sm):
  print("irq")

# at 10_000Hz, 1 tick is 100us
sm = rp2.StateMachine(0, stepper, freq=10000, set_base=Pin(25))

sm.irq(turn)
sm.active(1)
sm.put(3)  # steps
sm.put(2)  # delay

time.sleep(1)
sm.active(0)

Re: Stepper motors with PIO

Posted: Sat Apr 03, 2021 7:46 am
by Leonti
Thanks Robert!
I used second approach and it works properly now.

Can you explain why it was in a never ending loop without resetting X?

Cheers,
Leonti

Re: Stepper motors with PIO

Posted: Sat Apr 03, 2021 8:34 am
by Roberthh
Of course. Then the delay loop expires teh first time, it left X at a value of 0. Then Y was decremented, and a few steps later the statement `jmp(x_dec, "delay")` was performed the next time. With X being 0 before and X being an unsigned 32bit int, it will be decremented to 0xffffffff, or 4294967295 decimal, which is a pretty large number. Decrementing that to 0 takes a while. At the frequency of 10000 which you have set and 2 PIO clock cycles per loop it takes about 10 days.

Re: Stepper motors with PIO

Posted: Sat Apr 03, 2021 8:59 am
by Leonti
Thank you Robert!

Now it all makes sense!