Skip to content

Introduction

Stepper-C is a C11 library that drives a two-phase hybrid stepper motor with closed-loop sinusoidal current control. Given the measured phase currents and bus voltage, it computes the PWM compare values of the power stage, and it turns motion commands (move to a position, run at a velocity, stop) into a smooth microstep trajectory. It runs on any MCU: the hardware is reached only through callbacks, and the numeric backend is either fixed point (no FPU needed) or single-precision float.

What the library does

  • Controls the phase currents. One PI controller per phase with back-EMF feed-forward and anti-windup, gains derived from the motor's R and L and the requested bandwidth. An open-loop voltage mode is available for boards without current sensing.
  • Generates the microstep angle. Sine/cosine current references from a 32-bit electrical angle, 1 to 256 microsteps per full step.
  • Plans the motion. Trapezoidal profile with separate acceleration and deceleration, no overshoot, smooth replacement of a running command; constant-velocity mode; stop.
  • Fits the voltage to the power stage. Two full H-bridges (4 legs) or three half-bridges with a shared leg (3 legs); the request is limited to what the topology and the measured bus voltage can deliver, keeping its direction.
  • Protects the hardware. Overcurrent, overvoltage and undervoltage trips in the fast loop, hardware-callback errors, external faults; outputs off within the same period.
  • Detects a stall without a sensor. A back-EMF observer reports a rotor that stops, falls out of synchronism or slips at standstill (SSTEP_FAULT_STALL, optional).
  • Reduces the current at standstill. Hold current after a configurable delay.

What the library does not do

Concern Why it is not in the library
Timer, PWM and ADC drivers Hardware-specific; you start the conversions and pass raw ADC counts in, and write the compare values out in a callback.
Interrupt and task setup Every system has its own; the library only defines which function runs at which rate. See the integration guide.
Position feedback (encoder) The library is an open-loop positioner with closed-loop current; the rotor position is not measured. Sensorless stall detection reports a lost synchronism but does not correct the position.
Homing, limit switches, G-code, multi-axis coordination Application logic on top of sstep_move_to(), sstep_set_position() and the status.
Motor parameter identification R, L and Kt come from the datasheet or a measurement.
Communication (UART, CAN, Modbus…) Out of scope; call the API from your protocol handler.

Who it is for

  • Firmware for stepper drives on a general-purpose MCU with gate drivers, for example STMicroelectronics B-G431B-ESC1 or a custom board with two H-bridges.
  • Machines with several axes, one driver instance per motor, no shared state.
  • Projects that must be reviewed or certified: MISRA C:2012, 100 % coverage, no heap, bounded execution time.

Key properties

Property Value
Language C11, no warnings with -Wall -Wextra -Wpedantic -Wconversion
Dependencies <stddef.h>, <stdint.h>, <stdbool.h> only
Numeric backends Fixed point Q15/Q31 (integer only) or single-precision float, chosen at build time
Memory No heap, no global or static mutable data (.data and .bss are empty)
RAM per instance 432 B fixed point, 456 B float on Cortex-M4 (details)
Flash 9.0 KiB fixed point, 9.7 KiB float (Cortex-M4, -Os, both topologies)
Stack sstep_fast_loop() 216 B, sstep_slow_loop() 152 B worst case (Cortex-M4 -Os, details)
Coding standard MISRA C:2012, 0 Cppcheck addon violations, 1 deviation
Tests 100 % line and branch coverage of src/ in both backends; closed-loop tests on a motor model
Thread safety One fast-loop context and one slow-loop context per instance, by design; see Threading
License Apache License 2.0

Terminology

Full step
1/200 of a revolution for a 1.8° motor; a quarter of an electrical period.
Microstep
A full step divided by microsteps (power of two, 1 to 256). Positions and velocities of the API are in microsteps.
Electrical angle
Angle of the current vector in the two phases; one electrical period is four full steps. Held as a 32-bit unsigned number, one turn = \(2^{32}\).
Per unit (pu)
Internal signals are relative to a base value: currents to i_full_scale_ma, voltages to vbus_nominal_mv. 1.0 pu is the base.
Fast loop
sstep_fast_loop(), called from the PWM/ADC interrupt at fast_loop_hz (typically 20 kHz): current control and PWM.
Slow loop
sstep_slow_loop(), called at slow_loop_hz (typically 1 kHz): trajectory, angle, currents, events.
Leg
One half-bridge (high-side and low-side switch) of the power stage, driven by one PWM compare value.
Load angle
Electrical angle between the commanded current vector and the rotor; it grows with the load torque and the motor loses steps when it exceeds 90° (180° to the next stable position).

Conventions in this documentation

  • Engineering units in the API are integers with the unit in the field name: _mohm, _uh, _ma, _mv, _hz, _ms, _ns.
  • "Fixed point" and "float" name the two numeric backends; numbers are given for both when they differ.
  • The example motor is a 17HS19-2004S1 (1.6 Ω, 3.0 mH, 2.0 A, 0.21 N·m/A, 200 steps) on a 24 V supply; the example board is a B-G431B-ESC1 (three half-bridges).