Tuning a PID controller to desired Overshoot, settling time and rise time

277 ビュー (過去 30 日間)
Muhammad
Muhammad 2022 年 12 月 24 日
コメント済み: Sam Chak 2025 年 6 月 19 日 12:15
The uncompensated plant transfer function in this case is: as shown in the simulink model below:
I want to tune the PID so that the Rise time becomes 0.561 s, settling time becomes 2.6 s and overshoot narrows to 8.83%. However the PID tuner app is very inconvenient in this regard as it only varies the response time and transient behaviour, it is impossible to achieve the desired settling time and overshoot with such a PID tuner.

採用された回答

Sam Chak
Sam Chak 2024 年 1 月 14 日
I'm revisiting a control problem we encountered a year ago. Previously, we utilized the systune() method to establish PIDF gains, but the transient response exhibited significant oscillations, and the derivative term appeared unusual with an unexpectedly large time constant Tf. This time, I've discovered that a set of classical PID gains can fulfill the requirements: settling time (ts) less than 2.6, overshoot (os) of 8.83%, and a rise time (tr) of 0.561.
%% Original Plant
Gp = tf(20, [1 4.5 64]);
%% Target Reference
Gref= tf(64.9193300346851, [1, 7.93016824066555, 31.8718356679018, 64.9193300346851]);
%% Classical PID
kp = -0.733860787658412;
ki = 6.597481064703570;
kd = 0.100288660665148;
Gc = pid(kp, ki, kd);
%% Closed-loop system
Gcl = feedback(Gc*Gp, 1)
Gcl = 2.006 s^2 - 14.68 s + 131.9 --------------------------------- s^3 + 6.506 s^2 + 49.32 s + 131.9 Continuous-time transfer function.
Scl = stepinfo(Gcl)
Scl = struct with fields:
RiseTime: 0.5610 TransientTime: 2.0757 SettlingTime: 2.0757 SettlingMin: 0.9003 SettlingMax: 1.0883 Overshoot: 8.8301 Undershoot: 0 Peak: 1.0883 PeakTime: 0.9200
stepplot(Gref), hold on
stepplot(Gcl), grid on
stepplot(Gp), hold off
legend('Target System', 'PID Controller', 'Original Plant', 'location', 'east')
  2 件のコメント
