set initial conditions in matlab function block (simulink) - matlab

I'm currently trying to learn some basis for a bigger project that will make a massive use of simulink.
Right now, I would like to code my own simulink block whith a feedback. It means that one of the inputs is also the output (with a 'memory' block between them to ensure everything goes right!).
My code looks like
function out = func(cmd,in)
if in == 0 && cmd == 1
out = 1;
elseif in == 1 && cmd == 0
out = 0;
else
disp('error')
end
As I said, 'in' is linked to 'out'. Unfortunatly, it is required to set an initial value for out otherwise I get some errors. Of course I can't do it in the code like that :
out = 0;
In that case, the value 'out' is set to 0 at each time step.
Have you any advice to do it ? I've read that S-functions and flag could be used, but I have no idea how it works.

Your function gets called during model initialization (t=0), and the value of out will be calculated based on the value of cmd and in value at t=0.
Hence you need to make sure cmd and in are initialized correctly you shouldn't be setting a value explicitly for out.
If you really need to (which you won't) then the simplest thing to do is use an Initial Condition block after this block.
Note that the above is only applicable to a block that has no states, as with your example. For your bigger project, you may have custom written blocks with states, in which case the approach to setting initial conditions for the states is different depending on whether you are using a MATLAB Function block or an S-Function.
Finally, note that if you want an error to be thrown then throw an error in the usual MATLAB way. Using disp as you are doing doesn't stop the simulation, but you haven't set a value for out, which is bad coding.

Well, I think that I've solve that issue. I put it here, I could help someone else
by adding a clock and initialize out with an if statement if time <=0 out = ...
However, it requires to add an extra input, which is not very convinient. Maybe someone could tell me how to solve that.
do the if properly and terminate it by else out = in;
I belive that was the main problem here. I've also placed my matlab-function block in a subsystem with a mask that initializes in and cmd.
Thanks again for your help, it helped a lot.
However, my problem is still unsolved since the statement if t<0 doesn't work for some reason.

Related

multiple triggered subsystem + algebraic loop, initialisation problem

I have a Simulink diagram which contains multiple triggered subsystem with different timestamp. In this model I also got a feedback loop inducing an algebraic loop. Therefore the signal must be initialised, in order to do that, I used a Memory block.
The problem is on the feedback loop, the value of the signal seems to be not initialised.
I believe the origin of this problem is that it is indeed initialised by the memory block for the first timestamp, however, the trigger on the next subsystem did not occur. By default, this subsytem puts its out signal value to be 0. The loop is therefore broken there.
Did someone already encounter this situation ? Any Tips ?
Thank you for your time.
You could add initialization blocks for your trigger values? I don't know about what SubSystem0 looks like inside, but its output could use an initialization block as well, this way you guarantee that you have an input to Subsystem

How to create if-then logic in simulink?

I have a written code and a program in matlab, but I want to do the same think in simulink. I am stuck at the if-then part of the program which I can't figure out.
I tried using the "If" block, but then I didn't know how to say "then alfa=0". After trying to research it I saw many different ways to do conditional statements and now I'm very confused.
if(vb-y(2))*y(3)<0
alfa=0
end
if y(3)<zba && (vb-y(2))*y(3)>=0
alfa=0
end
if zba<y(3) && y(3)<zmax && (vb-y(2))*y(3)>=0
alfa=0.5*(sin(pi*(y(3)-(zmax+zba)/2)/(zmax-zba))+1)
end
if zmax<y(3) && (vb-y(2))*y(3)>=0
alfa=1
end
I basically need this made in simulink. If someone could just start it out for me or explain the proper way to do this I'd be very thankful.
I believe this can be done in the following way: Choose the if-block to implement your condition, and for the then and else-block, you choose an if-action-block. The if block decides which of these two if-action blocks will be evaluated at every timestep and the following merge-block integrates both individual outputs into one combined signal (alfa in your case) again. The image shows the first if-then of your code (assuming else alfa=1. In case of no else, the else-output can be disabled in the block-properties).
Since the if-block supports elseif expressions as a comma separated list, I suggest you use this for your 2nd, 3rd and 4th if's, which means that you will most likely need additional if-action blocks, and more inputs for the merge-block. Also for the elseif expressions, you'll need to change your && to & which should be fine. a && b only evaluates b if a is true, a & b always evaluates both.

How to save a value generated in middle of a MATLAB simulink operation

I have MATLAB Simulink model running successfully. In this model, a function runs code to do the operation. The function code generates a value during the operation. I want to save this value and use at successive operations.
In above screen shot, Icur_in and Icur_ou are input and output of the function. In fact both refer to same value. I am using memory function to hold the value for next operation. Up to this point is fine. But the value keeps on changing.
My present code is:
Function [Icur_ou] = fun(Icur_in)
Icur_ou = Icur_in;
if somecondition
Icur_ou = I_s;
end
end
I am not 100% sure about what your problem is, since you state: "Up to this point is fine." And also your model looks fine to me, but nevertheless I found this link, which seems to be about the same problem. Besides the suggested solutions, I also liked the first two comments about persistent variables, which I think could maybe also help you depending on the sample time of your model (see comments in the link).
In this case, you would not need the memory block, but instead you'd have to make your Icur_ variable persistent, so that it stays in memory between function calls. Similar to this:
Function [Icur_ou] = fun(Icur_in)
persistent Icur_ou = Icur_in;
if somecondition
Icur_ou = I_s;
end
end

Use exist to check if Simulink-Block has parameter 'SampleTime'

I want to write a function that automatically changes the parameter SampleTime of all blocks in my model to a specific value. I can use find_system to find all blocks and then I can loop through all blocks and use set_param('Blockpath','SampleTime','0.001'). But if I do this and the block does not have a parameter called SampleTime, it'll make my program crash.
So my question is how can I find out if the parameter exists before setting it? I tried something like exist(['blockpath','/SampleTime']), but it didn't do what I expected. Any ideas?
You can use get_param('blockpath','ObjectParameters') to get a struct with all parameters and then use isfield to check if you can find SampleTime.
I think what you are doing is not a good idea. In typical simulink models, you have the sample time set only at very few places, running all other models with inherited sample time. In most cases, it is not a problem to change these few places.
If you have to many blocks or you frequently change the sample time, better use a workspace variable or a mask parameter. Set all blocks to to have sample time x and put x=0.01 in your base work space to set it for all blocks.
Building on #Daniel's answer, if you really must do this, which for reasons given in the comments to #Daniel's answer is a bad idea, then the simplest approach is
% Define the new value as a string
>> newSampleTime = '10';
% Find all blocks in the model
>> allBlocks = find_system(gcs);
% Identify the blocks that have a SampleTime property
>> blockIdx = cellfun(#(c)isfield(get_param(c,'ObjectParameters'),'SampleTime'),allBlocks);
% Change the sample time
>> cellfun(#(c)set_param(c,'SampleTime',newSampleTime),allBlocks(blockIdx));

Determining direct-feedthrough paths without compilation/execution

I am currently working on a tool written in M-Script that executes a set of checks on a given simulink model. This tool does not compile/execute the model, I'm using find_system and get_param to retrieve all the information I need in order to run the routines of my tool.
I've reached a point where I need to determine whether a certain block has direct-feedthrough or not. I am not entirely sure how to do this. Two possible solutions come to mind:
A property might store this information and might be accessible via get_param. After investigating this, I could not find any such property.
Some block types have direct-feedthrough (Sum, Logic, ...), some other do not (Unit Delay, Integrator), so I could use the block type to determine whether a block has direct-feedthrough or not. Since I'm not an experienced Simulink modeller, I'm not sure if its possible to tell whether a block has direct-feedthrough by solely looking at its block type. Also, this would require a lookup table including all Simulink block types. An impossible task, since additional block types might get added to Simulink via third party modules.
Any help or pointers to possible solutions are greatly appreciated.
after some further research...
There is an "official solution" by Matlab:
just download the linked m-file
It shows that my idea was not that bad ;)
and for the record, my idea:
I think it's doable quite easily. I cannot present you some code yet, but I'll see what I can do. My idea is the following:
programatically create a new model
Add a Constant source block and a Terminator
add the Block you want to get to know the direct feedthrough ability in the middle
add_lines
run the simulation and log the states, which will give you the xout variable in the workspace.
If there is direct feedthrough the vector is empty, otherwise not.
probably you need to include some try/catch error catching for special cases
This way you can analyse a block for direct feedthrough by just migrating it to another model, without compiling your actual main model. It's not the fastest solution, but I can not imagine that performance matters that much for you.
Here we go, this script works fine for my examples:
function feedthrough = hasfeedthrough( input )
% get block path
blockinfo = find_system('simulink','Name',input);
blockpath = blockinfo{1};
% create new system
new_system('feed');
open_system('feed');
% add test model elements
src = add_block('simulink/Sources/Constant','feed/Constant');
src_ports = get_param(src,'PortHandles');
src_out = src_ports.Outport;
dest = add_block('simulink/Sinks/To Workspace','feed/simout');
dest_ports = get_param(dest,'PortHandles');
dest_in = dest_ports.Inport;
test = add_block(blockpath,'feed/test');
test_ports = get_param(test,'PortHandles');
test_in = test_ports.Inport;
test_out = test_ports.Outport;
add_line('feed',src_out,test_in);
add_line('feed',test_out,dest_in);
% setup simulation
set_param('feed','StopTime','0.1');
set_param('feed','Solver','ode3');
set_param('feed','FixedStep','0.05');
set_param('feed','SaveState','on');
% run simulation and get states
sim('feed');
% if condition for blocks like state space
feedthrough = isempty(xout);
if ~feedthrough
a = simout.data;
if ~any(a == xout);
feedthrough = ~feedthrough;
end
end
delete system
close_system('feed',1)
delete('feed');
end
When enter for example 'Gain' it will return 1, when you enter 'Integrator' it will return 0.
Execution time on my ancient machine is 1.3sec, not that bad.
Things you probably still have to do:
add another parameter, to define whether the block is continuous or discrete time and set the solver accordingly.
test some "extraordinary" blocks, maybe it's not working for everything. Also I haven implemented anything which could deal with logic, but actually the constant is 1 so it should work as well.
Just try out everything, at least it's a good base for you to work on.
A famous exception is the StateSpace Block which can have direct feedthrough AND states. But there are not sooo much standard blocks with this "behaviour". If you also have to deal with third party blocks you could get into some trouble, I have to admit that.
possible solution for the state space: if one compares xout with yout than one can find another indicator for direct feedthrough: if there is, the vectors are not equal. If so, than they are equal. Just an example, but I can imagine that it is possible to find more general ways to test things like that.
besides the added simout block above one needs the condition:
% if condition for blocks like state space
feedthrough = isempty(xout);
if ~feedthrough
a = simout.data;
if ~any(a == xout);
feedthrough = ~feedthrough;
end
end
From the documentation:
Tip
To determine if a block has direct feedthrough:
Double-click the
block. The block parameter dialog box opens.
Click the Help button in
the block parameter dialog box. The block reference page opens.
Scroll
to the Characteristics section of the block reference page, which
lists whether or not that block has direct feedthrough.
I couldn't find a programmatic equivalent though...
Based on a similar approach to the one by #thewaywewalk, you could set up a temporary model that contains an algebraic loop, similar to,
(Note that you would replace the State-Space block with any block that you want to test.)
Then set the diagnostics to error out if there is an algebraic loop,
If an error occurs when the model is compiled
>> modelname([],[],[],'compile');
(and you should check that it is the Algebraic Loop error that has occured), then the block has direct feed though.
If no error occurs then the block does not have direct feed though.
At this point you would need to terminate the model using
>> modelname([],[],[],'term');
If the block has multiple inports or outprts then you'll need to iterate over all combinations of them.