# Interrupts with Yukon and stepper motors

**URL:** <https://forums.pimoroni.com/t/interrupts-with-yukon-and-stepper-motors/23967>\
**Category:** Support\
**Created:** [January 25, 2024, 9:17pm UTC](https://forums.pimoroni.com/t/interrupts-with-yukon-and-stepper-motors/23967 "2024-01-25T21:17:55Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![Shoe](https://avatars.discourse-cdn.com/v4/letter/s/e36b37/32.png) [@Shoe](https://forums.pimoroni.com/u/Shoe)\
**Post date:** [January 25, 2024, 9:17pm UTC](https://forums.pimoroni.com/t/interrupts-with-yukon-and-stepper-motors/23967/1 "2024-01-25T21:17:55Z")

</div>

I’ve been trying to use the Yukon and a Dual Motor/Bipolar Step module to build a small machine for a science demo. What I’m trying to do at the moment is get the board to recognise an end-stop button/limit switch, which triggers an interrrupt, and then changes the direction of the Stepper. However, as far as I can tell when you call `stepper.move_to(step, duration)` there’s no graceful way to interrupt the movement of the motor to reverse the direction without, it seems, releasing the motor, which then seems to need the whole thing re-initialised. I’ve then not been able to get it reinitialised to start driving again in the opposite direction.

Has anyone else been able to get something like this working? I’m tempted to move to a more simple driver board as `OkayStepper` isn’t well documented and seems to have a few quirks.

---

<div class="post-metadata">

**Author:** ![ZodiusInfuser](https://sea2.discourse-cdn.com/flex016/user_avatar/forums.pimoroni.com/zodiusinfuser/32/10546_2.png) [@ZodiusInfuser](https://forums.pimoroni.com/u/ZodiusInfuser)\
**Post date:** [January 26, 2024, 8:21pm UTC](https://forums.pimoroni.com/t/interrupts-with-yukon-and-stepper-motors/23967/2 "2024-01-26T20:21:30Z")

</div>

Hi!

Yukon developer here. That sounds like a nice project!

As you have noted `OkayStepper` is not that featureful or well documented at present. This is because my own knowledge of how to drive stepper motors is limited, which is why I gave the class that self-deprecating name. I opened a discussion thread on the product’s Github back in November looking for feedback ([Stepper Motor Improvements Discussion · pimoroni/yukon · Discussion #6 · GitHub](https://github.com/pimoroni/yukon/discussions/6)), though it seems you are the first customer to use this functionality.

For your project, it does appear I neglected to include some kind of `stop()` command. For the pen plotter project I performed the homing routine using lots of small movements, checking the limit switches in between. This meant I never encountered that gap of functionality in the library. Had I used interrupts I immediately would have.

If you have time this weekend, could you try adding the following function into `OkayStepper` within `stepper.py` then calling it from your interrupt?

```python
def stop(self):
    self.__step_timer.deinit()
    self.hold()
    self.__moving = False

```

Or if I’ve misunderstood your requirements, please let me know. I can also be reached in the Yukon channel on our Discord.

---

<div class="post-metadata">

**Author:** ![Shoe](https://avatars.discourse-cdn.com/v4/letter/s/e36b37/32.png) [@Shoe](https://forums.pimoroni.com/u/Shoe)\
**Post date:** [January 26, 2024, 8:28pm UTC](https://forums.pimoroni.com/t/interrupts-with-yukon-and-stepper-motors/23967/3 "2024-01-26T20:28:29Z")

</div>

Hello!

Cool, I did spot the note that it was called `OkayStepper` for a reason, but thought I’d have a go at it anyway.

I’ll try to add that function tomorrow and see how it goes.

Thanks!

---

<div class="post-metadata">

**Author:** ![Shoe](https://avatars.discourse-cdn.com/v4/letter/s/e36b37/32.png) [@Shoe](https://forums.pimoroni.com/u/Shoe)\
**Post date:** [January 27, 2024, 9:32pm UTC](https://forums.pimoroni.com/t/interrupts-with-yukon-and-stepper-motors/23967/4 "2024-01-27T21:32:34Z")

</div>

Hello again!

So, I popped that code into `stepper.py` and the interrupts _mostly_ work now (also, hurray for having libraries in Python! I know a lot of `Pimoroni_pico` is a base of C with Python on top for ease of development, but it makes it really hard to tinker with).

An issue I’m having is that sometimes the stepper ignores the sign on the `steps` changing and simply continues in the same direction. If I manually press the limit switch then sometimes rather than reversing direction the stepper keeps moving, but slows down every time I press the switch. What I assume is happening is that when `stop()` is called, it is halting the motor but not resetting something like `self.__end_microstep`, so the next `stepper.move_to()` command is being added on top of the remaining portion of previous requests giving a different result than everything just starting from fresh?

I’ve tried adding `stepper.__end_microstep = 0` to the interrupt but still have the issue. I might tinker more tomorrow if I get time.

> **The code, in case that's helpful**
>
> ```python
> from pimoroni_yukon import Yukon
> from pimoroni_yukon import SLOT6 as SLOT
> from pimoroni_yukon.modules import DualMotorModule
> from pimoroni_yukon.devices.stepper import OkayStepper
> from machine import Pin
> import time
> 
> # Constants
> CURRENT_SCALE = 0.5 # How much to scale the output current to the stepper motor by, between 0.0 and 1.0
> 
> # Variables
> yukon = Yukon() # Create a new Yukon object
> module = DualMotorModule() # Create a DualMotorModule object
> stepper = None # A variable to store an OkayStepper object created later
> # Number of steps to take
> stepSize = -10000
> # Duration of steps
> stepDuration = 5
> 
> # Set up limit switch pins
> leftStop = Pin(26, Pin.IN, Pin.PULL_UP)
> rightStop = Pin(27, Pin.IN, Pin.PULL_UP)
> 
> # IRQ for LEFT limit switch, reverse the direction of the platform
> def callbackLeft(irq):
> # Halt the motor
> global stepper
> stepper.stop()
> stepper.__end_microstep = 0
> # Reverse the direction, move to other end of device
> global stepSize
> stepSize = 10000
> 
> # IRQ for RIGHT limit switch, move the platform left a little and then halt
> def callbackRight(irq):
> # Halt the motor
> global stepper
> stepper.stop()
> stepper.__end_microstep = 0
> # Reverse the direction and move a little
> global stepSize
> stepSize = -100
> global stepDuration
> stepDuration = 1
>    
> # Attach interrupts to limit switch pins
> leftStop.irq(trigger=Pin.IRQ_FALLING | Pin.IRQ_RISING, handler=callbackLeft)
> rightStop.irq(trigger=Pin.IRQ_FALLING, handler=callbackRight)
> 
> # Wrap the code in a try block, to catch any exceptions (including KeyboardInterrupt)
> try:
> yukon.register_with_slot(module, SLOT) # Register the DualMotorModule object with the slot
> yukon.verify_and_initialise() # Verify that a DualMotorModule is attached to Yukon, and initialise it
> yukon.enable_main_output() # Turn on power to the module slots
> 
> # Create a class for controlling the stepper motor, in this case OkayStepper, and provide it with the DualMotorModule's two outputs
> stepper = OkayStepper(module.motor1, module.motor2, current_scale=CURRENT_SCALE)
> 
> # Set the hardware current limit to its maximum (OkayStepper controls current with PWM instead)
> module.set_current_limit(DualMotorModule.MAX_CURRENT_LIMIT)
> #module.set_current_limit(DualMotorModule.MAX_CURRENT_LIMIT)
> module.enable() # Enable the motor driver on the DualMotorModule
> 
> # Loop until the BOOT/USER button is pressed
> while not yukon.is_boot_pressed():
> if not stepper.is_moving():
> stepper.move_to(stepSize, stepDuration) # Initiate the movement
> 
> finally:
> if stepper is not None:
> stepper.release() # Release the stepper motor (if not already done so)
> 
> # Put the board back into a safe state, regardless of how the program may have ended
> yukon.reset()
> 
> ```

---

<div class="post-metadata">

**Author:** ![ZodiusInfuser](https://sea2.discourse-cdn.com/flex016/user_avatar/forums.pimoroni.com/zodiusinfuser/32/10546_2.png) [@ZodiusInfuser](https://forums.pimoroni.com/u/ZodiusInfuser)\
**Post date:** [January 28, 2024, 12:04am UTC](https://forums.pimoroni.com/t/interrupts-with-yukon-and-stepper-motors/23967/5 "2024-01-28T00:04:39Z")

</div>

Judging by your variable name `stepSize` and the comment `move a little` I think you should be using `move_by()` rather than `move_to()` for the movements you want.

- `move_by()` is for moving a position relative to where the stepper last was. I use this during the homing phase of the pen plotter.

- `move_to()` is for moving to a global position, with zero being where the stepper was powered on at (or where `zero_position()` was last called). I used this during the drawing phase of the pen plotter.

(I assume you found it, but here is the pen plotter code: [yukon/examples/showcase/plotter/main.py at main · pimoroni/yukon · GitHub](https://github.com/pimoroni/yukon/blob/main/examples/showcase/plotter/main.py))

So in your code you are initially moving from zero to -10000, then to either -100 or +10000 (whichever corresponds to those limit switches). That would explain the behaviour you saw, because if it was moving to -10000 and you hit the right switch at -50, it would then try and move to -100.

I acknowledge that more documentation would clarify this difference.

Also 10000 steps is quite a lot to do in 1 second! I think at most the pen plotter had 3000 steps of travel across its 1 metre axis, and that took multiple seconds.

Oh, and another not documented feature that may be useful. When creating the `OkayStepper` you can specify a `steps_per_unit` value to convert your steps into useful units like centimetres. (There are also `move_to/by_steps()` functions that ignore this if needed)

Edit:

> I know a lot of `Pimoroni_pico` is a base of C with Python on top for ease of development, but it makes it really hard to tinker with).

There are performance advantages to having the code in C, though I admit not all of Pimoroni Pico needed that. Ideally this stepper driver would be in C, as MicroPython introduces all sorts of timing quirks that made `OkaySteppers` development challenging. For example, its not possible to run Yukon’s monitoring system without it causing the stepper movement to stutter. Once `OkayStepper` becomes `ActuallyGoodStepper` I will look at porting it.

---

<div class="post-metadata">

**Author:** ![Shoe](https://avatars.discourse-cdn.com/v4/letter/s/e36b37/32.png) [@Shoe](https://forums.pimoroni.com/u/Shoe)\
**Post date:** [January 28, 2024, 2:44pm UTC](https://forums.pimoroni.com/t/interrupts-with-yukon-and-stepper-motors/23967/6 "2024-01-28T14:44:56Z")

</div>

Ah, ok, so this probably explains all of the issues I’ve been having. Previously when I’ve used steppers (admittedly not that often) the move command was essentially “move to a position X steps clockwise/anticlockwise **from the current position** ”. I wasn’t expecting something which thought in terms of “move to a position which is X steps from **the intial** position”. I know you have a robotics background, is that the way it is generally done in industry/research? It might be worth just clarifying that in the stepper example for other people like me who’ve come from the Arduino libraries.

Thanks for the undocumented stuff, I’ll tinker with what I’ve got and see if I’ve time to work those into it. I need to get this working reliably and preferably looking fancy for a few weeks’ time, so it might be tight, especially as I’ve not really built machines before!

I know some of my other parameters were a bit weird, I was mostly working through things empirically with what actually got the spindle turning and getting very confused over why the stepper sometimes moved the platform to the perfect position, but sometimes overran it.

---

<div class="post-metadata">

**Author:** ![ZodiusInfuser](https://sea2.discourse-cdn.com/flex016/user_avatar/forums.pimoroni.com/zodiusinfuser/32/10546_2.png) [@ZodiusInfuser](https://forums.pimoroni.com/u/ZodiusInfuser)\
**Post date:** [January 29, 2024, 9:41am UTC](https://forums.pimoroni.com/t/interrupts-with-yukon-and-stepper-motors/23967/7 "2024-01-29T09:41:45Z")

</div>

> Previously when I’ve used steppers (admittedly not that often) the move command was essentially “move to a position X steps clockwise/anticlockwise **from the current position** ”. I wasn’t expecting something which thought in terms of “move to a position which is X steps from **the initial** position”.

Ah, that’s useful to know. I came at it from the mindset of “if someone is using steppers, over motors+encoders (like I was), then they are likely using them for their precise position control” and so that functionality should be baked in rather than the user having to write it themselves on top. Perhaps that was a wrong assumption.

The only library for stepper driving I used before was CircuitPython’s, which gave the single function of `oneStep()` you have to call all the time. And I intentionally avoided looking at other larger stepper libraries from arduino etc to avoid potential issues with code licences.

> I know you have a robotics background, is that the way it is generally done in industry/research?

Industry tend not to share what solutions they use, though I am aware that Field Oriented Control (see [https://simplefoc.com/](https://simplefoc.com/)) is quite common, which pairs a stepper (or brushless) motor with an encoder to give more efficient position/velocity control, since the motor only needs to be energised when the encoder value changes.

> I’ll tinker with what I’ve got and see if I’ve time to work those into it. I need to get this working reliably and preferably looking fancy for a few weeks’ time, so it might be tight, especially as I’ve not really built machines before!

I look forward to seeing the results!

---

<div class="post-metadata">

**Author:** ![SirFico](https://avatars.discourse-cdn.com/v4/letter/s/bcef8e/32.png) [@SirFico](https://forums.pimoroni.com/u/SirFico)\
**Post date:** [August 5, 2026, 7:07pm UTC](https://forums.pimoroni.com/t/interrupts-with-yukon-and-stepper-motors/23967/8 "2026-08-05T19:07:48Z")

</div>

@ZodiusInfuser Hi, just got a couple of steppers plus the dual motor / bipolar step boards for the Yukon, so I was wondering if you make any progress along the path to " Once `OkayStepper` becomes `ActuallyGoodStepper` I will look at porting it ". Is any porting on the cards? Thanks.
