A stepper that loses steps is found on the bench, not in the code
Microstepping drivers hide the physics: a current loop that lags at speed, a bus voltage that runs out, a rotor resonance, a dead time that distorts the current. Finding them on hardware costs boards and time; a library tested only on its own unit tests does not see them at all.
The motor is a dynamic system
A two-phase motor model with back-EMF, detent torque and friction shows load angle, loss of synchronism and resonance before the motor is connected.
Every MCU is different
Configuration in engineering units, callbacks for PWM and outputs, a fixed point backend without FPU and a float backend with one; no clock, no heap.
The same code everywhere
The C library runs unchanged inside Xcos (software in the loop) and is compared sample by sample with the Scilab prototype and its Python twin.
Three repositories, one verified chain
A control library, a simulation environment and a power stage model that hand their results to each other.
Stepper-C library
Current control
Simple integration
Two loop functions and four callbacks connect it to any board.
Software in the loop
Open one file in Scilab and watch the real C code drive the motor model.
Motor and control theory
Equations
Power stage in ngspice
Dead time
Measured results
Test catalogue and design limits from the models.
Quick start
A driver instance, two loops, four callbacks¶
Stepper-C needs two functions from your board — one that writes the PWM compare values and one that switches the gate drivers on or off — and two periodic calls: the fast loop in the PWM/ADC interrupt and the slow loop at 1 kHz.
#include "sstep.h"
/* Board functions (your HAL) */
extern void board_pwm_set(const uint16_t compare[SSTEP_LEGS_MAX]);
extern void board_gate_enable(bool on);
static int pwm_write(void* ctx, const uint16_t cmp[SSTEP_LEGS_MAX])
{
(void)ctx;
board_pwm_set(cmp);
return 0;
}
static int output_enable(void* ctx, bool on)
{
(void)ctx;
board_gate_enable(on);
return 0;
}
static struct sstep motor;
void app_start(const struct sstep_config* cfg) /* cfg.hal uses the two functions */
{
(void)sstep_init(&motor, cfg);
(void)sstep_enable(&motor);
(void)sstep_move_to(&motor, 3200); /* one revolution at 1/16 */
}
void adc_isr(uint16_t ia, uint16_t ib, uint16_t vbus) /* 20 kHz */
{
const struct sstep_sample s = { ia, ib, vbus };
(void)sstep_fast_loop(&motor, &s);
}
void tick_1khz(void)
{
(void)sstep_slow_loop(&motor);
}
A complete configuration for the 17HS19-2004S1 motor on the B-G431B-ESC1 board is in Using the library. Before the first motor turns on the bench, run the same code in the software-in-the-loop diagram.
Find your way¶
| If you want to… | Read |
|---|---|
| Understand what the system is and what it is not | Introduction |
| See how the three repositories work together | System Architecture |
| Install Scilab, the compiler, Python and ngspice and run everything | Getting Started |
| Understand the motor equations and the conventions | Motor Model |
| Understand the current loop, the power stage mapping and the motion generator | Control Algorithms |
| Add the library to a firmware project | Stepper-C Library |
| Look up a function, structure or return code | API Reference |
| Simulate a scenario or change the model | Simulation |
| Run the real C code against the motor model in Xcos | Software in the Loop |
| See what the power stage does in the dead time | Power Stage Model |
| Find a test and its pass criteria | Test Catalogue |
| Know the speed, resonance and dead time limits | Results and Design Guidance |
| Read everything offline or print it | PDF manual |
SystemFromScratch®
Part of an open-source embedded portfolio
Stepper-C is developed by Anton Vynohradov under SystemFromScratch® — embedded software and hardware built from the first schematic to certification.
SystemFromScratch® is a registered trademark. STM32 and B-G431B-ESC1 are trademarks of STMicroelectronics; Stepper-C is not affiliated with or endorsed by STMicroelectronics.