Main Content

Robust Tuning of DC Motor Controller

This example shows how to robustly tune a PID controller for a DC motor with imperfectly known parameters.

DC Motor Modeling

An uncertain model of the DC motor is derived in the "Robustness of Servo Controller for DC Motor" example. The transfer function from applied voltage to angular velocity is given by

$$P(s) = {K_m \over J L s^2 + (J R + L K_f) s + K_m K_b + R K_f}$$

where the resistance $R$, the inductance $L$, the EMF constant $K_b$, armature constant $K_m$, viscous friction $K_f$, and inertial load $J$ are physical parameters of the motor. These parameters are not perfectly known and are subject to variation, so we model them as uncertain values with a specified range or percent uncertainty.

R = ureal('R',2,'Percentage',40);
L = ureal('L',0.5,'Percentage',40);
K = ureal('K',0.015,'Range',[0.012 0.019]);
Km = K; Kb = K;
Kf = ureal('Kf',0.2,'Percentage',50);
J = ureal('J',0.02,'Percentage',20);

P = tf(Km,[J*L J*R+Kf*L Km*Kb+Kf*R]);
P.InputName = 'Voltage';
P.OutputName = 'Speed';

Time and frequency response functions like step or bode automatically sample the uncertain parameters within their range. This is helpful to gauge the impact of uncertainty. For example, plot the step response of the uncertain plant P and note the large variation in plant DC gain.

step(P,getNominal(P),3)
legend('Sampled uncertainty','Nominal')
ans = 

  Legend (Sampled uncertainty, Nominal) with properties:

         String: {'Sampled uncertainty'  'Nominal'}
       Location: 'northeast'
    Orientation: 'vertical'
       FontSize: 9
       Position: [0.5709 0.7695 0.3150 0.0789]
          Units: 'normalized'

  Use GET to show all properties

Robust PID Tuning

To robustly tune a PID controller for this DC motor, create a tunable PID block C and construct a closed-loop model CL0 of the feedback loop in Figure 1. Add an analysis point dLoad at the plant output to measure the sensitivity to load disturbance.

C = tunablePID('C','pid');
AP = AnalysisPoint('dLoad');
CL0 = feedback(AP*P*C,1);
CL0.InputName = 'SpeedRef';
CL0.OutputName = 'Speed';

Figure 1: PID control of DC motor

There are many ways to specify the desired performance. Here we focus on sensitivity to load disturbance, roll-off, and closed-loop dynamics.

R1 = TuningGoal.Sensitivity('dLoad',tf([1.25 0],[1 2]));
R2 = TuningGoal.MaxLoopGain('dLoad',10,1);
R3 = TuningGoal.Poles('dLoad',0.1,0.7,25);

The first goal R1 specifies the desired profile for the sensitivity function. Sensitivity should be low at low frequency for good disturbance rejection. The second goal R2 imposes -20 dB/decade roll-off past 10 rad/s. The third goal R3 specifies the minimum decay, minimum damping, and maximum natural frequency for the closed-loop poles.

viewGoal(R1)

viewGoal(R2)

viewGoal(R3)

You can now use systune to robustly tune the PID gains, that is, to try and meet the design objectives for all possible values of the uncertain DC motor parameters. Because local minima may exist, perform three separate tunings from three different sets of initial gain values.

opt = systuneOptions('RandomStart',2);
rng(0), [CL,fSoft] = systune(CL0,[R1 R2 R3],opt);
Nominal tuning:
Design 1: Soft = 0.838, Hard = -Inf
Design 2: Soft = 0.838, Hard = -Inf
Design 3: Soft = 0.914, Hard = -Inf

Robust tuning of Design 1:
Soft: [0.838,1.98], Hard: [-Inf,-Inf], Iterations = 65
Soft: [0.875,1.76], Hard: [-Inf,-Inf], Iterations = 30
Soft: [0.935,2.77], Hard: [-Inf,-Inf], Iterations = 27
Soft: [1.35,1.35], Hard: [-Inf,-Inf], Iterations = 35
Final: Soft = 1.35, Hard = -Inf, Iterations = 157

Robust tuning of Design 2:
Soft: [0.838,2.01], Hard: [-Inf,-Inf], Iterations = 40
Soft: [0.875,1.76], Hard: [-Inf,-Inf], Iterations = 29
Soft: [0.935,2.77], Hard: [-Inf,-Inf], Iterations = 27
Soft: [1.35,1.35], Hard: [-Inf,-Inf], Iterations = 35
Final: Soft = 1.35, Hard = -Inf, Iterations = 131

Robust tuning of Design 3:
Soft: [0.914,2.37], Hard: [-Inf,-Inf], Iterations = 57
Soft: [0.875,1.77], Hard: [-Inf,-Inf], Iterations = 78
Soft: [1.02,2.98], Hard: [-Inf,-Inf], Iterations = 34
Soft: [1.34,1.36], Hard: [-Inf,-Inf], Iterations = 32
Soft: [1.35,1.35], Hard: [-Inf,-Inf], Iterations = 20
Final: Soft = 1.35, Hard = -Inf, Iterations = 221

The final value is close to 1 so the tuning goals are nearly achieved throughout the uncertainty range. The tuned PID controller is

showTunable(CL)
C =
 
             1            s    
  Kp + Ki * --- + Kd * --------
             s          Tf*s+1 

  with Kp = 33.8, Ki = 83.2, Kd = 2.34, Tf = 0.028
 
Name: C
Continuous-time PIDF controller in parallel form.

Next check how this PID rejects a step load disturbance for 30 randomly selected values of the uncertain parameters.

S = getSensitivity(CL,'dLoad');
clf, step(usample(S,30),getNominal(S),3)
title('Load disturbance rejection')
legend('Sampled uncertainty','Nominal')
ans = 

  Legend (Sampled uncertainty, Nominal) with properties:

         String: {'Sampled uncertainty'  'Nominal'}
       Location: 'northeast'
    Orientation: 'vertical'
       FontSize: 9
       Position: [0.5709 0.7695 0.3150 0.0789]
          Units: 'normalized'

  Use GET to show all properties

The rejection performance remains uniform despite large plant variations. You can also verify that the sensitivity function robustly stays within the prescribed bound.

viewGoal(R1,CL)

Robust tuning with systune is easy. Just include plant uncertainty in the tunable closed-loop model using ureal objects, and the software automatically tries to achieve the tuning goals for the entire uncertainty range.

Related Examples

More About