Design PID Control for DC Motor Using Classical Control Theory
This example shows how to design a PID controller for a DC Motor using classical control theory. Alternatively, you can use Steady State Manager, Model Linearizer, Frequency Response Estimator, or PID tuner apps to streamline the design.
To design the controller using concepts such as gain and phase margin, you need a linearized model. To learn how to linearize models with converters, see Linearize DC-DC Converter Model.
Open Model
Open the DesignDCMotorPIDControl model.
myModel = "DesignDCMotorPIDControl";
open_system(myModel);
In this example, you model a DC Motor driven by a Controlled Voltage Source block. The Control block provides the control command, which is the voltage applied by the Controlled Voltage Source. You can run the system using closed-loop control or an open-loop.
First, you linearize the model, plot the frequency response, and compute the phase margin. Then, you design a proportional control, which changes the magnitude of the Bode plot but does not change the phase. This control reduces oscillations but introduces a larger steady-state error due to the lower gain. You then design a PI control, which changes both the gain and phase. This controller eliminates the steady-state error, but the response is slower. Finally, you design a PID control, which introduces a response to the derivative of the output, speeding up the response.
Linearize Averaged Switching Model and Plot Frequency Response
Set up the model to allow linearization. Set the model to start from steady state and configure the inputs to run in open loop.
set_param(myModel + "/Solver Configuration",DoDC="on"); set_param(myModel + "/Manual Switch",sw="1");
Linearize the model using the linmod function and obtain a SISO state-space model with the voltage as input and the angular speed as output.
[A,B,C,D] = linmod(myModel);
The transfer function is the Laplace transform of the impulse response of the open-loop system. This equation defines the transfer function in terms of the state-space matrices:
The variable to control is the output speed. Compute the open-loop transfer function G from the state-space representation matrices A, B, C, and D.
G = @(w) C*(1i*w*eye(size(A))-A)^-1*B + D; figure; plotBodeTransferFunction(G, maxFrequency)

Compute Phase Margin
To calculate the phase margin, first obtain the frequency when the gain is 0 dB and calculate the phase at that frequency. To calculate the gain margin, bring the open-loop system to the verge of instability, which occurs at a phase angle of .
[gainMargindB,phaseCrossoverPulsation,phaseMargin,gainCrossoverPulsation] = getStabilityCharacteristics(G);
Plot the Bode diagram with stability margins.
figure; plotBodeTransferFunction(G,maxFrequency) plotPhaseMargin(phaseMargin,gainCrossoverPulsation, maxFrequency);

Plot the closed-loop step response.
num = [1];
den = [1];
designDCMotorPIDControlPlotRPM("P");
The small phase margin of the open-loop indicates the closed-loop system is very close to instability. Consequently, the step response oscillates until the response settles down. Also, a small steady-state error indicates that the control needs integral action.
Design Proportional Controller
The plant is already stable. A proportional controller could speed up the response but also make it unstable.
A proportional controller changes the magnitude of the Bode plot while the phase remains the same.
Choose a crossover frequency with a sufficient phase margin. In this case, 15 Hz allows a phase margin of around , which is not yet sufficient but better than the current value.
crossoverFreqP =15; % Hz pulsationP = crossoverFreqP*2*pi; % rad/s phaseMarginP = 180 + angle(G(pulsationP))/pi*180 % deg
phaseMarginP = 23.7178
Calculate the proportional controller gain.
Kp = 1/abs(G(pulsationP))
Kp = 0.0362
Plot the new open-loop transfer function with the proportional control.
figure; plotBodeTransferFunction(G, maxFrequency) Gp = @(w) Kp*(C*(1i*w*eye(size(A))-A)^-1*B + D); plotBodeTransferFunction(Gp, maxFrequency);
Plot the Bode diagram with the stability margins.
[gainMarginP,phaseCrossoverPulsationP,phaseMarginP,gainCrossoverPulsationP] = getStabilityCharacteristics(Gp); plotPhaseMargin(phaseMarginP,gainCrossoverPulsationP, maxFrequency); subplot(2,1,1); legend("Plant","Kp * Plant");

Verify that the closed-loop system is now stable by plotting the output voltage of the converter.
num = Kp;
den = 1;
designDCMotorPIDControlPlotRPM("P")
Although the oscillations are significantly reduced, the plot now shows a larger a steady-state error due to the lower gain. If you calculate and observe the closed-loop transfer function, the order of the numerator and denominator polynomials is the same, which indicates a finite error at steady state for a step input.
Design Proportional-Integral Controller
A proportional-integral controller changes both the gain and the phase of the open-loop Bode plot. The transfer function of the PI control is:
where:
is the proportional controller gain.
is the integral control constant.
is the Fourier transform variable.
To calculate the gains analytically, use the relation of the control gain and phase. From the Bode plot, determine the control gain and phase you need, and then use this expression to calculate the gains:
where:
is the amplitude of the control.
is the phase of the control.
is the variable expressed in the time domain.
Firstly, determine the value of the crossover frequency and the phase margin. A reduction in speed improves the steady-state accuracy. Reduce around 10-20% of the crossover frequency.
crossoverFreqPI =10; % Hz phaseMarginPI =
50; % deg pulsationPI = crossoverFreqPI*2*pi; % rad/s
Then, calculate the amplitude and phase of the plant at this frequency.
gainGpulsationPI = abs(G(pulsationPI)); gainGpulsationPIdB = 20*log10(abs(G(pulsationPI))); angleGpulsationPI = angle(G(pulsationPI))/pi*180; % deg controlPhase = -180 + phaseMarginPI - angleGpulsationPI % deg
controlPhase = -6.3275
The control has an angle of Match the phases of both sides of the previous equation to obtain the value of .
; ;
If , then
Ki = tand(controlPhase+90)/pulsationPI
Ki = 0.1435
Calculate the gain of the plant at the gain crossover frequency and obtain the value of the proportional controller gain.
controlPIGain = 1/gainGpulsationPI; Kp = controlPIGain*pulsationPI*Ki/sqrt(1+(Ki*pulsationPI)^2)
Kp = 0.0116
Plot the new open-loop transfer function with the PI controller and the step response of the closed-loop system.
Gpi = @(w) Kp*(1+Ki*w*1i)/(Ki*w*1i)*(C*(1i*w*eye(size(A))-A)^-1*B + D); figure; plotBodeTransferFunction(G,maxFrequency); plotBodeTransferFunction(Gpi, maxFrequency); [gainMarginPI,phaseCrossoverPulsationPI,phaseMarginPI,gainCrossoverPulsationPI] = getStabilityCharacteristics(Gpi); plotPhaseMargin(phaseMarginPI,gainCrossoverPulsationPI, maxFrequency); subplot(2,1,1); legend("Plant","PI * Plant");

