PID speed control#
Tutorial · 12 min read · ESP32, 12 V DC motor, encoder
How I got both wheels to hit their target speed without overshoot, and the graphs that prove it.
Overview#
A speed controller with feedforward and anti-windup
A repeatable step-response test
A live plot of target vs measured speed
The idea#
PID reacts after an error appears. Feedforward predicts the voltage a speed needs. Feedforward does most of the work, PID cleans up the rest.
Step 1: The control loop#
float ff = kS * sign(target) + kV * target;
float err = target - measured;
integral = clamp(integral + err * dt, -iMax, iMax);
float pwm = ff + kP * err + kI * integral;
clamp on the integral is the anti-windup. Without it the motor overshoots
every time it leaves saturation.
Results#
Metric |
Before |
After |
|---|---|---|
Overshoot |
[X] % |
[Y] % |
Settling time |
[X] ms |
[Y] ms |
Steady-state error |
[X] % |
[Y] % |
Troubleshooting#
The loop jittered when Wi-Fi was busy#
Moving the web server to the other core fixed it.
Low speeds stuttered#
Static friction. The kS term solved it.
A few emails a month. Unsubscribe anytime.