Why does the step response to my discrete system not match between MATLAB and Simulink?

23 vues (au cours des 30 derniers jours)
Demian Mendez
Demian Mendez le 14 Avr 2016
Commenté : Paul le 17 Fév 2023
Hello, I am trying to figure out why I get different step responses to the same discrete system when I model the system in Simulink and MATLAB. Below is an example of what I am experiencing. The Following MATLAB code
G = tf(24.3,[3746 137.4 1]) % My original continuous time system.
Gz = c2d(G,1) % Discretization of the system with Ts = 1sec sample time.
step(Gz) %Step response to Gz
Produces
>> StepResponse_Comparison
G =
24.3
----------------------
3746 s^2 + 137.4 s + 1
Continuous-time transfer function.
Gz =
0.003204 z + 0.003165
---------------------
z^2 - 1.964 z + 0.964
Sample time: 1 seconds
Discrete-time transfer function.
The model of the same system in Simulink (At least I think its the same). Sample time is set to 1 in the step block and inherited by the transfer function block. Initial conditions are all 0.
Produces
From what I understand these two plots should match. Any explanation for what is going on here would be much appreciated. Thank you.

Réponses (3)

Steve Lee
Steve Lee le 18 Nov 2018
I had same problem.

Luca Ferro
Luca Ferro le 16 Fév 2023
Had the same problem earlier, it's late but it can be helpful for others i guess:
instead of using the discrete transfer function block use the LTI system block.
For PID blocks use the PID controller block as usual.
There is no need for ZOH or Rate transition blocks.
Also try to include the delays inside of the transfer functions, avoiding the use of the external Delay block.

Paul
Paul le 16 Fév 2023
The explanation for the Simulink resutls is that the coefficients entered in the Discrete Transfer Function block don't represent the actual transfer function G(z).
Here is how Gz is developed
G = tf(24.3,[3746 137.4 1]) % My original continuous time system.
G = 24.3 ---------------------- 3746 s^2 + 137.4 s + 1 Continuous-time transfer function.
Gz = c2d(G,1) % Discretization of the system with Ts = 1sec sample time.
Gz = 0.003204 z + 0.003165 --------------------- z^2 - 1.964 z + 0.964 Sample time: 1 seconds Discrete-time transfer function.
Based on what's shown in the display, the transfer function entered into Simulink was
Gsimulink = tf([0.003204 0.003165],[1 -1.964 0.964],1)
Gsimulink = 0.003204 z + 0.003165 --------------------- z^2 - 1.964 z + 0.964 Sample time: 1 seconds Discrete-time transfer function.
But Gz and Gsimulink result in different responses, with Gsimulink matching the Simulink solution.
step(Gz,Gsimulink,800)
The actual numerator and denominator of Gz are
format long e
Gz.num{:}
ans = 1×3
0 3.204093815520879e-03 3.165157912686405e-03
Gz.den{:}
ans = 1×3
1.000000000000000e+00 -1.963723295999098e+00 9.639854051237154e-01
Apparently all (well, maybe not all, but certainly more than three) of those significant digits matter.
The solution is to either enter Gz.num{:} and Gz.den{:} as the Numerator and Denominator block parameters in the Discrete Transfer Function block, or enter Gz as the LTI System Variable parameter in the LTI system block, as suggested by @Luca Ferro
  2 commentaires
Luca Ferro
Luca Ferro le 17 Fév 2023
i already tried that road and it doesn's seem like a perfect match:
When doing a set_param function it requires a string and during the conversion (red rectangle), it loses precision.
While by loading from workspace it actually work as intended:
As @Paul said they are equivalent, i was just missing the idea of working with the workspace instead of setting the parameters directly.
Do you know if Discrete Transfer Fcn block offer some advantages compared to LTI System block?
Paul
Paul le 17 Fév 2023
Use num2str to not lose that precision if needing to set the parameter as a literal vector
dcTf = tf(1,[0.2228665 0.770675 1]);
format long e
disDcTf = c2d(dcTf,0.01)
disDcTf = 0.0002218 z + 0.0002192 ----------------------- z^2 - 1.966 z + 0.966 Sample time: 0.01 seconds Discrete-time transfer function.
disDcTf.den{:}
ans = 1×3
1.000000000000000e+00 -1.965569927908843e+00 9.660109411503381e-01
"[" + string(num2str(disDcTf.den{:},16)) + "]"
ans = '[1 -1.965569927908843 0.9660109411503381]'
Don't know if there are any corner cases where the string literal will be different in the last bit or something like that. IMO, It's best to avoid this conversion and set the parameters with Gz.num{:} and Gz.den{:} or use the LTI System block with Gz.
The DTTF block offers some additional features, like setting initial states, external reset, and frame based processing. I don't think the LTI System block has those.

Connectez-vous pour commenter.

Community Treasure Hunt

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

Start Hunting!

Translated by