Emmanouil Tzorakoleftherakis
Emmanouil Tzorakoleftherakis 2024 年 6 月 17 日
For completeness, can you maybe share how you reached to those pid gains so that the accepted answer is complete?
Thanks
Sam Chak
Sam Chak 2025 年 6 月 19 日 12:15
Thank you for accepting my answer on behalf of the OP. The PID gains were obtained by solving the optimization problem using fmincon(). After revisiting this problem a year later, I adjusted the weights of the cost function and found a solution that yields slightly improved step performance.
For linear 2nd-order systems, achieving the desired settling time does not satisfy the rise time requirement. Thus, the rise time requirement takes precedence over the settling time. In other words, satisfying the rise time will satisfy the settling time.
For some unknown reason, systune() yields a less satisfactory solution, characterized by an oscillatory transient response, despite the TuningGoal.StepTracking being properly specified using the tau method, as demonstrated by @Paul. It is believed that systune() may be tuning the PID gains to meet internal objectives that are not known to users, aiming to achieve a balance between performance and robustness, similar to the behavior of pidtune().
%% Target Reference
zeta= 0.611315066227871; % desired damping ratio that yields target 8.83% overshoot
wn1 = 2.29352925249462; % natural frequency that yields target 2.6 s settling time
Gt1 = tf(wn1^2, [1, 2*zeta*wn1, wn1^2])
Gt1 = 5.26 -------------------- s^2 + 2.804 s + 5.26 Continuous-time transfer function.
wn2 = 3.35700150674195; % natural frequency that yields target 0.561 s rise time
Gt2 = tf(wn2^2, [1, 2*zeta*wn2, wn2^2]);
%% Find optimal PID gains using fmincon
[K, fval] = fmincon(@costfcn, [-0.7 6.6 0.1], [], [])
Warning: Simulation did not reach steady state. Please specify YFINAL if this system is stable and eventually settles.
Warning: Simulation did not reach steady state. Please specify YFINAL if this system is stable and eventually settles.
Warning: Simulation did not reach steady state. Please specify YFINAL if this system is stable and eventually settles.
Warning: Simulation did not reach steady state. Please specify YFINAL if this system is stable and eventually settles.
Warning: Simulation did not reach steady state. Please specify YFINAL if this system is stable and eventually settles.
Warning: Simulation did not reach steady state. Please specify YFINAL if this system is stable and eventually settles.
Warning: Simulation did not reach steady state. Please specify YFINAL if this system is stable and eventually settles.
Local minimum possible. Constraints satisfied. fmincon stopped because the size of the current step is less than the value of the step size tolerance and constraints are satisfied to within the value of the constraint tolerance.
K = 1×3
-0.4161 8.8316 0.1307
<mw-icon class=""></mw-icon>
<mw-icon class=""></mw-icon>
fval = 4.8215e-13
%% Original Plant
Gp = tf(20, [1 4.5 64])
Gp = 20 ---------------- s^2 + 4.5 s + 64 Continuous-time transfer function.
%% Classical PID
Kp = K(1);
Ki = K(2);
Kd = K(3);
Gc = pid(Kp, Ki, Kd)
Gc = 1 Kp + Ki * --- + Kd * s s with Kp = -0.416, Ki = 8.83, Kd = 0.131 Continuous-time PID controller in parallel form.
%% Closed-loop system
Gcl = feedback(Gc*Gp, 1)
Gcl = 2.614 s^2 - 8.322 s + 176.6 --------------------------------- s^3 + 7.114 s^2 + 55.68 s + 176.6 Continuous-time transfer function.
%% Plot results
hold on
stepplot(Gt1)
stepplot(Gt2)
stepplot(Gp)
stepplot(Gcl)
hold off
grid on
legend('Target Settling Time', 'Target Rise Time', 'Original Plant', 'PID Controller', 'location', 'east')
%% stepInfoTable
S1 = stepinfo(Gt1);
S2 = stepinfo(Gt2);
S3 = stepinfo(Gp);
S4 = stepinfo(Gcl);
stepInfoTable = struct2table([S1, S2, S3, S4]);
stepInfoTable = removevars(stepInfoTable, {'TransientTime', 'SettlingMin', 'SettlingMax', 'Undershoot', 'Peak', 'PeakTime'});
stepInfoTable.Properties.RowNames = {'Gt1', 'Gt2', 'Gp', 'Gcl'};
disp(stepInfoTable);
RiseTime SettlingTime Overshoot ________ ____________ _________ Gt1 0.82113 2.6 8.83 Gt2 0.561 1.7763 8.83 Gp 0.16265 1.7235 39.822 Gcl 0.561 1.9266 8.83
%% Cost function
function J = costfcn(param)
Gp = tf(20, [1 4.5 64]);
kp = param(1);
ki = param(2);
kd = param(3);
Gc = pid(kp, ki, kd);
Gcl = feedback(Gc*Gp, 1);
S = stepinfo(Gcl);
tr = S.RiseTime;
os = S.Overshoot;
Tr = 0.561; % desired Rise time
Os = 8.83; % desired Overshoot
J = 100*(tr - Tr)^2 + 50*(os - Os)^2;
end

サインインしてコメントする。

その他の回答 (3 件)

