# Effects of Zero Order Hold in Simulink linearization

37 views (last 30 days)
Marco Dettori on 22 Oct 2020
Edited: Paul on 2 Nov 2020 at 17:00
Hello, I am having some difficulties in finding out how to implement in Simulink a discrete time controller for an analog plant in a way that the frequency response of the "equivalent continuous-time controller" seen by the plant reflects the distortion produced by the zero-order-hold digital implementation.
From the theory it is known that if a digital controller Kd is implemented through a sample and hold mechanism, the "equivalent continuous-time controller" seen by the plant will have a distortion term equal to D(s) = (1-exp(-s*Ts)) / (s*Ts), where Ts is the sampling time.
To make my question clearer, consider the attached Simulink model ContVsDiscreteTime.slx
It has a continuous time noise source and a discrete-time LTI system (I will call it the controller) with transfer function K(z)=(631.3 z -578)/(z-0.3522) and sampling period Ts = 0.1 s. The transformations from the continuous-time source signal to the discrete-time controller input and from the discrete-time controller output back to continuous time at the outport are performed using two Rate Transition blocks as illustrated in the Fault-Tolerant Fuel Control System demo sldemo_fuelsys provided in the Simulink documentation.
To anayze the system, I use the Simulink Model Linearizer app. First I compute the Bode plot of the gain from B to C: as expected the Bode plot obtained matches the frequency response of the discrete-time block. Then I compute the Bode plot of the gain from A to D. My expectation is to obtain a continuous-time linear system whose frequency response is essentially equal to that of the discrete-time system modified by the distortion term D(s), which affects especially the phase. However, as shown in the attached screen shot, the Simulink Model Linearizer returns the same discrete-time system of the previous step, as if the conversions from and to continuous time were not present (the values stored in the To Workspace blocks clearly show.that the signals in A and D are not discrete-time with sampling time Ts) This is particularly misleading when it's part of a feedback loop, because it characterizes closed-loop performance as if the deterioration D(s) due to the digital implementation was not present.
How should I modify the Simulink diagram to have the distortion term included in the analysis? Obviously, I can always explicitly add the block D(s) as an LTI system after converting back the controller output to continuous time. However, I have the feeling that it might not be the cleanest way to do it, as it is difficult to imagine that Simulink would overlook the necessity of directly implementing such an essential part of the conversion.
Below are two JPG files with the block diagram and the relevant settings.  Paul on 22 Oct 2020
Can you post a picture of the block diagram from the .slx file? Or is the diagram too complicated? If it is, can you come up with a simple example that illustrates your question and post that diagram as a picture?
Marco Dettori on 23 Oct 2020
Hi Paul, thanks for your reply. The diagram is really simple, just bare bone to illustrate the issue. I posted a picture of it as well as of the relevant settings. Note that the samplig time for the Outport is set to 0