num = [Kp*Ki Kp];
den = [Ki 0];
designDCMotorPIDControlPlotRPM("PI")
The integral control successfully eliminates the steady-state error. However, the response is now slower. You need derivative action to speed up the response.
Design Proportional-Integral-Derivative Controller
A proportional-integral-derivative controller changes both the gain and the phase of the open-loop Bode plot. The control introduces a response to the derivative of the output, which makes the controller faster. The transfer function of the PID control is:
,
where:
is the proportional controller gain.
is the integral control constant.
is the derivative control constant.
is the Fourier transform variable.
is the filtering factor.
To calculate the gains analytically, use the following relation of the control gain and phase. There are four parameters to determine. After you determine the phase margin, you can determine the crossover frequency, the angle of the integral component, and the filtering factor of the derivative component.
,
where:
is the amplitude of the control.
is the phase of the control.
is the variable expressed in the time domain.
To start, choose the gain crossover frequency and phase margin. The derivative action compensates for the lag from the integral component, so you can select a frequency greater than the integral and proportional control. Choose a crossover frequency superior to the crossover frequency of the plant and a phase margin larger than the integral control.
crossoverFreqPID =100; % gainCrossoverPulsation; % Hz phaseMarginPID =
70; % deg
The control gain is the inverse of the plant at the crossover frequency.
gainGpulsationPID = abs(G(crossoverFreqPID*2*pi)); controlPIDGain = 1/gainGpulsationPID;
Calculate the control phase shift. The control phase is the difference between the plant phase and the angle given by the phase margin .
pulsationPID = crossoverFreqPID*2*pi; % rad/s angleGpulsationPID = angle(G(pulsationPID))/pi*180; % deg controlPhase = -180 + phaseMarginPID - angleGpulsationPID; % deg
Determine the angle of the integral component and calculate the integral control constant like you did for the PI control.
integralPhase =-10; % deg Ki = tand(integralPhase+90)/pulsationPID
Ki = 0.0090
Now that you have set the phase margin for the PID and the integral action phase, calculate the derivative action phase, .
derivativePhase = phaseMarginPID - 180 - angleGpulsationPID - integralPhase %degderivativePhase = 77.3773
After you design the integral action, choose a value of Keep in mind that the value of limits the maximum value of . A high value of makes certain values of impossible.
If the value of is too high, reduce the integral phase value to enable higher derivative action phases. Choose a value of 0.01 for and calculate the value of .
N =
0.01;Use this trigonometrical identity to obtain a second order equation, from which you can get two solutions for :
Kd = ((1-N)+sqrt((N-1)^2 - 4*N*(tand(derivativePhase))^2))/(2*pulsationPID*N*tand(derivativePhase))
Kd = 0.0253
Next, calculate the proportional gain using the amplitude equation derived from the control equation:
Kp = controlPIDGain/(sqrt(Ki^2+pulsationPID^2)/pulsationPID * sqrt(1+Kd^2*pulsationPID^2)/sqrt(1+N^2*Kd^2*pulsationPID^2))
Kp = 0.1350
Plot the new open-loop transfer function with the PI controller.
Gpid = @(w) Kp*((1+w*Ki*1i)/(Ki*w*1i)*(1+Kd*w*1i)/(1+N*Kd*w*1i))*(C*(1i*w*eye(size(A))-A)^-1*B + D); figure; plotBodeTransferFunction(G, maxFrequency); plotBodeTransferFunction(Gpid, maxFrequency); [gainMarginPID,phaseCrossoverPulsationPID,phaseMarginPID,gainCrossoverPulsationPID] = getStabilityCharacteristics(Gpid); plotPhaseMargin(phaseMarginPID,gainCrossoverPulsationPID, maxFrequency); subplot(2,1,1); legend("Plant","PID * Plant");

num = Kp*[Ki*Kd Ki+Kd 1];
den = [Ki*N*Kd Ki 0];
designDCMotorPIDControlPlotRPM("PID")
The PID controller significantly improves the response time compared to the PI controller.
See Also
DC Motor | Model Linearizer (Simulink Control Design) | PID Tuner (Control System Toolbox)





