I'm having serious trouble debugging the following Matlab Warning:
Warning: Ignoring excess mask dialog entries in:
(path to block under mask of block of Simulink model I'm running)
Does anybody know what it even means? What are "mask dialog entries"?
It means that the block saved in your .mdl file has too many parameters saved in the MaskValueString parameter. This shouldn't happen during normal use, but it can happen if you directly do a set_param the MaskValueString parameter on the masked block instead of using the dialog, and you end up setting more values than there are parameters. Simulink will just ignore all of the extra parameters in this case.
I think if you resave the model that the masked block lives in, the warning should go away. Just make sure your block has the right parameter values on the dialog.
I'm not absolutely sure, but I suspect that it means that you've got too many attributes defined in your block mask?
Is the mask particularly complex?
You could examine the mask definition by right clicking on the block and selecting "edit mask" - which will bring up the mask editor, and allow you to examine what attributes of the block are being defined via its mask.
Or I could be completely wrong....
Related
I am using Simulink to model a waste recycling plant out of a number of masked blocks that I created, representing sorting steps, buffers etc. Each module (that is, a masked block) has a failure probability, modeled using Discrete Events. If a failure event occurs, a triggered subsystem calls an Interpreted Matlab Function ("outside" of simulink). This function is supposed to set a parameter status of the masked block representing the module that failed as well as the upstream modules' status to 0 (because obviously, everything upstream has to stop as well or the material will just pile up).
`set_param(gcb, 'status', num2str(status));
PortConnectivity = get_param(gcb,'PortConnectivity');
sources = PortConnectivity.SrcBlock;`
Basically, this will be looped until I reach a block with no own Source Block.
This all works quite well, except for one problem: The gcb command gives me the block path to the last block I highlighted manually, and not to the block that called the Interpreted Matlab function. Is there any way to get the calling block's handle (which I would use with it's Parents parameter to access the Mask's status)? (A similar question has been asked here, with no results...)
I hope you get my problem - I'll be happy to elaborate if anything's unclear; I am not claiming to be a Simulink expert, so sorry for maybe using wrong terminology.
Ok, for everyone stumbling upon this:
For the mask that contains the caller of the Matlab Interpreted Function, in the mask editor I define a parameter 'this_block' (turn visibility off), that I initialize in the Initialisation pane using
parent = get_param(gcb,'Parent');
set_param(gcb, 'this_block','Parent')
Since this masked block (responsible for modelling the failure and its upstream communication) is itself used in another masked block also present in the library (responsible for modeling the module's behaviour), I also had to check "Allow library blocks to modify it's contents" in the mask editor Inititlization pane of the parent's mask. The parameter 'this_block' is then handed over as one of the input arguments of the called function (in my case, status_communication(u, this_block)).
I am trying to amend the example given here for creating a dynamic masked subsystem, where I want to dynamically change the number of imports and outports to an S-Function.
I have a very simple S-Function implemented in C (it's the timestwo example in the documentation) and for which I wish the user to be able to define the number of inputs and number of outputs in a mask. The intention is then, within the S Function, to manipulate the received input values and write to the output values. The S-Function will eventually do some quite complicated stuff and I need multiple instances of it in Simulink, hence why I want it defined in a library.
I have put the S-Function into a library and unlocked it by choosing Diagram->Unlock Library.
I have defined 2 variables, numInports and numOutports in the Parameters & Dialog pane of the mask editing window.
I then add the following to the Initialization pane:
blocks = find_system(gcb,...
'LookUnderMasks','on',...
'FollowLinks','on',...
'RegExp', 'on',...
'BlockType', 'port');
if ~isempty(blocks)
Simulink.SubSystem.deleteContents(gcb);
end
for n=0:(numInports - 1)
label = sprintf('/In%d', n);
add_block('built-in/Inport',[gcb,label]);
end
for n=0:(numOutports - 1)
label = sprintf('/Out%d', n);
add_block('built-in/Outport',[gcb,label]);
end
The intention is for the initialisation to delete all imports and outports when the parameters are changed, then recreate them. I then save the model within the library.
The find_system() command should find and delete all blocks with port in the type, as suggested here and here.
I have created a model that uses this library model S Function implementation. However, when I update the parameters, I get the error:
Error in 'MyModel/MyLibrarySFunction': Initialization commands cannot be evaluated. Caused by:
A new block named 'MyModel/MyLibrarySFunction/In0' cannot be added.
Can anybody please advise what is going wrong here?
EDIT:
The documentation for find_system() has all as a valid parameter value, not the on I used and which was in the documentation example, but this seems to have no effect when I change it. I added:
msg = sprintf('Num blocks: %d', numel(blocks));
disp(msg);
just after the find_system() call and get 0 for the number of blocks found, so I guess the problem may be that In0 is not deleted and hence I am trying to reinsert it.
There is a subsystem in my model called 'addBlock'. Inside it, I generate InPorts during Mask Initialization based on the number of inputs that the user specifies. For example, if the user says there are going to be six blocks connecting to this subsystem, I generate 6 input ports.
Now, say I specified six inputs. The first time I double click the block and specify this it creates 6 inputs. However, if I double click the mask again and hit OK, it creates 6 more inputs numbered 7 through 12.
What I would thus like to do is to delete everything within the subsystem every time I open the mask and start creating blocks from scratch. Is there any way of getting a list of every block that exists within a subsystem?
Thanks in advance.
I found the answer for this, in case anyone in the future looks it up. The method is to use
Simulink.SubSystem.deleteContents(gcb);
The gcb bit returns the name of the current block, which would be the block you want anyway because you're in that block's mask. Also, note the different camelCases. The solution is a bit inelegant because the whole subsystem needs to be created from scratch, but it does the job.
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.
The Gain block and continuous block in Simulink require the user to specify a gain. This can be a workspace variable. But I want to vary this gain during runtime. I can't seem to get a solution for this. This idea is simple but I can't believe it is so difficult to implement.
I have tried using another block to write to workspace, but found out that the 'to workspace' block only writes to the workspace after the simulation ends or pauses.
I can store the variable in a data memory block, but I don't know how to specify the gain value(s) for the gain/PID block in this case.
If you have Inline Parameters turned off (it's on the Optimization page of the Configuration Set), you can just open the gain block dialog and change the value. If you want to use a workspace variable, then you can change the value of the workspace variable and do an Update Diagram (^D) while the simulation is running.
There's also a block called the Slider Gain which allows you to change the gain value using a slider UI.
May be it'd be helpful at some point: try using the MATLAB Function Block (Matlab user-defined function that can be used directly in Simulink).
As a command-line alternative, you can use the SET_PARAM function to change the Gain value of the block during model simulation.
For example, the following code would change the Gain value of a block named "My Gain" at the top level of a model called "my_model.mdl" to a value of 20:
set_param('my_model/My Gain','Gain','20');
Note, however, that only Tunable Parameters can be changed with SET_PARAM at runtime.