# Why the build-in step function and the user defined m-file generate different results

6 views (last 30 days)
Yuan-Pao Hsu on 21 Jan 2016
I am simulating a system controlled by a PID controller. The system is very simple:
I*x_ddot + d*x_dot + m*g*L*x = u.
I suppose the step response should be the same as the code using Matlab build-in functions, if the user uses the ode45 running the system combined with the PID controller by setting reference to 1. But they generate different results!
The user's code is:
function test2
clear all
clc
close all
global error ref
error = 0;
ref = 1;
t = [0,5];
x0 = [0; 0];
dtspan = t;
[t, x] = ode45(@ODESolver, dtspan, x0);
plot(t, x(:,1), 'r', 'LineWidth', 2);
title('Regulation Problem','Interpreter','LaTex');
xlabel('time (sec)');
ylabel('$\theta(t)$', 'Interpreter','LaTex');
grid on
function dx = ODESolver(t, x)
global error ref; % for PID controller
persistent t_prv
if isempty(t_prv)
t_prv = 0;
end
dx = zeros(2,1);
%Parameters:
m = 0.5; % mass (Kg)
d = 0.0023e-6; % viscous friction coefficient
L = 1; % arm length (m)
I = 1/3*m*L^2; % inertia seen at the rotation axis. (Kg.m^2)
g = 9.81; % acceleration due to gravity m/s^2
% PID tuning
Kp = 5;
Kd = 1.9;
Ki =0.20;
% u: joint torque
u = Kp*(ref - x(1)) + Kd*(-x(2)) + Ki*error;
error = error + (ref - x(1))*(t-t_prv);
dx(1) = x(2);
dx(2) = 1/I*(u - d*x(2) - m*g*L*(x(1)));
t_prv = t;
The outcome is as the following image:
The code using Matlab build-in functions for step response is as the following:
clear all
clc
close all
% Model Parameters
m = 0.5; % mass (Kg)
d = 0.0023e-6; % viscous friction coefficient
L = 1; % arm length (m)
I = 1/3*m*L^2; % inertia seen at the rotation axis. (Kg.m^2)
g = 9.81; % acceleration due to gravity m/s^2
s = tf('s');
P_pend = 1/(I*s^2 + d*s + m*g*L);
% PID tuning
Kp = 5;
Kd = 1.9;
Ki = 0.2;
C = pid(Kp,Ki,Kd)
T = feedback(P_pend*C,1)
t=0:0.1:5;
step(T,t)
%axis([0, 2.5, -0.2, 0.2]);
title('Response under PID Control: Kp = 5, Ki = 1.9, Kd = 0.2');
For this code its outcome is as the following image:

Arkadiy Turevskiy on 26 Jan 2016
The difference is due to how the derivative term is handled in the simulation. When you use ode45 (the first approach in the question) you compute the pure derivative of the signal. In general, this is not a recommended thing to do: in real life signals are noisy, and taking a derivative of a noisy signal amplifies the noise at high frequencies. That's why it is recommended instead of calculating a pure derivative using a derivative with a lowpass filter. Derivative with a low pass filter can be calculated without taking a derivative of a signal.
The second approach with pid and feedback does not result in taking a pure derivative of a signal during simulation - you first compute closed-loop transfer function using "feedback" and when you do that, the resulting close-loop transfer function does not have a pure derivative term anymore. So when you simulate it with 'step' command, you get a different response than your first method.
I guess your next question would be - which of the 2 answers is right. I would argue it is the second one, because in real life you would not want to implement a PID with pure derivative.
Hope this helps.