TeensyStep Fast Stepper Library

repository·master·Indexed 43 days ago

https://github.com/luni64/teensystep

A high-performance stepper motor control library for PJRC Teensy boards (3.0, 3.1, 3.2, 3.5, 3.6) and STM32F4. It supports pulse rates up to 300kHz, synchronous movement for up to 10 motors, and independent movement for 4 groups. The library includes acceleration profiles via LinRotAccelerator, LinStepAccelerator, and SinRotAccelerator, as well as a custom ErrorHandler for intercepting module-specific errors.

Tokens
8.9K
Snippets
45
Records
52
Agent score
54%

What's inside TeensyStep

  1. Overview of TeensyStep Fast Stepper Library

    master
    TeensyStep is a high-performance Arduino library designed for PJRC Teensy boards (3.0, 3.1, 3.2, 3.5, 3.6) and STM32F4. It is optimized for handling synchronous and independent stepper motor movements, including continuous rotation. The library supports high-speed operation with pulse rates up to 300,000 steps per second.
  2. TeensyStep Technical Specifications

    master

    TeensyStep provides high-speed stepper control with the following capabilities:

    FeatureSpecificationDefault
    Motor speed / pulse rate1 - 300,000 stp/s800 stp/s
    Acceleration0 - 500,000 stp/s²2,500 stp/s²
    Pull in speed50 - 10,000 stp/s100 stp/s
    Synchronous movementUp to 10 motors-
    Independent movement4 groups (1 to 10 motors per group)-
    Step pulse polarityActive HIGH or LOWActive HIGH
    Step pulse width1 - 100µs5µs
    Direction signal polaritycw / ccwcw
  3. Manage delay channels in TeensyStepFTM

    master

    The TeensyStepFTM namespace provides functions to manage hardware-backed delay channels used for timing interrupts. You can register a handler that implements the IDelayHandler interface to receive interrupt callbacks via addDelayChannel.

    To use this, implement the delayISR(unsigned channel) method in a class derived from IDelayHandler. This method will be called when the timer reaches the specified delay value for that channel.

    class MyHandler : public IDelayHandler {
    public:
        void delayISR(unsigned channel) override {
            // Handle the interrupt for this specific channel
        }
    };
    
    MyHandler handler;
    unsigned myChannel = TeensyStepFTM::addDelayChannel(&handler);
    // ... later ...
    TeensyStepFTM::removeDelayChannel(myChannel);
  4. Control the step timer in TimerField

    master

    The step timer controls the frequency of motor steps. Use setStepFrequency to define the speed and stepTimerStart/stepTimerStop to control execution.

    • setStepFrequency(unsigned f): Sets the step frequency in Hertz. Passing 0 will automatically stop the step timer.
    • stepTimerStart(): Resumes and refreshes the step timer to ensure immediate start.
    • stepTimerStop(): Pauses the step timer.
    • stepTimerIsRunning(): Returns true if the step timer is currently active.
    • getStepFrequency(): Returns the current timer clock frequency.
    timerField.setStepFrequency(1000); // 1kHz
    timerField.stepTimerStart();
    
    if (timerField.stepTimerIsRunning()) {
        // ...
    }
    
    timerField.stepTimerStop();
  5. Manage timers with TimerControl

    master

    The TimerControl class acts as the manager for all timer instances. To make a timer functional, it must be registered with the controller.

    Workflow:

    1. Call TimerControl::begin() once in your setup.
    2. Create a PeriodicTimer or OneShotTimer instance.
    3. Register the timer using TimerControl::attachTimer(timer_pointer).
    4. Call TimerControl::tick() frequently in your main loop to process timer expirations.
    5. Use TimerControl::detachTimer(timer_pointer) to remove a timer from the management list.

    Note: TimerControl::tick() is the engine that drives the callbacks. If it is not called, timers will not fire.

    PeriodicTimer myTimer([]() { /* task */ });
    
    void setup() {
        TimerControl::begin();
        TimerControl::attachTimer(&myTimer);
        myTimer.setFrequency(10.0f);
        myTimer.start();
    }
    
    void loop() {
        TimerControl::tick();
    }
  6. Use LinRotAccelerator for linear rotation acceleration profiles

    master

    The LinRotAccelerator class implements a linear acceleration/deceleration profile for rotation. It allows you to define a target speed and acceleration rate, which the accelerator then uses to smoothly ramp the speed up or down over time based on a specified update period.

    Key Methods:

    • prepareRotation(currentPosition, targetSpeed, acceleration, accUpdatePeriod, speedFactor): Initializes the acceleration profile.
      • targetSpeed: The desired final speed.
      • acceleration: The acceleration rate (typically in units/s²).
      • accUpdatePeriod: The time interval (in microseconds) between speed updates.
      • speedFactor: A multiplier for the target speed (defaults to 1.0).
    • updateSpeed(currentPosition): Calculates and returns the new target speed for the current step. This should be called periodically to advance the acceleration profile.
    • initiateStopping(currentPosition): Sets the target speed to 0 to begin a deceleration phase.
    • overrideSpeed(factor): Dynamically scales the target speed by a multiplier.
    • overrideAcceleration(factor): Dynamically scales the acceleration rate by a multiplier.
    LinRotAccelerator accel;
    
    // Initialize: target speed 1000, acceleration 5000, update every 1000us
    accel.prepareRotation(0, 1000, 5000, 1000);
    
    // In your main loop or timer interrupt:
    int32_t nextSpeed = accel.updateSpeed(currentPosition);
    // Use nextSpeed to drive your stepper motor...
  7. Perform non-blocking continuous rotation with rotateAsync()

    master

    Use rotateAsync() to command one or more steppers to rotate continuously without blocking the main execution loop. This method calculates Bresenham parameters for synchronized multi-motor rotation based on the vMax of each stepper and uses the lowest acceleration among the provided steppers.

    You can pass steppers as a variadic list of arguments or as an array of pointers.

    Note: The rotation is managed via an internal accelerator and timer ISR. The rotation continues until stopAsync() is called or the speed reaches zero.

    // Using variadic arguments
    controller.rotateAsync(stepper1, stepper2, stepper3);
    
    // Using an array of stepper pointers
    Stepper* motors[] = {&stepper1, &stepper2};
    controller.rotateAsync(motors);
  8. Configure PIT frequency and reload values

    master

    The PIT class allows fine-grained control over the timer's timing parameters:

    • setFrequency(uint32_t val): Sets the timer frequency based on the bus frequency (F_BUS).
    • setThisReload(uint32_t ldval): Sets the reload value (LDVAL) immediately for the current cycle.
    • setNextReload(uint32_t ldval): Sets the reload value to be used for the next timer cycle.
    • getLDVAL(): Returns the current reload value.
    • getCVAL(): Returns the current compare value.
  9. Get and set current position

    master

    Use these methods to track or manually override the stepper's current position.

    • getPosition(): Returns the current position as an int32_t.
    • setPosition(int32_t pos): Manually sets the current position value.
    int32_t currentPos = myStepper.getPosition();
    
    // Reset position to zero
    myStepper.setPosition(0);
  10. Monitor motor controller status

    master

    Use the following methods to query the state of the motor controller:

    • isOk(): Returns true if the controller is in a valid state.
    • isRunning(): Returns true if the step timer is currently active (motors are moving).
    • isAllocated(): Returns true if the step timer has been allocated.
    • getCurrentSpeed(): Returns the current step frequency (speed) of the motors.