Test Catalogue
Every claim in this manual is backed by a test that prints the measured value. This
chapter lists all tests of the three repositories with their stimulus, their pass
criterion and the last result. The Status column says where the result comes from:
Scilab (run in Scilab 2027), Python (run in the Python twin, the Scilab run of this
version is pending), C (GoogleTest), ngspice.
Naming
| Prefix |
Meaning |
Where |
T |
test of the model or of the prototype against theory or limits |
sfs-stepper-sim/tests/test_T*.sce, twins in tools/ |
X |
cross-check: Scilab equals its Python twin |
tests/test_X*.sce + tests/reference/*.csv |
B |
power stage mapping |
tests/test_B01_bridge.sce |
S |
software in the loop: the C library in Xcos equals the prototype |
tests/test_S01_sil.sce |
SP |
ngspice power stage |
sfs-stepper-power-spice/tools/run_tests.py |
| GoogleTest suites |
library unit tests |
sfs-stepper-ctrl/tests/unit/ |
Motor model
| Test |
Stimulus |
Pass criterion |
Result |
Status |
| T00 |
1000 random states; current vector at φ = 0.7 |
power balance e·i = T·ω within 10⁻⁹ W; zero and restoring torque at p θ = φ |
1.1·10⁻¹³ W; −1.0·10⁻⁵ N·m restoring |
Scilab |
| T01 |
3.2 V on phase A, locked and free rotor |
steady current V/R within 10⁻⁶; free rotor stays at θ = 0 |
2.000000 A, error 2·10⁻⁹ |
Scilab |
| T02 |
voltage step, locked rotor |
i(t) = V/R (1 − e^(−t/τ)), t63 = L/R within 0.1 % |
t63 = 1.8750 ms |
Scilab |
| X01 |
rotating voltage 5 Hz el., free rotor |
Scilab (lsoda) equals Python (Radau) |
3.6·10⁻⁸ A, 8.8·10⁻⁷ rad/s |
Scilab |
Power stage and current loop
| Test |
Stimulus |
Pass criterion |
Result |
Status |
| B01 |
20 000 random voltage requests, both topologies |
duties 0 … 1, direction kept, exact when feasible; largest circle Vbus / Vbus/√2 |
direction error 2·10⁻¹⁶; 24.0000 V / 16.9706 V |
Scilab |
| T03 |
microstepping 2 A, 10 Hz el. |
A leads B by 90° ± 0.5°, amplitude ± 10 mA, rotor follows |
90.000°, 2.0000 A, lag 0.57° |
Scilab |
| T04 |
current step 0 → 2 A, locked, both topologies |
overshoot < 5 %, settling (2 %) < 1 ms, error < 0.1 % |
1.12 %, rise 0.35 ms, settling 0.40 ms |
Scilab |
| X02 |
current step, shared leg |
Scilab equals Python |
5·10⁻¹³ A |
Scilab |
| T08 |
controller for the nominal motor; plant R ×0.9 … 1.3, L ×0.8 … 1.2 (current step) and R, L, J ×5, load 0.15 N·m (ramp to 4 rev/s) |
step: overshoot < 10 %, settling < 2 ms, error < 1 %; ramp: load angle < 90° |
worst settling 1.6 ms (R ×1.3, L ×0.8); worst load angle 46.3° |
Python |
| T09 |
8 rev/s, both topologies |
shared leg limited earlier than full bridge, both synchronous |
1.862 A / 1.557 A, load angle 24.5° / 39.3° |
Scilab |
| T10 |
switching stage: hold 2 A; ±2 A with dead time; 4 rev/s |
ideal switches = averaged (< 1 mA); ripple = analytic ± 5 %; dead time error = formula ± 1 %; synchronous, peak < trip |
0.01 mA; 23.11 mA p-p (analytic 23.11); 0.07 mV deviation; peak 2.03 A |
Python |
| X04 |
switching stage, shared leg, 4 rev/s |
Scilab equals Python (10⁻⁶ A) |
— |
pending |
Motion
| Test |
Stimulus |
Pass criterion |
Result |
Status |
| T05 |
move 6400 µsteps (2 rev), 5 rev/s, 50 rev/s² |
target exact, |Δv| ≤ acc, monotonic, load angle < 45° |
499 ms, load angle 15.24°, final 6400.00 µsteps |
Scilab |
| T06 |
load step 0.25 and 0.5 N·m at 1 rev/s |
synchronous below K_t I with angle asin(T/(K_t I)); loss of synchronism detected above |
37.21° (theory 37.21°); slip at 151.9 ms |
Scilab |
| T07 |
reversal +4 → −4 rev/s |
synchronous, deceleration limit kept, final speed |
load angle 12.25°, −240.0 rpm |
Scilab |
| X03 |
move 160 µsteps |
motion generator + loop equal the Python twin |
4.9·10⁻¹³ A |
Scilab |
Resonance and friction
| Test |
Stimulus |
Pass criterion |
Result |
Status |
| T11a |
angle step 0.1 rad at 2 A |
natural frequency √(p K_t I / J)/2π ± 5 % |
248.1 Hz (theory 253.8 Hz) |
Python |
| T11b |
speed sweep 0.8 … 1.8 rev/s, detent 0.02 N·m |
largest oscillation at 4 p n = f_n ± 10 %, peak > 3× minimum |
peak at 1.2 rev/s (theory 1.27), ±13.6° |
Python |
| T11c |
5, 8, 11 rev/s, shared leg, 24 V |
oscillation < 1° / < 5° below the voltage limit, > 20° beyond |
0.0° / 1.3° / 47.6° |
Python |
| T12 |
unpowered rotor without back-EMF, T_c 0.01 N·m, 50 rad/s |
spin-down time (J/B) ln((ω0 + T_c/B)/(ω + T_c/B)) ± 1 % |
39.60 ms (theory 39.60 ms) |
Python |
Software in the loop
| Test |
Scenario |
Pass criterion |
Result |
Status |
| S01 |
current step, locked rotor |
currents < 5 mA from the prototype |
— |
pending re-run |
| S02 |
move 640 µsteps |
currents < 5 mA, commanded angle identical, rotor < 0.05 µstep |
1.05 mA, 0, 0.0075 µstep |
Scilab |
| S03 |
8 rev/s, both topologies |
amplitude as T09 ± 30 mA |
1.862 A / 1.557 A |
Scilab |
| S04 |
run 4 rev/s, switching stage |
currents and peak < 5 mA from the prototype |
— |
pending |
Library unit tests (GoogleTest)
| Suite |
Tests |
Covers |
SstepMath |
29 |
saturating arithmetic, gains from ratios (brute force over 200 000 cases), sine/cosine accuracy, integrator, duty to ticks |
SstepBridge |
5 |
random requests, circular amplitude, bus voltage scaling, very large requests keep the direction, zero request centred |
SstepMotion |
10 |
integer square root, two-revolution move (499 ms), short and negative moves, random targets without velocity step, retarget and reversal, run and reverse, hold |
SstepApi |
24 |
configuration validation, NULL arguments, state rules, trips, faults, hardware errors, late slow loop, bus voltage corner cases, feed-forward saturation |
SstepLoop |
8 |
closed loop with a motor model: current step, move, load step, reversal and stop, voltage limit by topology, bus voltage compensation, voltage drive, other microstep settings |
Result: 76 tests pass with the fixed point backend, 75 with float (one test is
backend-specific); 100 % line and branch coverage of src/; no finding under ASan and
UBSan. Status: C.
ngspice
| Test |
Pass criterion |
Result |
Status |
| SP01 |
device against the datasheet (Rds ±5 %, capacitances and Qg ±10 %, VSD ≤ 1.2 V) |
all within |
ngspice |
| SP02 |
step model within 15 mV for 1–3 A; driven gates never overlap |
12.8 mV; 154 ns gap |
ngspice |
| SP03 |
shunt sample within 1 % |
exact, settling 345 ns |
ngspice |
Running everything
| Repository |
Command |
| Stepper-C |
ctest --test-dir "build/[UnitTests]Stepper Motor Control" (and the Float preset) |
| sfs-stepper-sim |
scilab-cli -f tests/run_all.sce; Python: python tools/ref_*.py |
| sfs-stepper-power-spice |
python tools/run_tests.py |