PID tuning to meet conditions for settling time and overshoot while a stable system with minimum peak time and zero velocity error.

60 views (last 30 days)
So I am trying to find the gain values for a PI control system that would give me a settling time not exceeding 6 seconds, and an maximum overshoot not going over 5% while ensuring that the peaktime is the lowest it can be, and that the system is stable, and also has zero velocity error.
I have written the following code. Starting with a kp and ki value of 1 each, I get a system that gives desirable overshoot and settling time, but I am wondering if the peaktime can be even lower while still having settling time <= 6 and overshoot <= 5.
I am using the following toolboxes: Control System Toolbox
Questions
  1. Using the rlocus function, I have also shown that the real parts of the poles are negative, so this demonstrates that my system is stable right?
  2. Also am I using Lsim correctly to determine if velocity error is zero? The resultant graph has a gray line showing the time response, and a blue line that is parallel to it. This means zero velocity error right?
  3. What is the best way to fine-tune the gain values kp and ki to minimize peak time while ensuring the above conditions are still met?
I would like to use matlab only and no simulink for this please.
clc
clear all
% plant transfer function
G = tf([1], [0.5 1.5 1])
kp = 1
ki = 1
% PI controller
C = tf([kp ki], [1 0])
% closed loop transfer function
T = feedback(C*G, 1)
rlocus(T)
% Find the poles
poles = pole(T)
% step response
figure;
step(T);
title('Step Response');
grid on;
% Step analysis
info = stepinfo(T)
% Ramp Input
t = 0:0.01:10;
ramp = t;
% System response to ramp
figure;
lsim(T, ramp, t);
title('Ramp Response')
legend
grid on

Accepted Answer

Sam Chak
Sam Chak on 2 Dec 2024 at 12:53
Here is the solution using pidtune(). There is no direct way to input the desired settling time and overshoot percentage; however, you can enter the desired phase margin. This has been a concern for me in MATLAB for many years. Nevertheless, based on the desired overshoot percentage, you can apply the formula from your lecture notes to determine the desired phase margin.
%% The Plant
Gp = tf([1], [0.5 1.5 1])
Gp = 1 ------------------- 0.5 s^2 + 1.5 s + 1 Continuous-time transfer function.
%% Using pidtune
Pm = 68.2; % desired Phase Margin
opt = pidtuneOptions('PhaseMargin', Pm, 'DesignFocus', 'balanced');
[Gc, info] = pidtune(Gp, 'pidf', opt)
Gc = 1 s Kp + Ki * --- + Kd * -------- s Tf*s+1 with Kp = 2.02, Ki = 1.87, Kd = 0.489, Tf = 0.00619 Continuous-time PIDF controller in parallel form.
info = struct with fields:
Stable: 1 CrossoverFrequency: 1.4142 PhaseMargin: 72.6977
%% Closed-loop system
Gcl = feedback(Gc*Gp, 1)
Gcl = 81.01 s^2 + 328.2 s + 302.2 ------------------------------------------------- 0.5 s^4 + 82.31 s^3 + 324.4 s^2 + 489.8 s + 302.2 Continuous-time transfer function.
S = stepinfo(Gcl)
S = struct with fields:
RiseTime: 1.1479 TransientTime: 3.6131 SettlingTime: 3.6131 SettlingMin: 0.9088 SettlingMax: 1.0499 Overshoot: 4.9883 Undershoot: 0 Peak: 1.0499 PeakTime: 2.3938
step(Gcl), grid on, grid minor
xline(S.SettlingTime, '--', sprintf('Settling Time: %.3f s', S.SettlingTime), 'color', '#7F7F7F', 'LabelVerticalAlignment', 'bottom')
yline(1+S.Overshoot/100, '--', sprintf('Overshoot: %.3f %%', S.Overshoot), 'color', '#7F7F7F', 'LabelVerticalAlignment', 'top')

More Answers (2)

Epsilon
Epsilon on 2 Dec 2024 at 5:34
Hi Ashaya,
The answers to your queries are:
  1. Yes, for a linear close looped continuous-time system the negative real parts of all the poles do indeed represent a stable system.
  2. The resultant graph does not show a zero-velocity error as there is a steady state error present (response of the system does not match the ramp input). Tuning the gain parameters can help in achieving a zero steady state error.
  3. To automatically fine tune the value of the gain parameters(kp,ki), use ‘pidtune’. Alternatively, the ‘PID Tuner App’ can also be used. Attaching a code snippet for reference:
% using pidtune function
[C, info] = pidtune(G, 'PI');
kp = C.Kp;
ki = C.Ki;
% Alternatively, opening the PID Tuner App
% pidTuner(G, 'PI');
Documentation link to PID Tuner App and pidtune function:
Hope it helps!
  1 Comment
Ashaya KC
Ashaya KC on 2 Dec 2024 at 5:55
Hi Epsilon,
Thanks for the response but I still have some questions. Using the gain values from the pidtune helped reduce the peak time and also the settling time, but the overshoot increased to 8.0374. I want the % overshoot to be less than or equal to 5%.
It looks like the pidtune found the best gain values to reduce settling time and peak time but at the cost of a greater overshoot, is there a way I can define a maximum overshoot value for the "pidtune"?
Additionally, the ramp plot still has error between the two lines, if I understood you correctly, zero error should make the two lines overlap perfectly right?
% System response to ramp
figure;
lsim(T, ramp, t);
title('Ramp Response')
legend
grid on
Ramp response from above code:

Sign in to comment.


Sam Chak
Sam Chak on 2 Dec 2024 at 11:26
Let's first use the ideal mathematical solution and then compare it to your solution obtained using the pidtune() command. In this context, 'ideal' means that the order of the controller should match the order of the plant. Since your plant is of order 2, the controller should ideally also be of order 2. The practical PID controller fits this requirement.
% Plant
Gp = tf([1], [0.5 1.5 1])
Gp = 1 ------------------- 0.5 s^2 + 1.5 s + 1 Continuous-time transfer function.
% PID controller
kp = 0.561012507894632;
ki = 0.723966578400112;
kd = -0.044798506317072;
Tf = 0.725085073492745;
Gc = pid(kp, ki, kd, Tf)
Gc = 1 s Kp + Ki * --- + Kd * -------- s Tf*s+1 with Kp = 0.561, Ki = 0.724, Kd = -0.0448, Tf = 0.725 Continuous-time PIDF controller in parallel form.
% Closed-loop system
Gcl = feedback(Gc*Gp, 1)
Gcl = 0.4992 s^2 + 1.498 s + 0.9985 ------------------------------------------------- 0.5 s^4 + 2.19 s^3 + 3.568 s^2 + 2.877 s + 0.9985 Continuous-time transfer function.
S = stepinfo(Gcl)
S = struct with fields:
RiseTime: 2.0987 TransientTime: 6.0000 SettlingTime: 6.0000 SettlingMin: 0.9005 SettlingMax: 1.0500 Overshoot: 5.0000 Undershoot: 0 Peak: 1.0500 PeakTime: 4.3409
step(Gcl), grid on, grid minor
xline(S.SettlingTime, '--', sprintf('Settling Time: %.3f s', S.SettlingTime), 'color', '#7F7F7F', 'LabelVerticalAlignment', 'bottom')
yline(1+S.Overshoot/100, '--', sprintf('Overshoot: %.3f %%', S.Overshoot), 'color', '#7F7F7F', 'LabelVerticalAlignment', 'top')

Products


Release

R2024a

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!