Sam Chak
Sam Chak 2022 年 12 月 24 日
編集済み: Sam Chak 2022 年 12 月 24 日
This is the Root Locus compensator design approach, first attempt.
s = tf('s');
Gp = 20/(s^2 + 4.5*s + 64)
Gp = 20 ---------------- s^2 + 4.5 s + 64 Continuous-time transfer function.
controlSystemDesigner('rlocus', Gp)
The app will show root locus of .
Fig. 1: Right-click the white area and add a new design requirement.
Fig. 2: Select Percent overshoot and insert the design value.
Fig. 3: An exclusion region is indicated by the yellow shaded area, separated from the white area by the thick black lines.
Fig. 4: Add a second design requirement, select Settling time and insert the design value.
Fig. 5: A second exclusion region overlaps with the first exclusion region. A new thick black line can also be seen.
Fig. 6: Right-click the white area, click on Edit compensator, and then add an Integrator, because the Plant is a Type-0 system.
Fig. 7: Right-click the white area, click on Edit compensator, and then add a Real Pole, placing it relatively far away from the Plant's poles
Fig. 8: Right-click the white area, click on Edit compensator, and then add the Complex Zeros to cancel out the Plant's stable Complex poles. Natural frequency , and Damping ratio .
Note: This doesn't work if the Plant is unstable.
Fig. 9: The "magenta dot markers" can be seen. The Plant's stable poles are cancelled out by the Compensator's zeros. Next, the design task is to drag one of the magenta markers (on the real axis) along the root locus until a response plot stays outside of the associated exclusion regions.
Fig. 10: The "magenta dot markers" are dragged to the breakaway point (My preference).
Fig. 11: This can also be directly adjusted through entering a design value to Compensator gain.
Fig. 12: Check the Step response if the performance is satisfactory.
Fig. 13: If satisfactory, then export the designed Compensator to Workspace. With the design values, they can be entered in the Transfer function block or zpk block in Simulink.
C = zpk(1.8*(s^2 + 4.5*s + 64)/(s*(s + 12)))
C = 1.8 (s^2 + 4.5s + 64) --------------------- s (s+12) Continuous-time zero/pole/gain model.
Gcl = tf(feedback(C*Gp, 1))
Gcl = 36 s^2 + 162 s + 2304 --------------------------------------- s^4 + 16.5 s^3 + 154 s^2 + 930 s + 2304 Continuous-time transfer function.
% Can check in MATLAB whether the design requirements are satisfied.
S = stepinfo(Gcl)
S = struct with fields:
RiseTime: 0.5599 TransientTime: 0.9725 SettlingTime: 0.9725 SettlingMin: 0.9055 SettlingMax: 1.0000 Overshoot: 0 Undershoot: 0 Peak: 1.0000 PeakTime: 2.1337
If satisfactory, find the equivalent PID gains via algebraic calculations.
% This step is unnecessary, because the Compensator works just as good!
kp = -0.125;
ki = 9.6;
kd = 77/480;
Tf = 1/12;
Cpid = pid(kp, ki, kd, Tf)
Gpid = 1 s Kp + Ki * --- + Kd * -------- s Tf*s+1 with Kp = -0.125, Ki = 9.6, Kd = 0.16, Tf = 0.0833 Continuous-time PIDF controller in parallel form.
% Proof
zpk(Cpid)
ans = 1.8 (s^2 + 4.5s + 64) --------------------- s (s+12) Continuous-time zero/pole/gain model.
  5 件のコメント
Paul
Paul 2022 年 12 月 27 日
Hi Sam,
I haven't been looking at this problem too closely, still wasn't able to get systune to give me what I wanted, but I was getting closer. Anyway, there are several ways to insert an Analysis Point into a model. See the link from the doc page you linked for some examples, maybe other doc pages as well. Here's one way, using connect
G = tf(20,[1 4.5 64],'InputName','u','OutputName','y');
K = tunablePID('PID','PID');
K.InputName = 'e';
K.OutputName = 'u';
% Create the closed loop system, include an analysis point at the error
% signal
S = sumblk('e = r - y');
CL0 = connect(G,K,S,'r','y','e')
CL0 = Generalized continuous-time state-space model with 1 outputs, 1 inputs, 3 states, and the following blocks: AnalysisPoints_: Analysis point, 1 channels, 1 occurrences. PID: Tunable PID controller, 1 occurrences. Type "ss(CL0)" to see the current value, "get(CL0)" to see all properties, and "CL0.Blocks" to interact with the blocks.
Then, in systune, the "location" input would 'e'
Sam Chak
Sam Chak 2022 年 12 月 28 日
Thank you, @Paul. Will look into it.

