matlab simulink convert PID continuous to discrete - matlab

How do I convert a continuous PID (in s form) to discrete form (in z form)? Let's say I have the tuned gain of the PID (in s form) :
Kp=2266.76751174231;
Ki=3461.10112077832;
Kd=360.96017761997;
Now, I would like to apply the same gain to the PID in z form. However I couldn't get the same responses in discrete compared to continuous. Below is the z block diagram:
And this is the responses in z form:
Block diagram in s form:
this is the responses in continuous form:
Any suggestion what's my mistake?
thanks!

I tried running the model in continuous time with the PID parameters that you specified and the default N=100 for the derivative gain filter coefficient. I used ode45 solver with default parameters, but I limited the maximum time step to 0.01. Unfortunately, I found the system to be unstable.
I tuned the gains using a heuristic manual approach (I believe that the values of the gains are not relevant from the perspective of answering your question). I settled on the following set of gains:
Kp = 6
Ki = 12
Kd = 1
The models that I used are shown below. As you can see from the Simulink diagram, I constructed two models. They are (almost) equivalent. However, the first model (the topmost model) uses the standard Simulink PID(s) block and the second one (the lowermost model) uses a custom transfer function block instead of the Simulink PID(s) block. The custom transfer function should produce the output that is equivalent to the Simulink PID(s) block, as they only differ in their implementation. The second model was created to assist in the explanation of the method that I used for the conversion of the models from z-domain to s-domain. I also used it as a "sanity check" to ensure that the implementation of the Simulink PID is not different from the way I thought it was implemented.
The PID parameters for the continuous time simulation.
The parameters of the transfer function block associated with the plant.
The result of the continuous time simulation.
In order to convert the plant model from s-domain to z-domain I used the Tustin transformation. I used the symbolic toolbox in MATLAB to perform the conversion. This is my preferred approach, as it enables for a more general solution in comparison with the in-built toolboxes for control systems. I also constructed the PID function in s-domain and converted it to z-domain using the same approach. The script that does the conversion is shown below. Please note that I used 0.1 as the simulation time step for the discrete time simulation. This value should also be set in the solver configuration in Simulink.
The following variables are important from the perspective of the construction of the Simulink model in z-domain:
NPlantCoeffs - contains the coefficients of the numerator of the transfer function associated with the plant in z-domain. For a reference, the following value was obtained: [45 135 135 45].
DPlantCoeffs- contains the coefficients of the denominator of the transfer function associated with the plant in z-domain. For a reference, the following value was obtained: [406502 -1104494 1035506 -333498].
NPIDFiltCoeffs - contains the coefficients of the numerator of the transfer function associated with the PID in z-domain. For a reference, the following value was obtained: [-349 515 -196].
DPIDFiltCoeffs - contains the coefficients of the denominator of the transfer function associated with the PID in z-domain. For a reference, the following value was obtained: [-15 5 10].
Tval - the value of the time step. For a reference, the following value was used: 0.1.
The script for the definition of the parameters for the discrete-time simulation.
% Initialisation.
clear;
clc;
% Define the symbolic variables of interest.
% T is the time step for discrete simulation.
syms s z T;
% Define the controller parameters.
% The parameters should correspond to the parameters obtained from tuning
% the continuous system.
Kp = 6;
Ki = 12;
Kd = 1;
N = 100;
% Define the plant and the controller in the s-domain.
TFPlant = 0.09/(0.09*s^3 + 0.18*s^2 + s + 1.004);
TFPIDFilt = Kp + Ki/s + Kd*N/(1 + N/s);
% Obtain the numerator and the denominator of the transfer functions in the
% s-domain.
[NPIDCont, DPIDCont] = numden(collect(TFPIDFilt));
NPIDCont = sym2poly(NPIDCont);
DPIDCont = sym2poly(DPIDCont);
% Convert to z-domain using Tustin substitution (referred to as Trapezoidal
% method in Simulink block PID(s)).
TFPlant = collect(subs(TFPlant, s, (2/T)*(z - 1)/(z + 1)));
TFPIDFilt = collect(subs(TFPIDFilt, s, (2/T)*(z - 1)/(z + 1)));
% Define time step for discrete simulation.
Tval = 0.1;
% Perform substitution for the time step T.
TFPlant = subs(TFPlant, T, Tval);
TFPIDFilt = subs(TFPIDFilt, T, Tval);
% Decompose into the numerator and denominator.
[NPlant, DPlant] = numden(TFPlant);
[NPIDFilt, DPIDFilt] = numden(TFPIDFilt);
% Obtain the polynomial coefficients associated with the numerator and
% denominator.
NPlantCoeffs = sym2poly(NPlant);
DPlantCoeffs = sym2poly(DPlant);
NPIDFiltCoeffs = sym2poly(NPIDFilt);
DPIDFiltCoeffs = sym2poly(DPIDFilt);
For the discrete time simulation, it is important to select the fixed time step solver and set the time step to the value that is equivalent to the value that was used for the conversion of the plant model from s-domain to z-domain. As you can see below, I used the z-domain version of the continuous time PID controller block for the discrete time simulation. Given the calculated plant parameters for the discrete-time simulation, the result of the simulation is very close to the result of the simulation of the continuous time system.
Solver configuration for the discrete time simulation.
Models for the discrete time simulation.
Discrete time plant model parameters.
Parametrisation of the Simulink PID(s) block for discrete time simulation.
The result of the discrete time simulation.
To answer your original question, I am not sure where your mistake is exactly. However, I provide several assumptions below:
There is something strange with the PID gains that you obtained for continuous time simulation. The system that was specified in your screenshot is unstable when these gains are used, unless I misread the plant parameters in the screenshot.
I am not sure what process you followed for the conversion of the plant model from s-domain to z-domain. The conversion process that I presented in the answer should provide a valid methodology for the conversion. It is also important to use a fixed time step solver for the discrete time domain simulation. Moreover, it is important to use the time step that is equivalent to the time step used for the conversion of your plant model from s-domain to z-domain.

