1
\$\begingroup\$

Please also read Update

I created a PID simulation in Simulink:

enter image description here

where the Step block is set with parameters:

Set time = 0
Initial value = 0 
Final value = 100 
Sample time = 0.01

And I coded the above PID in MATLAB:

classdef PID < handle
    properties
        Kp = 0
        Ki = 0
        Kd = 0
        SetPoint = 1
        Dt = 0.01
    end
    
    properties (Access = private)
        IState = 0
        PreErr = 0
    end
    
    methods
        function obj = PID(Kp, Ki, Kd, SetPoint, Dt)
            if nargin == 0
                return;
            end
            obj.Kp = Kp;
            obj.Ki = Ki;
            obj.Kd = Kd;
            obj.SetPoint = SetPoint;
            obj.Dt = Dt;
        end
        
        function output = update(obj, measuredValue, t)
            err = obj.SetPoint - measuredValue;
            P = obj.getP(err);
            I = obj.getI(err);
            filter = lowPass(obj,t);
            D = obj.getD(err*filter);
            output = P + I + D;
        end
        
        function val = getP(obj, err)
            val = obj.Kp*err;
        end
        
        function val = getI(obj, err)
            obj.IState = obj.IState + err * obj.Dt;
            val = obj.Ki * obj.IState;
        end
        
        function val = getD(obj, err)
            val = obj.Kd * (err - obj.PreErr) / obj.Dt;            
            obj.PreErr = err;
        end
        
        function val = lowPass(obj,t)
            N = 1;
            val = 1-exp(-N*t);
        end
    end
end

The transfer function same as the one in the Simulink:

function r = getResponse(t)
r = 0.2 - 0.2*exp(-5*t);
end

And the code for the programmatic simulation:

sr = 1e2; % sampling rate 100Hz
st = 10; % sampling time 10s
ss = st*sr+1; % sample size
t = 0:1/sr:st; % time

input = ones(1,ss)*100;
output = zeros(1,ss);
measured = 0;

pid = PID(0,1,0,input(1),t(2)-t(1)); %Kp=0,Ki=1,Kd=0
for i = 2:ss
    rPID(i) = pid.update(measured, t(i));
    output(i) = rPID(i)*getResponse(t(i));    
    measured = output(i);
end
figure;
hold on;
plot(t,output)
plot(t,input)
plot(t,rPID)
legend('Output','Input','PID')

I have confirmed that when Kp=1; Ki=0; Kd=0;, both simulations yield the exact same result. But when I set Kp=0; Ki=1; Kd=0;, the results are different.

Simulink result:

enter image description here

Programmatic simulation result:

enter image description here

As you can see, not only the final values are completely different, but the difference starts from the very beginning at the first time stamp 0.01s. I can't think of how Simulink does the calculation and where my mistake is. (I know I must have some mistake in low pass filter -> the derivative term, but they are isolated from this example.)

The last time I did control system was years ago in undergraduate, so I must have made some very fundamental mistakes.


Update

I recalculated the inverse Laplace transformation. It turns out my previous calculation is incorrect. The correct getResponse function is:

function r = getResponse(t)
r = 1 - exp(-5*t);
end

After this correction, the result looks much similar:

enter image description here

However, there is still some minor differences. Here's a figure showing the difference (programmatic simulation result - Simulink):

enter image description here

\$\endgroup\$
8
  • \$\begingroup\$ did you try \$\frac {10s}{s+10}\$ for the differentiator path? \$\endgroup\$
    – Chu
    Apr 3, 2019 at 22:43
  • \$\begingroup\$ @Chu the differential path is completely off for some reason. The values go sky rock after several seconds kept increasing to infinity. But I set kd = 0 so these minor error can't be attributed to anything else but the integral path. \$\endgroup\$
    – Anthony
    Apr 3, 2019 at 23:01
  • \$\begingroup\$ I wouldn't expect them to be identical, because you certainly haven't modelled your actual system with zero error. Looking at the graph, the difference seems to be small enough that it shouldn't matter. \$\endgroup\$
    – Hearth
    Apr 3, 2019 at 23:47
  • \$\begingroup\$ @Hearth the plant is simply a random low pass filter not near any representation of the actual system. I'm only trying to refresh my memory on PID (mostly re-study). \$\endgroup\$
    – Anthony
    Apr 3, 2019 at 23:52
  • \$\begingroup\$ Oh, I see; I had thought you were using a physical system. Note to self, read the entire question before commenting next time. \$\endgroup\$
    – Hearth
    Apr 3, 2019 at 23:57

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Browse other questions tagged or ask your own question.