Paul on 23 Oct 2020
Edited: Paul on 1 Nov 2020 at 15:42
"My expectation is to obtain a continuous-time linear system whose frequency response is essentially equal to that of the discrete-time system modified by the distortion term D(s), which affects especially the phase."
The path from A to D contains a discrete element. AFAIK, there is no way to tell the linearizer to convert that to a continuous block. For sure, the default (and maybe only) behavior is to go the other way, i.e., in a sampled-data system all continuous poritions of the model are converted to discrete time in a prescribed manner, which is the textbook way of analyzing sampled-data systems. Here is a simple example to illustrate some concepts.
Consider the following block diagram. The three transfer functions are:
Ts = 0.1;
G1 = tf([1 .5],[1 -.5],Ts);
G2 = tf(1,[1 1]);
G3 = tf(1,[1 2]);
First, we get the io points for the model.
io = getlinio('linexamp')
7x1 vector of Linearization IOs:
--------------------------
1. Linearization input perturbation located at the following signal:
- Block: linexamp/Gain
- Port: 1
- Signal Name: u2
2. Linearization input perturbation located at the following signal:
- Block: linexamp/Ground
- Port: 1
- Signal Name: u1
3. Linearization output measurement located at the following signal:
- Block: linexamp/sys1
- Port: 1
- Signal Name: y1
4. Linearization output measurement located at the following signal:
- Block: linexamp/sys2
- Port: 1
- Signal Name: y2
5. Linearization output measurement located at the following signal:
- Block: linexamp/sys3
- Port: 1
- Signal Name: y3
6. Linearization output measurement located at the following signal:
- Block: linexamp/sys4
- Port: 1
- Signal Name: y4
7. Linearization output measurement located at the following signal:
- Block: linexamp/sys5
- Port: 1
- Signal Name: y5
Linearize the model from input u1 to all outputs using all default options.
sys = linearize('linexamp',io(2:end));
The transfer functions from u1 to y1,y2,y3, and from u1 to y4 and y5 are:
tf(sys(1:3,1))
tf(sys(4:5,1))
ans =
From input "u1" to output...
z + 0.5
y1: -------
z - 0.5
0.09516 z + 0.04758
y2: ----------------------
z^2 - 1.405 z + 0.4524
0.004528 z^2 + 0.006361 z + 0.002049
y3: ------------------------------------
z^3 - 2.224 z^2 + 1.603 z - 0.3704
Sample time: 0.1 seconds
Discrete-time transfer function.
ans =
From input "u1" to output...
0.09516 z + 0.04758
y4: ----------------------
z^2 - 1.405 z + 0.4524
0.004528 z^2 + 0.006361 z + 0.002049
y5: ------------------------------------
z^3 - 2.224 z^2 + 1.603 z - 0.3704
Sample time: 0.1 seconds
Discrete-time transfer function.
We see that the tf Y1/U1 = G1, as expected. Furthermore, Y2/U1 = Y4/U1 and Y3/U1 = Y5/U1. These results show that that the linearizer does place a ZOH (default option) in front of G2, even though it is not exmplicitly included in the diagram. Also, these tf's are what we expect them to be:
Y2overU1 = G1*c2d(G2,Ts,'zoh')
Y3overU1 = G1*c2d(G3*G2,Ts,'zoh')
Y2overU1 =
0.09516 z + 0.04758
----------------------
z^2 - 1.405 z + 0.4524
Sample time: 0.1 seconds
Discrete-time transfer function.
Y3overU1 =
0.004528 z^2 + 0.006361 z + 0.002049
------------------------------------
z^3 - 2.224 z^2 + 1.603 z - 0.3704
Sample time: 0.1 seconds
Discrete-time transfer function.
Now look at what happens when we include the input u2 in the linearization. As expected the tf's from u1 don't change, but what about Y3/U2?
sys = linearize('linexamp',io);
Y2andY3overU1 = tf(sys(2:3,2))
Y3overU2 = tf(sys(3,1))
Y2andY3overU1 =
From input "u1" to output...
0.09516 z + 0.04758
y2: ----------------------
z^2 - 1.405 z + 0.4524
0.004528 z^2 + 0.006361 z + 0.002049
y3: ------------------------------------
z^3 - 2.224 z^2 + 1.603 z - 0.3704
Sample time: 0.1 seconds
Discrete-time transfer function.
Y3overU2 =
From input "u2" to output "y3":
0.09063
----------
z - 0.8187
Sample time: 0.1 seconds
Discrete-time transfer function.
The tf Y3/U2 is what we would expect if the the perturbuation input u2 is sampled and followed by a ZOH
c2d(G3,Ts,'zoh')
ans =
0.09063
----------
z - 0.8187
Sample time: 0.1 seconds
Discrete-time transfer function.
In this case, the system included a discrete element, G1, that it could not remove using the default linearization options (see response below from Marco for other options). So the linearization results in a discrete model of the sampled-data system. It (apparently) does this by isoloating the continuous portions of the model, discretizes assuming a ZOH on the inputs to that portion (unless specified otherwise) and then connects to the discrete part. If there are multiple sample times in the model, I'm pretty sure the default behavior is to use d2d to get all discrete blocks up to the largest sample time.
Let's look at what happens when we only specify only the input u2 and only the output y3:
sys = linearize('linexamp',io([1 5]))
sys =
A =
Internal
Internal -2
B =
u2
Internal 1
C =
Internal
y3 1
D =
u2
y3 0
Continuous-time state-space model.
We see that sys is now a continous model, with only one state, and the tf Y3/U2 is G2:
tf(sys)
ans =
From input "u2" to output "y3":
1
-----
s + 2
Continuous-time transfer function.
The reason for this behavior is that the default option for linearization is 'BlockReduction' = 'on'. With this setting, the linearizer first eliminates all blocks that are not in the linearizzation path(s), which in this case was specified by io([1 5]). If you turn BlockReduction off, you get back the discrete result (and you'll see that sys includes all of the states in the system):
sys=linearize('linexamp',io([1 5]),linearizeOptions('BlockReduction','off'));
tf(sys)
ans =
From input "u2" to output "y3":
0.09063
----------
z - 0.8187
Sample time: 0.1 seconds
Discrete-time transfer function.
More details and discussion at:
doc linearize
doc linearizeOptions

Marco Dettori on 1 Nov 2020 at 5:50
Hi Paul,
I apologize for the late reply. Thank you very much for your reply and the time you spent in putting together your example and providing such a thourough analysis of it. It helped me learn a great deal about how Simulink treats hybrid system and pointed me in that right direction to solve my issue. Let me start by adding two extra results to your analysis, which you might find useful as well. The first one is that, in fact, the presence of a discrete-time block in the diagram does not force a discrete-time analysis as the only possible path. This apparent restriction is only due to one of the default linearization options. By executing the code
linOpt=linearizeOptions;
linOpt.SampleTime=0;
sysc=linearize('linexamp',io(2:end),linOpt);
tf(sysc(1,1))
ans =
From input "u1" to output "y1":
s + 20.79
---------
s + 6.931
which is exactly equal to
d2c(G1,'zoh')
The apparent behavior of always performing a continuous to discrete-time conversion is due to the default value of -1 for linOpt.SampleTime, which, according to the documentation, tells the linearization algorithm to "Use the longest sample time that contributes to the linearized model", and Ts = 0 will never be the longest.
Another interesting aspect is that the ZOH method that is used in the c2d conversions of your example as well as in the d2c conversion of my example above is not related to the presence of the ZOH block in the model. In fact, it is another default linearization option. By setting
linOpt.RateConversionMethod='tustin';
all the c2d and d2c conversions will now be performed with the Tustin method.
Incidentally, I find the ZOH block sort of the poster child of how confusingly Simulink handles conversions between continuous and discrete time domains. In your example, in fact, you use the ZOH block in the same way as I would, which is the standard way: as a D2C converter that gets digital samples at its input and creates a continuous-time staircase-like signal by holding each sample for Ts seconds. Instead, Simulink defines the functionality of the ZOH block this way: "Convert an input signal with a continuous sample time to an output signal with a discrete sample time". In essence, Simulink treats the ZOH as the opposite converter, i.e., as if it were a sampler, which does not really make any sense: a discrete time signal does not need to be held, because it does not exist outside of the sampling instants.
Since you have been so nice, I'd like to provide some perspective on why I was looking to transform the hybrid system into a continuous time system rather than into a sampled-data system. Those are basically two equivalent views and depending on the circumstances, one might be more useful than the other.
In general, in a control system we have a numeric controller sitting in a processor which updates numbers only at discrete points in time (the red world) and a plant sitting in the physical world, where time is continuous (the blue world). Getting an equivalent discrete-time or continuous time system really depends on where you cut the loop: if you cut it at "the red wires" you get the former, but you are making an implicit assumption, i.e., that the behavior of the physical world between u[k] and y[k] matters only at the sampling instants, and nothing relevant happens in between. This assumption is an approximation that can be more or less justified based on the value of the sampling time T. If you cut at the "blue wires", instead, you do not need to make any assumptions because you do see a continuous-time system, just one that is not super smooth because it reacts to a signal y(t) changing in a smoothly continuous fashion by producing a signal u(t) which is piece-wise constant, a bit jumpy if you want.
Let's now get to the root of my problem: I wanted to design a discrete time controller for a continuous-time plant P(s). And I wanted to do it by using some design techniques that have been developed for continuous-time systems. I know by theory and experience that If I design a continuous-time controller K(s) for a plant P(s), no matter how I discretize it into K(z), when I implement it on a test board and close the loop with the plant, its performance will not be as good as the results that I was expecting from the design. This is because there is an inherent loss of performance associated to the digital implementation of a controller with ZOH (that jumpiness mentioned earlier). The key point is that this performance loss will always be present, no matter how I discretize K(s) into K(z) (actually by using ZOH as method of discretization, one doubles the amount of deterioration). The frequency response of the "continuous-time controller" seen by the plant is equal to the frequency response of the digital controller multiplied frequency-wise by the frequency response of the distortion factor D(s)=(1-exp(-sT))/(sT), which accounts for the jumpiness of a ZOH system seen in continuous time.
In conclusion, to make sure to get a design with the same performance level that will be seen in the actual digital implementation, one needs to account for the distortion term in advance, i.e., by designing a continuous-time controller K(s) for a modified plant P(s)*D(s), instead of P(s), and then discretizing it into K(z) by using the method that achieves the max fidelity in preserving the shape of the frequency response (generally Tustin).
Paul on 1 Nov 2020 at 15:40
Marco,
Geat point about the SampleTime linearization option (though it's not explained well in the doc). I will update my answer to clarify that I was assuming default options.
At first I wasn't sure I agreed with your assessment of how Simulink defines and implements the functionality of the ZOH block. The Description from the doc page says "The Zero-Order Hold block holds its input for the sample period you specify." OTOH, as you point out, later down the doc page states that the purpose of the ZOH block is to "Convert an input signal with a continuous sample time to an output signal with a discrete sample time," which sounds weird. And that same page also says "Do not use the Zero-Order Hold block to create a fast-to-slow transition between blocks operating at different sample rates. Instead, use theRate Transition block." I'd think that continous-to-discrete is a form of fast-to-slow. I do think there are other confusing aspects of that block, like in this example the sample time at the output of the block is D1 as opposed to Cont. I think it would all be much clearer if there was a specific block for sampling (i.e., A-to-D) and another for going the other way (i.e., D-to-A), although as we've seen the D-to-A is implicitly included at the transition from discrete to continuous. The more I think about this, the more I'm in agreement with you that the ZOH block does not implement an an actual zoh the way that you and I think it should be. This issue is proably worthy of a separate question; maybe it will get some attention from TMW staff.
I fully agree that if you want design to design your compensator K() in the continuous domain that:
a) you may need to account for D(s) in series with P(s), and
b) once you design K(s) it would be inappropriate to discretize to K(z) using the zoh method.
As to the former, I built a simple model that had an input, followed by a ZOH block, followed by G2. I then called linearize with the SampleTime=0 and was surprised (disappointed?) to see that the result returned just G2, as opposed to G2 in series with some representation of D(s). Maybe I missed some option that governs how it handles the ZOH block. Note that you can also define your own linearization for a block, which might come in useful for some applications. Of course, you can always use linearize to get P(s) and then append D(s) yourself as part of your design process. Also, you can implement D(s) explicily, specifly the order of the Pade approximation for linearization in the block parameters of the transport delay, and then linearize to get a model of the D(s)*P(s).