FastAccelStepper

repository·master·Indexed 19 days ago

https://github.com/gin66/fastaccelstepper

A high-performance, interrupt-driven stepper motor control library for AVR, ESP32, RP2040, and SAM Due microcontrollers. Designed as a high-speed alternative to AccelStepper, it features fixed-point math (log2 representation), advanced motion profiles including linear acceleration, and multi-axis synchronization via command queues. Supports various pin configurations (1, 2, or 3-pin) and provides platform-specific pulse drivers to ensure efficient execution without runtime polymorphism.

Tokens
37.5K
Snippets
91
Records
145
Agent score
67%

What's inside FastAccelStepper

  1. Overview of FastAccelStepper

    master

    FastAccelStepper is a high-speed alternative to the AccelStepper library designed for stepper motor control. It is fully interrupt or task-driven, meaning it does not require a periodic function call in your main application loop.

    Key features include:

    • High Speed & Precision: Supports acceleration/deceleration with per-stepper max speed/acceleration and uses fixed-point arithmetic (log2 representation) instead of float calculations for efficiency.
    • Flexible Operation Modes: Supports 1-pin (positive move only), 2-pin (axis control), and 3-pin (power dissipation reduction) configurations.
    • Advanced Motion Control: Features constant acceleration control, configurable linear acceleration (cubic speed function via setLinearAcceleration()), and jump start from standstill (setJumpStart()).
    • Automation: Includes an auto-enable mode that enables the motor before movement and disables it after with configurable delays.
    • Multi-Axis Synchronization: Provides an API to fill a command queue for each stepper. Commands are tied to timer ticks (CPU frequency), allowing for near-synchronous starts of multiple steppers.
    • Resource Sharing: Enable and direction pins can be shared between multiple motors.
    • Hardware Abstraction: Uses platform-specific pulse drivers for AVR, ESP32, Pico, and SAM architectures.
  2. Overview of ESP32 StepperDemo with WebUI

    master
    The ESP32 StepperDemo with WebUI is a modern, web-based interface for controlling stepper motors on ESP32 platforms. Unlike the standard StepperDemo, this version provides a browser-based UI via WiFi, supports dynamic configuration (adding/configuring steppers on-the-fly), and offers extended pin support via I2S expanders (32 additional outputs). It also supports persistent configuration using LittleFS and real-time monitoring via WebSockets.
  3. Overview of ESP32 StepperDemo features

    master

    The ESP32 StepperDemo provides a web-based interface for controlling up to 14 stepper motors on an ESP32 using the FastAccelStepper library.

    Key Capabilities:

    • Web-based UI: Control steppers via any web browser.
    • Real-time updates: Uses WebSockets for live status updates.
    • Configuration management: Uses JSON-based config files stored in LittleFS.
    • REST API: Provides a full REST API for external system integration.
    • WiFi setup: Supports both serial and AP mode configuration.
  4. Configure Auto-Enable behavior for multiple steppers

    master

    When using setAutoEnable(true), the library manages the enable pin automatically.

    Key Behaviors:

    • Microstepping Warning: If using microstepping, enabling/disabling the motor may cause the stepper to jump to or from the closest full step position.
    • Shared Enable Pins: Multiple steppers can share a single enable pin. The engine manages this via a consensus mechanism:
      1. If a stepper needs to enable, it waits for its defined 'on delay' and sets the pin.
      2. If a stepper stops, it starts a 'delay off' counter.
      3. When the counter finishes, the engine asks all connected steppers if they agree to the disable request. If any other stepper is still running, the output stays enabled.
      4. Once all steppers are idle and their counters finish, the engine calls disableOutputs() for all steppers sharing that pin.
    • Limitation: The library does not support mixing High-Active and Low-Active enable logic on the same pin. Doing so will lead to unexpected behavior.
    • Delays:
      • The 'turn on' delay is minimal (MIN_CMD_TICKS).
      • The 'turn off' delay is implemented via cyclic tasks (ESP32) or cyclic interrupts (AVR). Actual turning off occurs approximately [(n-1)..n] * delay_period after the last step, where n >= 2.
  5. Understand the StepperISR Driver Architecture

    master

    The StepperISR layer acts as an abstraction between the high-level FastAccelStepper API and hardware-specific pulse generation drivers.

    Abstract Model

    Each StepperQueue instance functions as a generic pulse generator that:

    1. Accepts commands specifying steps and ticks (the period between steps).
    2. Outputs step pulses on a GPIO pin.
    3. Tracks position based on executed pulses.

    Hardware Constraints

    Depending on your microcontroller, pin assignment flexibility varies:

    • Flexible Assignment: ESP32 and Pico allow assigning pulse generators to GPIO pins freely.
    • Fixed Assignment: AVR architectures (e.g., ATMega) are restricted to specific pins (e.g., Timer1 on OC1A/OC1B).
  6. Configure pin sharing for Enable and Direction pins

    master

    When managing multiple motors, you can optimize pin usage through sharing:

    • Enable pin sharing: The common pin remains enabled as long as at least one motor is running plus a configured delay. Each motor still adheres to its own auto enable delay independently.
    • Direction pin sharing: The direction pin is driven exclusively by one motor at a time. If one motor is operating, other motors will wait until the direction pin becomes available before moving.
  7. How the Direction Pin Toggle Mechanism works

    master

    The library uses a toggle_dir flag within the queue_entry structure to signal a direction change.

    1. Detection: When addQueueEntry() is called, it compares the new direction with the current queue_end.dir.
    2. Queueing: If a direction change is detected, toggle_dir is set to 1 in the new entry.
    3. Execution: The ISR or driver checks entry.toggle_dir. If set, it toggles the direction pin before processing the steps in that entry.

    Note: If the queue is empty and the stepper is not currently running, addQueueEntry() toggles the direction pin directly instead of setting the flag.

    struct queue_entry {
      uint8_t steps;
      uint8_t toggle_dir : 1;      // Flag: toggle direction pin before this entry
      uint8_t countUp : 1;
      uint8_t moreThanOneStep : 1;
      uint8_t hasSteps : 1;
      // ...
    };
  8. Understand I2S Bit Serialization and Frame Layout

    master

    The ESP32 I2S outputs bits MSB-first within each 16-bit half (Left then Right).

    Frame Layout in Memory: Each frame consists of 4 bytes: [L_hi, L_lo, R_hi, R_lo].

    Bit Order: I2S outputs in time order: L_hi[7], L_hi[6], ..., L_hi[0], L_lo[7], ..., L_lo[0], R_hi[7], R_hi[6], ..., R_hi[0], R_lo[7], ..., R_lo[0]

  9. Understand the PIO state machine flow for Raspberry Pi Pico

    master

    The fastaccelstepper project utilizes the Raspberry Pi Pico's Programmable I/O (PIO) state machines to handle high-speed stepper motor control. The PIO implementation follows a specific execution flow involving a Step Loop and a Period Loop to manage acceleration, direction, and step pulses with minimal CPU intervention.

    High-Level Execution Flow

    1. Main Loop: Initiates the process by pulling data from the OSR (Output Shift Register) into the X register.
    2. Step Loop Start: Prepares the X register with encoded motion parameters (R, U, D, C) and sets up the direction (Y) and OSR.
    3. Direction Branching: Determines the direction pin state based on the D bit.
    4. Step Branching: Evaluates the step pulse requirement. If a step is required, it enters the Update Start phase to modify the state machine's internal registers.
    5. Update Phase: Updates the motion parameters (R, U, D, C) based on the current state. Note that there are different cycle counts depending on the U bit value.
    6. Period Loop: Handles the timing between steps. It uses a loop body that executes 3 * (R - 1) cycles to maintain the required period.
    7. End Branch: Checks if the motion sequence is complete (if C-1 == 0). If not, it loops back to the Step Loop; otherwise, it returns to the Main Loop.
  10. Understand the forceStop() Contract

    master

    When calling forceStop(), the following behaviors are guaranteed:

    1. Best effort stop: The driver stops as quickly as the hardware allows. Note that for DMA-based drivers (like I2S or RMT), pulses already committed to hardware buffers may still be physically output.
    2. Position not guaranteed: The reported position may not exactly match the number of physically output pulses. The error is bounded by the driver's buffering depth.
    3. Queue is cleared: The queue is logically emptied, and all remaining commands are discarded.
    4. State reset: The driver resets its internal state (e.g., _isRunning = false) so the stepper can accept new commands immediately.
  11. Synchronize multiple axes for coordinated movement

    master

    FastAccelStepper can be used for multi-axis applications by executing raw commands (without internal ramp generation) to achieve near-synchronous starts. This allows an external planner (like Marlin) to handle the multi-dimensional acceleration/speed calculations while FastAccelStepper handles the tick-exact execution of the resulting step pulses.

    To maintain synchronization between two steppers, observe these constraints:

    • Enable Delay: If configured, the stepper queue adds pauses at startup for enable delay. To avoid synchronization drift, it is recommended not to use enable on delay.
    • Direction Change Delay: If configured, a pause is added to the command queue for every direction change. To maintain sync, either execute direction changes together with a pause or disable direction change delay.
    • ESP32 RMT Driver: Due to the internal implementation, pauses may be introduced before/after direction changes. Tick-exact execution cannot be assumed unless the application explicitly generates these pauses during command generation.
  12. Hardware Connection Requirements for FastAccelStepper

    master

    Stepper motors must be connected via a driver IC (e.g., A4988). The library supports 1, 2, or 3-wire connections using Step, Direction, and Enable signals.

    Step Signal Pin Constraints

    • AVR ATmega168/328/P: Only Pins 9 and 10.
    • AVR ATmega32u4: Only Pins 9, 10, and 11.
    • AVR ATmega2560: Only Pins 6, 7, and 8. (Note: On PlatformIO, these can be changed to other triples like 11/12/13 for Timer 1, 5/2/3 for Timer 3, or 46/45/44 for Timer 5 using the FAS_TIMER_MODULE setting).
    • ESP32: Any output-capable port pin. Supports I2S for additional steppers (Mux mode for up to 32 extra steppers or Direct mode for 1-3 extra steppers, requires IDF ≥5.3).
    • Pico: Any GPIO up to 31.
    • Atmel SAM Due: Specific pin groups: (34/67/74/35), (17/36/72/37/42), (40/64/69/41), (9), (8/44), (7/45), or (6).

    Direction and Enable Signals

    • Direction Signal (Optional): Any output-capable port pin. On ESP32, I2S Mux slots can be used. Position counting direction is configurable via setDirectionPin() (defaults to High).
    • Enable Signal (Optional): Any output-capable port pin. On ESP32, I2S Mux slots can be used. Enable state is configurable via setEnablePin() (defaults to Low).