Related

How to generate pulse signal in Simulink with pulse width input?

I would like to drive a transfer function block with a pulse signal in Simulink. This can for example be done with a Pulse Generator block. The only thing I am missing is an external input where I can specify the pulse width or duty cycle of the signal. Signal parameters can only be entered through the Pulse Generator's Block parameters. Is there a way to go around this?
Simulink model 1
Pulse generator block parameters
Alternatively, I tried to use a Matlab function block inside Simulink with the Matlab function "square", which takes a few constants as well as the current simulation time as inputs. I used the following function:
% Output data value for specific time instant
function DataValue = pulsegen(PulseWidth,Frequency,TimeInput)
PulseDutyCycle = PulseWidth*Frequency*100;
% Generate signal
t = 0:0.0001:60;
y = square(2*pi*Frequency*t,PulseDutyCycle);
y = max(y,0); % Set nonzero elements to zero
DataValue = y(find(t==TimeInput)); % find data value at specific time instance
end
And the following model:
Simulink model 2
But with no luck either. I get the following error message:
Simulink error messages
Which does not makes sense to me. When I test this function stand-alone in Matlab, the function output is just a 1x1 constant value, not an array. Does anyone know a solution to this?

How to solve an ODE equation in Simulink?

I'm studying a report about roll angle estimation. In the article I found the following scheme:
where vx is the longitudinal vehicle velocity, psi_dot is the horizontal yaw rate, lambda_dot is the roll rate and lambda is the roll angle. I need to verify this method on matlab/simulink
Here is my simulation:
I chose random values (reasonable, I hope) for vx and yaw rate, while lambda_dot is similar to the one used in the article. The MATLAB function block contains this code:
function lambda = fcn(vx, yaw_r)
g = 9.81;
lambda0 = -(vx*yaw_r)/g;
tspan = [0 40];
[t,lambda_var] = ode45(#(t,lambda_var) tan(0.9*lambda_var)*cos(lambda_var), tspan, lambda0);
t0 = 0:0.01:40;
lambda1 = zeros(1,4001);
lambda1 = interp1(t,lambda_var,t0);
lambda = [t0' lambda1'];
I used the equations I found in the paper in the lambda0 expression and in the [t,lambda_var] one. The "lambda_d" block contains a two-column vector, the first one with time values and the second one with the corresponding lambda_dot values. Also lambda (output of fcn block) should be defined in the same way, as you can see in the code above.
I thought the problem was the scope: if I run this simulation, I do not have a single signal plotted on the scope. Instead, I get as many signals as the size of the vector which contains something like 4000 values (0.01 seconds of sampling time on 40 seconds tot).
But I understand now that the problem is the ODE equation in the Simulink block. I need to write it in that block, because the two inputs will be variable in the next step. The equation I need to solve is:
tan(0.9*lambda)*cos(lambda) = -vx*yawrate /g
EDIT: I changed the main question according to your comments.

Simulink: Setting the output of a continuous S-Function

I have a continuous S-Function that solves the derivatives for various state properties within a ICE cylinder. As such, the output of the function is set to output the integral of those derivatives for each time step which is a 7 element vector (1 for each of the properties being calculated)
block.OutputPort(1).Data = block.ContStates.Data;
At some point in the cycle I would like to change the value of this output to an explicit value (i.e. not the integral of the derivative) such as below (in this case the explicit value being x):
block.OutputPort(1).Data = block.ContStates.Data;
block.OutputPort(1).Data(3) = x;
I'm using a if statement to switch into this alternative output. Through debugging, I think I've verified that Simulink is entering this block of code at the right point - however the output of the S-Function remains as the integral of the derivatives which gives me a non-finite error.
Any help or suggestions that would allow me to explicitly set the output of a continuous S-Function would be much appreciated.

ODE implemetation in NetLogo

How does one implement ODE in netlogo?
Right now , I use the Euler method which is solves the the given equations:
R[t+1] = r[t] + v[t] * step-size
V[t+1] = v[t] + f * step-size
Found this similar question, but it suggest uni-directional link from mathematica to netlogo which is makes it not possible to implement.
I looking for something similar to ode solver in matlab?
Partial answer, compare accuracy-runtime estimates for Euler, improved Euler and RK4
Assume that the most time-consuming part is the evaluation of the system function, i.e., the vector arithmetic of the Runge-Kutta methods are a small overhead.
Given a time interval of T=1, restrict the methods to 100 function evaluations. Then
Euler performs 100 steps with step size h=0.01 and global error of the magnitude pow(h,1)=0.01.
improved Euler has global error order 2 and 2 function evaluations. Thus performs 50 steps with step size h=0.02 and global error of magnitude pow(h,2)=4e-4.
classical RK4 of order 4 and 4 function evaluations per step performs 25 steps of step size h=0.04 with global error magnitude pow(h,4)=2.56e-6.
Fixing the global error at about 1e-4 one obtains inversely for number of function evaluations
10000 for Euler, with h=1e-4
200 for improved Euler, with h=1e-2
40 for classical RK4, with h=0.1
which explains speed differences if the methods are tuned for the same level of the global error.
The strategy for the implementation of RK4 in the ball example is for an ODE system x'=f(t,x), where x is the, possibly very large, state vector
save t0=t, x0=x
evaluate k1 = f(t,x)
set t=t0+h/2, x=x0+h/2*k1
evaluate k2=f(t,x)
set x=x0+h/2*k2
evaluate k3=f(t,x)
set t=t+h, x=x0+h*k3
evaluate k4=f(t,x)
set x=x0+h/6*(k1+2*(k2+k3)+k4)
In an agent based system it is reasonable to store the components of the state vector belonging to the agent as internal variables of the agent. Then the vector operations are performed by iterating over the agent collection and computing the operation tailored to the internal variables.
A second order ODE is transformed to a first order system as indicated in the question, x''=a(x,x') gets transformed to [x',v']=[v, a(x,v)]. The big vector of the agent system is the composed of the collection of the pairs [x,v] or, if desired, as the concatenation of the collection of all x components and the collection of all v components.

Matlab ode solver algebreic calculation

I have an ODE model in Matlab coded as a function. I integrate the ODE's over time using ode15s. After the solver has finished, I calculate algebraically, a new variable that's a fraction of the sum of the other variables output by the model.
For example:
dA/dt = xxxxx
dB/dt = xxxxx
dC/dt = xxxxx
this gets integrated and returns an array of columns for dA,dB,dC. From the output I calculate:
model_result = A/(A+B+C).
for the whole time course), and plot this vector of values vs time.
However, I also need to perform sensitivity analysis on the model, for which I've used the modified ODE15s on the Mathworks repository. I need to be able to set "model_result" above as the objective function for the sensitivity calculations.
I attempted to calculate model_result inside the function, and have it returned as another variable, but obviously this doesn't work as the integrator returns the integrated value, rather than the algebraically calculated value.
Is it possible to have algebraic values returned by an ODE solver in Matlab?
If not, does anybody have any idea how to perform this kind of sensitivity analysis?
thanks for any help. I'm quite new to modelling so apologies if I'm using all the wrong terms!