The problem
Every EV drive has torque and current limits, and every practical speed controller has an integrator. During a hard acceleration or a steep climb the controller saturates, the integrator keeps growing, and when the limit releases the vehicle overshoots its target. The fix is well known but often implemented without understanding the differences between methods. This project makes the problem and its cures measurable.
Objectives
- Build an EV speed loop with a torque-limited motor and road load.
- Reproduce integrator windup in hard acceleration and hill scenarios.
- Implement clamping, back-calculation and conditional integration anti-windup.
- Compare overshoot, recovery time, peak jerk and energy.
- Study the back-calculation gain and recommend settings.
What you need
Tools and toolboxes
- Simulink — Plant, saturation, custom PI with each anti-windup scheme and the built-in PID Controller block for comparison.
- Control System Toolbox — pidtune or the PID Tuner app on the hand-linearised plant for the unsaturated baseline design. Manual tuning works on a base licence.
- MATLAB — Scripted test runs with sim(), the back-calculation gain sweep and the comparison table.
Software
- MATLAB R2023b or later
- Simulink
Extra parts and data
None beyond the software above.
Key concepts
- Integrator windup
- When the actuator is saturated the error persists, and the integrator keeps accumulating it. After saturation ends, the large stored integral holds the output high and causes overshoot.
- Clamping
- Stops integration whenever the output is saturated and the error would drive it further into saturation. Simple and effective in most cases.
- Back-calculation
- Feeds the difference between the saturated and unsaturated controller output back into the integrator through a gain Kb, bleeding off the stored integral. Kb sets how fast it unwinds.
- Conditional integration
- Integrates only when the error is small or the output is not saturated. It is easy to explain but needs a threshold that suits the operating range.
Step-by-step guide
- 1
Build the plant
Use example EV parameters: 1500 kg, Cd 0.3, A 2.2 m², Crr 0.01, tyre radius 0.3 m, gear ratio 9 and a motor with ±200 N·m torque limits. Build the longitudinal model with drag, rolling and grade forces and integrate to speed. Add a Saturation block on torque and a 50 ms first-order torque lag. Fixed-step solver at 10 ms.
Checkpoint: Full-torque acceleration from 0 to 100 km/h takes a plausible time for the parameters.
- 2
Design the baseline PI
Linearise the plant by hand at 60 km/h (a first-order lag with time constant m/(ρ·Cd·A·v0)) and use pidtune to get a PI controller with a response time of a few seconds and phase margin above 60 degrees. Test small speed steps of 2–3 km/h that do not saturate the torque. Record overshoot and settling as the baseline. Store the gains in the parameter script so every anti-windup version uses exactly the same Kp and Ki, and only the anti-windup logic differs between them.
Checkpoint: Small-step overshoot under 2 per cent with torque well below the limit.
- 3
Reproduce windup
Build the PI from Gain, Integrator and Sum blocks so the integrator is accessible, with no anti-windup. Apply a large step from 0 to 100 km/h, and a long 8 per cent hill where the motor saturates for many seconds. Log speed, unsaturated controller output, saturated torque and integrator state in the Simulation Data Inspector. Mark on the plot the moment the torque comes out of saturation and the moment speed peaks, to show the delay caused by the stored integral. Record the overshoot and recovery time.
Checkpoint: The integrator state grows far beyond what is needed during saturation, and speed overshoots clearly after the step.
- 4
Implement clamping
Add logic that sets the integrator input to zero when the output is saturated and the error has the same sign as the output. Use a Switch block and a comparison, or the Integrator block's external reset and reset logic. Compare with the built-in PID Controller block's clamping option to check your version. Test the logic in both directions, including deceleration with regenerative torque at its negative limit. Confirm that the integrator resumes normally once the output leaves saturation.
Checkpoint: Custom and built-in clamping give matching responses, with much less overshoot than the windup case.
- 5
Implement back-calculation
Compute the difference between saturated and unsaturated output, multiply by Kb and add it to the integrator input. A common starting point is Kb near Ki/Kp or 1/Ti. Sweep Kb over a decade either side and record overshoot and recovery time for the large step and hill scenarios. Plot the integrator state for three values of Kb on the same figure to show how quickly it is bled off. Pick a value and justify the choice from the sweep.
Checkpoint: A plot of overshoot against Kb showing too small a gain behaves like windup and a well-chosen gain removes most overshoot.
- 6
Implement conditional integration
Integrate only when |error| is below a threshold, for example 5 km/h, or when the output is unsaturated. Test with thresholds of 2, 5 and 10 km/h. Observe that a small threshold can leave a steady error on a hill where saturation is long and the error stays large. Explain why the threshold must suit the operating range and why one threshold may not work for both small corrections and large steps. Compare its behaviour with clamping on the hill case.
Checkpoint: Results for each threshold, with any steady error or slow recovery clearly identified.
- 7
Compare schemes
Run all schemes on a test set: large acceleration step, deceleration step with regeneration limit, long hill and a sequence of steps. Compute overshoot, time to settle within 1 km/h after saturation ends, peak jerk and energy used. Script the runs with sim() and put results in one table. Use the same test sequence and seed for each run. Highlight in the table which scheme is best for each scenario and whether any scheme is best everywhere.
Checkpoint: A comparison table across schemes and scenarios with a clear winner or trade-off per scenario.
- 8
Discrete-time check
Discretise the controller at 10 ms using a Discrete PID or discrete-time Integrator with forward Euler, as embedded code would. Repeat the comparison. Check that the clamping logic still behaves correctly with one-sample delay. Watch for a one-sample delay in the saturation feedback, which can cause small oscillations when the output is near its limit. Compare the continuous and discrete results in one table, and add a short note on how the clamping condition is written in C for an embedded implementation.
Checkpoint: Discrete results match continuous results closely, with any differences explained.
- 9
Report
Present the windup mechanism, each scheme's equations and block diagram, the comparison table and the back-calculation gain study. Recommend a scheme and settings for this drive. State that the model is a simplified longitudinal plant and that the same issue appears in current loops with voltage saturation. Include a block diagram of each scheme and the equations behind it. Note any practical issues such as tuning effort and sensitivity to measurement noise.
Checkpoint: A report with a recommendation backed by the comparison numbers.
Testing & validation
- Small-step baseline unaffected by any anti-windup scheme.
- Windup case shows clear overshoot that each scheme reduces.
- Custom clamping matches the built-in PID block's clamping.
- Discrete-time results consistent with continuous-time results.
Expected results
A clear demonstration of integrator windup in a torque-limited EV drive and a quantified comparison of three anti-windup schemes, with a recommended scheme and gain.
Take it further
- Apply anti-windup to a dq current loop with voltage limit.
- Add rate limiting on torque for comfort and study interaction with anti-windup.
- Use a reference governor to avoid saturation instead of handling it.
- Generate code and test in software-in-the-loop.
Viva and review questions
Why does windup cause overshoot?
During saturation the integrator stores a large value that is not needed. After saturation ends, that stored value keeps the output high until the error reverses and unwinds it.
How do you choose the back-calculation gain?
A common start is about 1/Ti. Too small does little; too large can unwind the integrator so fast that it fights normal operation. The sweep shows the useful range.
Why does anti-windup not change small-step behaviour?
Anti-windup only acts when the output saturates. For small steps the output stays within limits, so the controller behaves as the plain PI.
Learn it at DIYguru
These DIYguru courses and programmes teach what this project needs.
