The problem
Many EV subsystems use brushed DC motors, such as wipers, seat and mirror drives, pumps and small traction motors in toys and carts, and the DC motor is the standard first plant for learning feedback control. Students often tune PID gains by trial and error without seeing the link to bandwidth, phase margin and actuator limits. This project makes that link explicit.
Objectives
- Derive and implement the DC motor transfer function from first principles.
- Design a PI or PID speed controller to a stated bandwidth and phase margin.
- Test reference tracking and load-torque disturbance rejection.
- Show the effect of voltage saturation and anti-windup on large steps.
- Compare the linear model with a Simscape physical model.
What you need
Tools and toolboxes
- Simulink — Motor model from Transfer Fcn or Integrator blocks, PID Controller block, logging.
- Control System Toolbox — tf, step, bode, margin and pidtune for design and analysis.
- Simscape Electrical — Optional: DC Motor block for a physical-network comparison. Not needed for the core project.
Software
- MATLAB R2023b or later
- Simulink
- Control System Toolbox
Extra parts and data
None beyond the software above.
Key concepts
- DC motor equations
- Electrical: V = R·i + L·di/dt + Ke·ω. Mechanical: J·dω/dt = Kt·i − b·ω − TL. In SI units Kt and Ke are numerically equal for an ideal motor.
- Bandwidth and phase margin
- Bandwidth sets how quickly the loop responds; phase margin sets how well damped it is. Around 60 degrees of phase margin gives a step response with little overshoot.
- Integrator windup
- When the controller output hits the supply voltage limit, the integral term keeps growing, causing a large overshoot when the error finally reverses. Anti-windup stops or bleeds off the integrator during saturation.
- Disturbance rejection
- A load torque step is a disturbance entering at the plant. Integral action removes the steady-state speed error it causes.
Step-by-step guide
- 1
Choose example motor parameters
Pick a labelled example set for a 24 V, roughly 200 W motor: R = 0.5 ohm, L = 1 mH, Kt = Ke = 0.05 N·m/A, J = 1e-4 kg·m², b = 1e-5 N·m·s. Put them in a script and compute the electrical time constant L/R, the mechanical time constant, the no-load speed V/Ke and the stall current V/R. If you have a real motor datasheet, use it instead and note the source.
Checkpoint: Script prints no-load speed near 480 rad/s and stall current of 48 A for the example set.
- 2
Derive the transfer function
Take Laplace transforms of both equations with TL = 0 and derive ω(s)/V(s) = Kt / ((J·s + b)(L·s + R) + Kt·Ke). Create it with tf in MATLAB, find its poles, and plot step and bode responses. Note that the electrical pole is much faster than the mechanical pole, which justifies a first-order approximation for a first controller design.
Checkpoint: step() of the open-loop plant at 24 V settles to the computed no-load speed.
- 3
Build the Simulink plant
Build the motor from Integrator, Gain and Sum blocks, with current and speed as explicit states so you can log them and inject a load torque. Add a Saturation block on the applied voltage at ±24 V. Use a variable-step solver such as ode45 with a relative tolerance of 1e-4, or a fixed step of 1e-5 s if you later move to discrete control.
Checkpoint: The Simulink open-loop step overlays the tf step response in Simulation Data Inspector with no visible difference.
- 4
Design the controller
Choose a target, for example closed-loop bandwidth of 50 rad/s and phase margin of at least 60 degrees. Use pidtune(G, 'PI', 50) and check with margin on the loop transfer function. Also tune a PID and compare. Record gains, gain and phase margins and predicted rise time, and explain why derivative action adds little here and amplifies sensor noise. Save the gains in the parameter script so that every later test uses the same values.
Checkpoint: margin() reports phase margin of at least 60 degrees at the chosen crossover.
- 5
Test reference tracking
Insert the PID Controller block with the designed gains and apply speed steps of 10, 50 and 90 per cent of no-load speed. Log speed, current and voltage. The small step should match the linear prediction; the large step will saturate the voltage and show a slower, more overshooting response. Measure rise time, overshoot and settling time for each. Plot current alongside speed, because the current spike during acceleration shows how close the motor comes to its stall-current limit.
Checkpoint: The 10 per cent step matches predicted rise time within about 10 per cent; the 90 per cent step clearly saturates.
- 6
Add anti-windup
Set the PID block's output saturation to ±24 V and enable clamping anti-windup, then repeat the large step. Compare overshoot and settling with and without anti-windup on one plot. Also try back-calculation with a tracking gain and note which behaves better for your motor. Explain the difference from the integrator state trace. Keep both runs in one Simulation Data Inspector session so the overlay is easy to export for the report, and note the tracking gain you settled on.
Checkpoint: Overshoot on the large step drops noticeably with anti-windup, and the integrator state stays bounded.
- 7
Test disturbance rejection
With speed at 50 per cent, apply a load torque step equal to half the rated torque. Measure maximum speed dip and recovery time. Repeat with a P-only controller to show the steady-state error that integral action removes. Run a sweep of Ki values with sim() in a loop and plot dip against recovery time to show the trade-off. Note the hand-calculated P-only error, load torque divided by the loop gain, beside the measured value.
Checkpoint: PI recovers to zero steady error; P-only leaves a steady error matching the hand calculation.
- 8
Compare with a physical model and report
Optionally rebuild the plant with the Simscape Electrical DC Motor block driven by a Controlled Voltage Source and compare responses. Summarise the design procedure, margins, step and disturbance results, and the saturation study. State model limits such as no brush drop, no friction non-linearity and an ideal speed sensor. If you do not have Simscape Electrical, compare instead with a model that adds a 0.5 V brush drop and Coulomb friction, which shows the same kind of mismatch.
Checkpoint: A report where every plot is regenerated by one script, and the Simscape and linear responses agree for small steps.
Testing & validation
- Open-loop step matches no-load speed V/Ke.
- Phase margin of the designed loop meets the target.
- Small-step response matches the linear prediction.
- Anti-windup reduces overshoot on saturating steps.
- Integral action removes steady error after a load step.
Expected results
A documented DC motor speed controller designed to stated margins, with measured tracking, disturbance rejection and saturation behaviour, and a clear explanation of why each tuning choice was made.
Take it further
- Add a cascaded inner current loop and compare with the single speed loop.
- Discretise the controller at 1 kHz and study the effect of sample rate.
- Add Coulomb friction and a quantised encoder and retune.
- Generate code for the DIYguru embedded kit's motor driver in a later project.
Viva and review questions
Why can you approximate the DC motor as first order?
The electrical time constant L/R is much shorter than the mechanical time constant, so the current settles almost instantly compared with speed and the slow mechanical pole dominates.
What does anti-windup do?
It stops the integral term accumulating while the output is saturated, so the controller does not overshoot badly once the error changes sign.
Why did you avoid derivative action?
With a PI loop the phase margin was already adequate, and derivative action would amplify speed-sensor noise without a clear benefit.
Learn it at DIYguru
These DIYguru courses and programmes teach what this project needs.
