SkillAgentSearch skills...

StepperMotors

Python stepper motor library with customizable acceleration strategies and responsive, interruptible motor operations.

Install / Use

/learn @juanmf/StepperMotors

README

Intro

Although Python and PC in general (RPI in particular) are not optimal for accurate timing of stepper motor pulses (OS scheduler + Python sleep inaccuracies and, ATM, Global Interpreter Lock [GIL]), this library aims at providing a versatile tool for managing a set of stepper motors (through their drivers) in several ways that might fit specific scenarios.

A few distinct concepts have been implemented:

  • Driver (or Controller, used interchangeably), each instantiated driver will behave as a dedicated single thread worker (see BlockingQueueWorker) which receives steps jobs through a shared queue, in an attempt decouple steps timing from the rest of the system, (here the GIL imposes some challenged in theory).
  • StepperMotor, encapsulates the motor characteristics, like min and max PPS (pulses per second), and instantaneous
    torque. A Generic motor is implemented that can be constructed with specifics in case of lacking implementation of
    your motor (you are welcome to add it).
  • Navigation, The driver can navigate from A to B, setting direction & sending pulses to the motor, statically (as in a 3D printer scenario where planning is made up front), dynamically (for interactive or event based systems that need to quickly respond to unplanned speed and direction changes), or centrally synchronized for several motors ran in choir (this is also dynamic).
  • AccelerationStrategies or profiles, handle how to reach max speeds for the motor. Linear, Exponential & Custom (which takes motor's instantaneous torque or a list of transformations as input to max out your motor capabilities). Custom acceleration strategy has a pre-requisite that you use the Benchmark module (see bellow) to find optimal
    transformations for your motor, in a production setup (proper load applied). All changes are effected as a function of current motor' speed in PPS. (other systems use curves as function of time. I found that impractical)
    • DelayPlanners (in tandem with Navigation modes) enable Drivers to handle inertia gracefully either in a static or dynamic context. DelayPlanner implementations determine if it's time to start breaking, speeding up or stay steady. Acceleration strategies effect proper changes to speed.
  • Benchmark, a stress test module to find your motor's (under current load), min & max speeds, and instantaneous torque characteristics, all in terms of PPS. For instantaneous torque characteristics the output (with format [(minPPS, incrementPPS_1), (minPPS + incrementPPS_1, incrementPPS_2), ..., (maxPPS, 0)]) can be used as YourStepperMotorSubClass.TORQUE_CURVE or as an input to CustomAccelerationPerPps acceleration strategy's transformations constructor argument. This enables your motor to reach max speed in the least amount of steps possible while keeping synch (useful when speed matters).
    • Currently tested on (see https://www.reddit.com/r/robotics/comments/18ukw4p/benchmarking_stepper_motor/):
      • Raspberry Pi 4B with,
      • DRV8825 driver board
      • PG35S_D48_HHC2 stepper motor
  • EventDispatcher centralized events broker Drivers use to notify any subscriber if steppingComplete events, finalStep
    or in advance (10 steps in advance by default). your app can also use it to publish and subscribe to app level events.
    It's a neat way to allow for extension points without modifying working classes. In multiprocess scenario EventDispatcher uses MultiprocessObserver to gain awareness of, and proxy events from, child dedicated process running motor drivers, so in effect, driver events are (re)published in MainProcess where your app resides.

Implemented Drivers

The following table shows what driers have specific implementations, and vaguely their signaling specs, headers marker with * are concepts the MotorDriver base class knows about, Explicitly implemented Driver names are marked with *Bolded. Driers that should work with implemented classes in Italic

| Driver | Step* (Pulse 20-50μs) | Direction* | Enable* | Sleep* | Microstepping* (Number of Pins) | Fault | Implemented | |-------------------------------------------------------------------------------|-----------------------|------------|------------|------------|---------------------------------|-------|-------------| | DRV8825 | 1-2μs (min) | HIGH/LOW | ACTIVE LOW | ACTIVE LOW | 3 (2^3 = 8 modes) | YES | Yes | | TMC2209 | 1-2μs (min) | HIGH/LOW | ACTIVE LOW | NA | 4 (2^4 = 16 modes) | YES | Yes | | A4988 | 1-2μs (min) | HIGH/LOW | ACTIVE LOW | ACTIVE LOW | 3 (2^3 = 8 modes) | NO | Eq(DRV8825) | | TB6600 | 1-2μs (min) | HIGH/LOW | ACTIVE LOW | ACTIVE LOW | 3 (2^3 = 8 modes) | YES | | | TB6560 | 1-2μs (min) | HIGH/LOW | ACTIVE LOW | ACTIVE LOW | 3 (2^3 = 8 modes) | YES | | | TMC2208 | 1-2μs (min) | HIGH/LOW | ACTIVE LOW | NA | 4 (2^4 = 16 modes) | YES | Eq(TMC2208) | | TMC2226 | 1-2μs (min) | HIGH/LOW | ACTIVE LOW | NA | 4 (2^4 = 16 modes) | YES | Eq(TMC2208) | | Adafruit Motor HAT Adapter | - | - | - | - | 4 (2^4 = 16 modes) | - | Yes | | LV8729 | 1-2μs (min) | HIGH/LOW | ACTIVE LOW | ACTIVE LOW | 3 (2^3 = 8 modes) | NO | Eq(DRV8825) | | L298N Not supported | 1-2μs (min) | HIGH/LOW | ACTIVE LOW | ACTIVE LOW | 3 (2^3 = 8 modes) | NO | | | ULN2003 (Unipolar) | Full cycle on/off | Sequence | - | - | - Full & Half step | NO | Yes |

Also implements an adapter to Adafruit stepper motor driver.

Demo

All motors driven by dedicated DRV8825.

Demo with 2 steppers at 400PPS (0.2 Deg/step)

2 Steppers * 3 pins each (dir, step, sleep)

2 steppers

Demo with 4 steppers at 400PPS 2 (0.2 Deg/step) + 4 Nema17 1.8 Deg/step

2 Steppers * 3 GPIO pins (dir, step, sleep) 2 Steppers * 2 GPIO pins (dir, step)

4 steppers

Demo TMC2209(Nema17-17hs4401) + DRV8825(PG35S)

TMC2209 + DRV8825

Install

Happy path

If everything works fine (on my RPI this method gets stuck.)

pip install -i https://pypi.org/simple/ stepper-motors-juanmf1

Manually

Manually (find latest link at https://pypi.org/project/stepper-motors-juanmf1/#files copy link for stepper_motors_juanmf1-<latest version>-py3-none-any.whl). Example with stepper_motors_juanmf1-0.0.2-py3-none-any.whl:

juanmf@raspberrypi:~/project/project $ wget https://test-files.pythonhosted.org/packages/8b/7d/289fdee8b0a01e3c0927b9407e14803341daa0d50e65cb592de9a41581b7/stepper_motors_juanmf1-0.0.2-py3-none-any.whl
--2024-01-08 14:23:42--  https://test-files.pythonhosted.org/packages/8b/7d/289fdee8b0a01e3c0927b9407e14803341daa0d50e65cb592de9a41581b7/stepper_motors_juanmf1-0.0.2-py3-none-any.whl
...
Saving to: ‘stepper_motors_juanmf1-0.0.2-py3-none-any.whl’

stepper_motors_juanmf1-0.0.2-py3-none-any.whl      100%[================================================================================================================>]  21.98K  --.-KB/s    in 0.007s  

2024-01-08 14:23:43 (3.01 MB/s) - ‘stepper_motors_juanmf1-0.0.2-py3-none-any.whl’ saved [22507/22507]

juanmf@raspberrypi:~/project/project $ pip install ../
stepper_motors_juanmf1-0.0.2-py3-none-any.whl  project/                                        
juanmf@raspberrypi:~/project/project $ pip install ../stepper_motors_juanmf1-0.0.2-py3-none-any.whl 
Looking in indexes: https://pypi.org/simple, https://www.piwheels.org/simple
Processing /home/juanmf/project/stepper_motors_juanmf1-0.0.2-py3-none-any.whl
Installing collected packages: stepper-motors-juanmf1
Successfully installed stepper-motors-juanmf1-0.0.2

To upgrade to a newer release manually, find latest whl file as explained above, then: now installing stepper_motors_juanmf1-0.0.4-py3-none-any.whl, overriding 0.0.3

juanmf@raspberrypi:~/project $ pip install --upgrade stepper_motors_juanmf1-0.0.4-py3-none-any.whl
Looking in indexes: https://pypi.org/simple, https://www.piwheels.org/simple
Processing ./stepper_motors_juanmf1-0.0.4-py3-none-any.whl
Installing collected packages: stepper-motors-juanmf1
  Attempting uninstall: stepper-motors-juanmf1
    Found existing installation: stepper-motors-juanmf1 0.0.3
    Uninstalling stepper-motors-juanmf1-0
View on GitHub
GitHub Stars29
CategoryDevelopment
Updated1mo ago
Forks1

Languages

Python

Security Score

95/100

Audited on Feb 17, 2026

No findings