サインインしてコメントする。


Sulaymon Eshkabilov
Sulaymon Eshkabilov 2022 年 12 月 24 日
Simply double-click on PID block and its parameters window opens. Click on "Tune" button as shown in the attached screen shot - Step 1 - PID_tune_step1.jpg.
Then follow step 2 as shown in the attached file: PID_tune_step2.jpg
Alternative way is using pidtune() in MATLAB.
Good luck

Paul
Paul 2022 年 12 月 24 日
The CST offers some tools to do this. Start from this doc page. Or from this doc page if you want to use Simulink.
Here is an example of the command line workflow. The result I got is not that good, so you'll have to make it work better to get the result you want
Define the plant model
G = tf(20,[1 4.5 64],'InputName','u','OutputName','y');
Define a tunable PID compensator
K = tunablePID('PID','PID');
K.InputName = 'e';
K.OutputName = 'u';
Create the closed loop system
S = sumblk('e = r - y');
CL0 = connect(G,K,S,'r','y');
Define a second order model response that meets the requirements for rise time, settling time, and overshoot.
Rtrack = TuningGoal.StepTracking('r','y',.30,8.8);
stepinfo(Rtrack.ReferenceModel)
ans = struct with fields:
RiseTime: 0.5654 TransientTime: 1.7893 SettlingTime: 1.7893 SettlingMin: 0.9077 SettlingMax: 1.0880 Overshoot: 8.7988 Undershoot: 0 Peak: 1.0880 PeakTime: 1.1967
Use systune to design the PID gains
CL = systune(CL0,Rtrack);
Final: Soft = 3.09, Hard = -Inf, Iterations = 44
The PID controller is:
showTunable(CL)
PID = 1 s Kp + Ki * --- + Kd * -------- s Tf*s+1 with Kp = -0.101, Ki = 6.45, Kd = -23.9, Tf = 1.37e+04 Name: PID Continuous-time PIDF controller in parallel form.
Those negative gains look peculiar!
The closed-loop step response is
stepplot(CL)
stepinfo(CL)
ans = struct with fields:
RiseTime: 0.4233 TransientTime: 2.0735 SettlingTime: 2.0735 SettlingMin: 0.8039 SettlingMax: 1.0237 Overshoot: 2.3675 Undershoot: 0.0210 Peak: 1.0237 PeakTime: 1.5024
Presumably there are other Tuning Goals that can be applied to get the desired response.
  8 件のコメント
Paul
Paul 2024 年 1 月 15 日
IIRC, the approxiation tr ~ 1.8/wn applies for "intermediate" values of zeta. In this problem, the specified overshoot was 8%, which implies a zeta of around 0.62 (which sounds like it's intermediate), which happens to correspond very closes to wn = 1.8/tr.
Here's the plot (assuming wn = 5, the plot should be agnostic to the value of wn)
zeta = 0.1:.1:0.9; wn = 5;
for ii = 1:numel(zeta)
S = stepinfo(tf(wn^2,[1 2*zeta(ii)*wn wn^2]));
tr(ii) = S.RiseTime;
Mp(ii) = S.Peak - 1;
end
figure
plot(zeta,tr*wn,zeta,Mp)
xlabel('zeta')
yline([0.08 1.8])
xline(0.62)
legend('10-90 Rise Time*wn','%OverShoot/100','Location','NorthWest')
Senol Gulgonul
Senol Gulgonul 2025 年 6 月 13 日 18:29
編集済み: Senol Gulgonul 2025 年 6 月 13 日 18:29
Recently I published a preprint on PID tuning for settling time and overshoot requirements by using IAE optimization at https://arxiv.org/abs/2505.17268
By using my algorithm I reached zero overshoot with Ts=2.26s
Method Kp Ki Kd Ts PO (%) IAE
SOSTIAE 0.0000 4.9777 0.1278 2.2667 0.0000 0.6429
you can set your target Ts and PO

サインインしてコメントする。

製品


リリース

R2022a

Community Treasure Hunt

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

Start Hunting!

Translated by