Integrator State Port: Why is its use restricted?

9 vues (au cours des 30 derniers jours)
creepydog
creepydog le 8 Juin 2020
Commenté : creepydog le 24 Juin 2020
Hello.
I'd like to know why the use of the Integrator Block's State Port is restricted (and I have some more questions, see below). Here's the long story:
What I want to do
I'm trying to write a Simulink block that computes the arithmetic mean value of a continuous input signal over some period of time. In general, beginning and end of a period are given by an external trigger signal, but in this minimal working example for simplification I use a Pulse Generator as a trigger signal (constant period every 1 second). Every rising edge marks the beginning of a new period and also the end of the previous one. Additionally, I use a Triggered Subsystem to sample the computed mean value and hold it until the next period is over.
To compute the mean value I integrate the given signal and divide it by the period length (which is equal to 1 here, so I left that out). The integrator is reset at the beginning of every period. The integrator state at the end of a period is the result I'm looking for.
First attempt
My first solution looked like this:
Version 1 (without state port)
This doesn't work as naively expected because the integrator reset occurs before the Triggered Subsystem can copy the result. So the result is always zero:
I think I understand this behavior, therefore no questions so far ...
Second attempt
My second solution involved the integrator's state port. The Integrator Block documentation states:
"[...] If the block is reset in the current time step, the output of the state port is the value that would have appeared at the block's standard output if the block had not been reset. The state port's output appears earlier in the time step than the output of the Integrator block's output port. [...]"
This doesn't work either. Simulink throws an error:
"State ports can only be used to break algebraic loops or to "hand-off" states between systems. Use the output port rather than the state port of 'model/Integrator' as the source of the signal routed (either by direct or virtual connection) to 'model/Triggered Subsystem' "
The Integrator Block documentation also tells me that the use of the state port is restricted to only two special scenarios, stating:
"When updating a model, Simulink checks that the state port applies to one of these two scenarios. If not, an error message appears."
So my first set of questions is: Why is this an error? Is there a technical necessity? Is there a problem I don't see yet?
Third attempt
One of the mentioned two special scenarios where I'm allowed to use the state port is the case of a self-resetting integrator. So I tricked Simulink to believe that that's what I'm doing. I added two Gain blocks and a Sum block which should not change anything.
Now I don't get any error messages and the model works perfectly as expected (the mean value of a constant 1 signal over 1 second is equal to 1; the result is output for the first time when the first period ends, which is at t=1):
So my second set of questions is: Why does this work, although the former example doesn't? Does this solution have any hidden disadvantages, apart from its obvious ugliness? Is it more difficult for the variable-step solver, the zero-crossing detection or any other part of the simulation? Is there any reason why I shouldn't use this solution? Could I get wrong results in a "less minimal example" context?
And my third, only supplementary question: Is there an even better way to solve the problem? (I already tried manual (trapezoidal rule) integration using memory blocks but that's less accurate and also somewhat ugly)

Réponses (2)

Paul
Paul le 10 Juin 2020
Modifié(e) : Paul le 10 Juin 2020
Only answering the third, supplementary question ....
I think I was able to do what you want without using integrator reset at all. Just let the integrator run and use the triggered subsystem to sample, and store, the integrator output at the boundaries of your intervals and compute the average. I implemented your original block diagram, but without the reset on the integrator. The triggered subsystem is:
The delays and the digital clock all have sample time of -1. Both delays have an initial output of 0, though you might want to use a different value on the clock delay to avoid potential for divide by zero if the trigger hits at t=0. Set the initial output of the output port to 0.
Here's the result I got using a sine wave as the source input.
  8 commentaires
Paul
Paul le 23 Juin 2020
Here's a modification that might have more appeal, though I'm sure it has some limitations somewhere. The idea is as follows. Use the hit crossing to do two things:
Trigger the average system as has already been done.
Trigger a separate subsystem that computes a future time (from the time of the hit crossing detection) that you can use to reset the integrator.
This way the trigger only depends on the solver catching the hit crossing and you can control how much of the interval that you're going to miss at the start of the window.
Here's the model:
The Average block triggers on the hit crossing as does the Reset Time block, which is:
All the reset time block does is compute a small offset from the time of the trigger that is the time to reset the integrator. The inital output is set to zero.
When sim clock >= reset time, the integrator resets (rising). As you can see, I made the time offset 1e-8. I'd not be surprised if problems arise if you make that offset too small, but I didn't experiment. Anyway, here's the output:
So far the only odd thing I've noticed is that the solver takes a lot more steps to integrate through some reset times than others. For example, it seems to get through t = 3, pretty quickly:
>> out.tout(45:55)
ans =
2.482494474052150e+00
2.682494474052150e+00
2.882494474052150e+00
3.000000000000000e+00
3.000000009999972e+00
3.000000010000000e+00
3.000000010000028e+00
3.050000000000000e+00
3.099999989999971e+00
3.199999969999914e+00
3.399999929999800e+00
But a lot more steps to get through t = 4:
>> out.tout(55:85)
ans =
3.399999929999800e+00
3.599999929999800e+00
3.799999929999800e+00
3.999999929999801e+00
4.000000000000000e+00
4.000000009999943e+00
4.000000010000000e+00
4.000000010000057e+00
4.000000360001054e+00
4.000000710002051e+00
4.000001410004045e+00
4.000002810008033e+00
4.000005610016010e+00
4.000011210031963e+00
4.000022410063869e+00
4.000044810127682e+00
4.000089610255308e+00
4.000179210510558e+00
4.000358411021060e+00
4.000716812042064e+00
4.001433614084070e+00
4.002867218168084e+00
4.005734426336111e+00
4.011468842672165e+00
4.022937675344273e+00
4.045875340688489e+00
4.050000000000000e+00
4.070623296557556e+00
4.141246583115055e+00
4.282493156230053e+00
4.482493156230053e+00
I don't know what's going on here, but I did notice that when I made the pulse generator period 1.1 sec the solver took about the same, small number of steps to integrate through each reset time.
creepydog
creepydog le 24 Juin 2020
I still think the approach using the integrator state port (see me original question) should be better (cleaner, more robust ...) than all our workaround solutions that rely on sufficiently small time steps.
Apart from that, I've posted a new question about zero-crossings, partially based on our discussion. See here: https://de.mathworks.com/matlabcentral/answers/553960-number-of-necessary-time-steps-to-handle-a-zero-crossing

Connectez-vous pour commenter.


Jonas
Jonas le 17 Juin 2020
"This doesn't work as naively expected because the integrator reset occurs before the Triggered Subsystem can copy the result. So the result is always zero:"
Maybe you can add a Unit Delay in front of the Integrator reset, such that the triggered subsystems is triggered one sample earlier than the Integrator is reset.
  2 commentaires
creepydog
creepydog le 17 Juin 2020
Thank you, Jonas, for your proposal regarding my supplementary question. I'm afraid, adding a Unit Delay block doesn't work in a Continuous Sample Time environment because it only supports discrete sample time. So it would delay the signal for a whole discrete step, not only for a single time step of the variable step solver.
In case you instead meant adding a Memory block: This only works under some assumptions. See Paul's similar proposal and my reply.
Jonas
Jonas le 17 Juin 2020
Ah indeed, my mind was fixed on discrete time simulation. I have too little experience with continuous time simulation to answer your questions.
Good luck!

Connectez-vous pour commenter.

Produits


Version

R2018b

Community Treasure Hunt

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

Start Hunting!

Translated by