Main Content

Design PID Control for DC Motor Using Classical Control Theory

Since R2025a

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:

G(s)=C(sI-A)-1B+D

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)

Figure contains 2 axes objects. Axes object 1 with title Bode Diagram, xlabel Frequency (Hz), ylabel Magnitude (dB) contains an object of type line. Axes object 2 with xlabel Frequency (Hz), ylabel Phase (deg) contains an object of type line.

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 -π (-180o).

[gainMargindB,phaseCrossoverPulsation,phaseMargin,gainCrossoverPulsation] = getStabilityCharacteristics(G);

Plot the Bode diagram with stability margins.

figure; plotBodeTransferFunction(G,maxFrequency)
plotPhaseMargin(phaseMargin,gainCrossoverPulsation, maxFrequency);

Figure contains 2 axes objects. Axes object 1 with title Bode Diagram, xlabel Frequency (Hz), ylabel Magnitude (dB) contains 3 objects of type line. Axes object 2 with xlabel Frequency (Hz), ylabel Phase (deg) contains 5 objects of type line, text. One or more of the lines displays its values using only markers

Plot the close-loop step response.

num = [1];
den = [1];
designDCMotorPIDControlPlotRPM("P");

Figure contains an axes object. The axes object with title DC Motor Angular Speed, ylabel Angular speed (RPM) contains 2 objects of type line. These objects represent Measured, Reference.

The small phase margin of the open-loop indicates the close-loop system is very close to instability. Consequently, the step response oscillates until the response settles down. Furthermore, there is a small steady-state error that indicates 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 24o, 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");

Figure contains 2 axes objects. Axes object 1 with title Bode Diagram, xlabel Frequency (Hz), ylabel Magnitude (dB) contains 4 objects of type line. These objects represent Plant, Kp * Plant. Axes object 2 with xlabel Frequency (Hz), ylabel Phase (deg) contains 6 objects of type line, text. One or more of the lines displays its values using only markers

Verify that the close-loop system is now stable by plotting the output voltage of the converter.

num = Kp;
den = 1;
designDCMotorPIDControlPlotRPM("P")

Figure contains an axes object. The axes object with title DC Motor Angular Speed, ylabel Angular speed (RPM) contains 2 objects of type line. These objects represent Measured, Reference.

Although the oscilations have been significantly reduced, the plot shows now a bigger a steady-state error due to the lower gain. If you calculate and take a look at 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 a 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:

C(s)=KP1+KIsKIs

where:

  • KP is the proportional controller gain

  • KI is the integral control constant

  • s is the Fourier transform variable

To calculate the gains analytically, use the following relation of the control gain and phase. From the Bode plot, decide the control gain and phase you need, and then use this expression to calculate the gains.

KP1+KIωjKIωj=ACejϕC

where:

  • AC is the amplitude of the control

  • ϕC is the phase of the control

  • ωj is the variable s expressed in the time domain

Firstly, decide the value of the crossover frequency and the phase margin. The idea is that a reduction in speed will improve the steady-state accuracy. Reduce around 10-20% 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 will have an angle of -6o. Match the phases of both sides of the previous equation to obtain the value of KI.

(1+KIωjKIωj)=ϕC; (1+KIωj)-(KIωj)=ϕC;

If (KIωj)=90, then KIω=tan(-90+ϕC)

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 close-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");

Figure contains 2 axes objects. Axes object 1 with title Bode Diagram, xlabel Frequency (Hz), ylabel Magnitude (dB) contains 4 objects of type line. These objects represent Plant, PI * Plant. Axes object 2 with xlabel Frequency (Hz), ylabel Phase (deg) contains 6 objects of type line, text. One or more of the lines displays its values using only markers

num = [Kp*Ki Kp];
den = [Ki 0];
designDCMotorPIDControlPlotRPM("PI")

Figure contains an axes object. The axes object with title DC Motor Angular Speed, ylabel Angular speed (RPM) contains 2 objects of type line. These objects represent Measured, Reference.

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 a 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:

C(s)=KP1+KIsKIs1+KDs1+NKDs

where:

  • KP is the proportional controller gain

  • KI is the integral control constant

  • KD is the derivative control constant

  • s is the Fourier transform variable

  • N 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. Once you have decided the phase margin, you can decide the crossover frequency, the angle of the integral component, and the filtering factor of the derivative component.

KP1+KIωjKIωj1+KDωj1+NKDωj=ACejϕC

where:

  • AC is the amplitude of the control

  • ϕC is the phase of the control

  • ωj is the variable s 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 we can select a frequency greater than the integral and proportional control. Choose a crossover frequency superior to the one of the plant, and the phase margin at least like the integral control.

crossoverFreqPID = 100; % gainCrossoverPulsation; % Hz
phaseMarginPID = 70; % deg

The control gain will be 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 be the difference between the plant phase and the angle given by the phase margin (-180+ϕM).

pulsationPID = crossoverFreqPID*2*pi; % rad/s
angleGpulsationPID = angle(G(pulsationPID))/pi*180; % deg
controlPhase = -180 + phaseMarginPID - angleGpulsationPID; % deg

Decide the angle of the integral component and calculate the integral control constant KI like you did for the PI control.

integralPhase = -10; %deg
Ki = tand(integralPhase+90)/pulsationPID
Ki = 
0.0090

Having set the phase margin for the PID and the integral action phase, calculate the derivative action phase, ϕPD.

derivativePhase = phaseMarginPID - 180 - angleGpulsationPID - integralPhase %deg
derivativePhase = 
77.3773

Once you have designed the integral action, choose a value of N. Bear in mind that N limits the maximum value of ϕPD, and high values make certain values impossible. If this is the case, reduce the integral phase value to enable higher derivative action phases. Choose a value of 0.01 for N and calculate the value KD:

N = 0.01;

ϕPD=atan(KDω)-atan(NKDω)

Using the trigonometrical identity below, obtain a second order equation, from which you can get two solutions for KD:

arctan(a)-arctan(b)=arctan(a-b1+ab)

KD=(1-N)±(N-1)2-4Ntan2ϕPD2ωNtanϕPD

Kd = ((1-N)+sqrt((N-1)^2 - 4*N*(tand(derivativePhase))^2))/(2*pulsationPID*N*tand(derivativePhase))
Kd = 
0.0253

Lastly, calculate the proportional gain using the amplitude equation derived from the control equation:

AC=KP(I2+ω2ω1+KD2ω21+N2KD2ω2)

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");

Figure contains 2 axes objects. Axes object 1 with title Bode Diagram, xlabel Frequency (Hz), ylabel Magnitude (dB) contains 4 objects of type line. These objects represent Plant, PID * Plant. Axes object 2 with xlabel Frequency (Hz), ylabel Phase (deg) contains 6 objects of type line, text. One or more of the lines displays its values using only markers

num = Kp*[Ki*Kd Ki+Kd 1];
den = [Ki*N*Kd Ki 0];
designDCMotorPIDControlPlotRPM("PID")

Figure contains an axes object. The axes object with title DC Motor Angular Speed, ylabel Angular speed (RPM) contains 2 objects of type line. These objects represent Measured, Reference.

The PID controller significant improves the response time compared to the PI controller.

See Also

| (Simulink Control Design) | (Control System Toolbox)

Topics