Guy and Seth on Simulink

Mask Initialization and Self-Modifying Blocks 16

Posted by Seth Popinchalk,

In previous posts, I introduced advanced masking concepts and discussed how to build a masked library block with a dynamic mask dialog.   In this post, I will show how the example Saturation block adds/deletes ports and rewires itself depending on its configuration.

The Saturation Block Example

Animation of the saturation block mask.

After configuring the block dialog, clicking Apply or OK executes the mask initialization callback.  The mask initialization callback is where most of the work for a mask happens.  Mask initialization commands should take the parameter values set in the mask dialog and configure the block so it is ready to run.  In the Saturation block example, the block is switching between two basic configurations, the Dynamic Saturation and the Fixed Saturation.

Saturation blocks using constants and ports

The difference between the configurations is the type of block used for up and lo.  They are ports to provide dynamic limits, and constants to provide fixed limits.

Key point: do the least amount of work that you can in the mask initialization.

Mask initialization code should do the minimum amount of work that it can because mask initialization runs many times in the life of a model.  In addition to running when you click OK or Apply, mask initialization runs at the start of every simulation and update diagram, when you call set_param to modify the block, and when you are building the model as you drop the block into the system.

The mask parameters are the variable names set on the parameters page of the mask editor. (See below)

Saturation block mask editor parameters

Blocks in the system under the mask can access these variables in the mask workspace.  Initialization commands also run in the mask workspace, so these variables are part of the mask initialization callback. (see below)  If a block will rewire itself, or add ports, you must check Allow library block to modify its contents.

Mask editor initialization page

For the saturation block, I chose to call an M-function to do the work of the initialization command.  I find it is more convenient to debug and the MATLAB editor is a more comfortable development for mask initialization commands that are more than a few lines.

Use the state of the mask GUI to control the code

My function is saturation_init_cb.  I pass into the function all the variables it needs from the mask workspace.  This is more efficient than calling get_param on the block.  I always pass in the result of gcb (get pathname of current block).  I will use this path when I need to reference the blocks inside the saturation block subsystem.

In order to do the least amount of work, my mask initialization checks the system to see if changes are needed.  The check for the upper limit source runs through the switch statement to handle the two possible values, internal or external.  The code then checks for the BlockType of the saturation/up block.  If it is not the right type, we call the local replace function to replace the block.  If we have added a constant, we set the Value of that constant to use the uplim variable from the mask.  A similar action is repeated for the lower limit.

% saturation_init_cb Mask Initialization
function saturation_init_cb(blk,uplimsrc,uplim,...
                                lowlimsrc,lowlim)
 
% Check for upper limit source
switch uplimsrc
    case 'external'
        % Check for constant
     if strcmp(get_param([blk '/up'],'BlockType'),...
                                         'Constant')
            replace([blk '/up'],'built-in/Inport');
        end
    case 'internal'
        % Check for inport
     if strcmp(get_param([blk '/up'],'BlockType'),...
                                           'Inport')
            replace([blk '/up'],'built-in/Constant')
            set_param([blk '/up'],'Value','uplim')
        end
end
 
% Check for lower limit source
switch lowlimsrc
    case 'external'
        % Check for constant
     if strcmp(get_param([blk '/lo'],'BlockType'),...
                                         'Constant')
            replace([blk '/lo'],'built-in/Inport')
        end
    case 'internal'
        % Check for inport
     if strcmp(get_param([blk '/lo'],'BlockType'),...
                                           'Inport')
            replace([blk,'/lo'],'built-in/Constant')
            set_param([blk '/lo'],'Value','lowlim')
        end
end
 

The replace function gets the position and orientation from the old block, deletes it and then adds the new block in its place.

% Local replace function
function replace(oldblock,newblock)
pos = get_param(oldblock,'Position');
orient = get_param(oldblock,'Orientation');
delete_block(oldblock);
add_block(newblock,oldblock,'Position',pos,...
    'Orientation',orient);
 

Note, the replace_block function in Simulink could not be used here because it is meant for model wide changes.  While it is possible to limit the affect of replace_block to a specific system, replace block doesn’t work on library blocks.   Self-modifiable masked blocks are library blocks, so this is a common helper function used for this kind of mask.

Renumbering ports to control the order

The port number affects the order that the ports show up on the outside of the block.  Wires cross the boundary of the block and remain connected through the inport that they are originally connected to.  A port can be inserted before or after existing ports on the block by changing the numbering of all ports.  The following code sets the port numbers by checking the values of uplimsrc and lowlimsrc.  When the upper limit source is external, that will be the first port.  If not, the first port is the u input.  I can keep track of the order and number of the ports by incrementing the numbering variable each time I set a port number.

% Renumber ports
% when using external upper limit,
% set blk/up port to 1

n = 1;
if strcmp(uplimsrc,'external')
    set_param([blk '/up'],'Port',num2str(n))
    n = 2; % increase n
end
 
% set u port to n
set_param([blk '/u'],'Port',num2str(n))
 
% when using external lower limit,
% set blk/lo port to n+1

if strcmp(lowlimsrc,'external')
    set_param([blk '/lo'],'Port',num2str(n+1))
end
 

Now it’s your turn

I have shared some of my best practices for programming self-modifying blocks.  What techniques have you used to program masks? Share your comments here.

16 CommentsOldest to Newest

I wonder how it is possible to define initial values for the parameters in the mask. for example your values “1″ and “-1″ for the upper and lower limit. how do you do this? when i define a parameter as ‘uplim = 1′ in the initialization window of the mask editor it still remains 0 when starting the model.

TIA,
Kai

@Kai – The initial value will be the last one you entered into the library block mask. When you work in the mask editor, all your parameters are initialized to 0, or the first option in a popup list. After you have completed designing the mask, close the mask editor, and while the library is still unlocked, set the value in the mask. Save the library, and this is now your default value. The next time you drag that block into your model, that initial value will be your parameter value.

Hi Seth,

Great graphics you got here. I especially like the first one, cool animated picture! I”m not a big simulink user, but I like the way you presented your information. Love the graphics.

Quan

I have used configurable subsystems in my library to provide a similar capability – one block provides multiple variations of basically the same functionality. The drawback with my approach is that the input ports are present whether they are used or not. It seems that this approach could provide similar functionality with a much cleaner finished model.

Can the two techniques be combined – i.e., can I update my configurable subsytems to remove unused inputs via self-modification without breaking all my existing models that use those blocks?

@Quan – Thanks for the compliment!

@Jim – The two methods can be combined. If you have large structural changes in your block algorithm, the configurable subsystem can be used to switch between them. It may be even easier to simply delete one block and replace it with the other, and then wire the ports appropriately.

Seth, I’m reading your post on self modifying blocks with great interest. I’d like to create a subsystem with a variable number of inputs, but am a novice at programming in simulinkese. My subsystem contains a mux to which the inputs will be connected. My mask for the subsystem will prompt for the number of inputs. So, since the new number of inputs may be more or less than the current number, I’m guessing I should start by removing all input ports and connectors from the input ports. I’m not sure how to find them however. Then I guess I would create new input ports, and sequentially connect them to the mux. I think I know how to do that. Any help you can provide would be great.

@Hans – I suggest that you aim to do the minimum work required to update the mask. Start by finding the existing inports:

s = find_system(gcb,’BlockType’,'Inport’)

Then delete some number of ports if you have too many, or add ports if you have too few. MaskInitialization code is called during many different operations. Every time you start the simulation, your block should merely check that the state of the blocks inside it match the values of the parameters in the mask. Update diagram can also happen DURING simulation (think, Pause and Restart). If your code just deletes all the ports, this will not be allowed. Good luck on making your mask.

I’ve created a simular subsystem. My problem is, that all connection lines are shifted, eyery time I open my modell or I want to simulate it. There are no connection to the Subsystem when I open it.
Any Idea?

@Jens – In situations where blocks end up disconnected I usually suspect that initialization code is deleting lines or blocks or both. Try to write conditional code to only delete the block if it needs to be replaced. If this doesn’t help, contact technical support and they may be able to help find the reason why.

Seth hello,

In continuation to @Jens,
I use self-modifying-blocks to show/hide my block’s neutral point. In order to do so I use replace_block() in the following manner:

replace_block(gcb,’Name’,'NP’,'built-in/terminator’)

The problem is the new block (terminator) appears in a 180 deg rotation and disconnected form the orginal wire.
Any suggestion?

Haven’t noticed your comment on replace_block().
I’ve managed to construct my own self-modifying-block and placed it in a library.
To check whether changes are needed, my initialization checks for existing of specific block in the following manner:

if isempty(find_system(blk,’LookUnderMasks’,'all’,…
‘MaskType’,'Series RLC Branch’,…
‘Name’,'L-A’))

I can’t use your check (get_param()) since when the block is missing I get an error due to reference to a non-existing block.

The thing is, when I test the block in my library all works well. It is when I locate the block into my model and test it that troubles are appearing. After some testing I’ve found that the find_system() command provides me with an empty matrix:

K>> find_system(blk,’LookUnderMasks’,'all’,…
‘MaskType’,'Series RLC Branch’,'Name’,'L-A’)

ans =

Empty cell array: 0-by-1

Any idea why?

@K(11) – it seems both ‘LookUnderMasks’ and ‘FollowLinks’ should be active to find signals in library blocks and in masked subsystems.

Hi,

I’ve a Simulink model named ‘example.mdl’ with parallel RLC branch. Branch Type is R, variable of resistance is ‘res’. How can I set value of resistance in GUIDE with set_param?

Hi Seth,

Thanks for all of your very nice tutorials.

I have created my own self modifying blocks on simulink, and it works fine.
My problem comes when I create a library with these self modifying blocks.
As I drag the block from my own library to my model, the block is still connected to the library, and it can’t make structural change (it is not anymore self modifying). I can manually disable the link with the library (Link options > Disable Link).
But I would like that this “disabling” would be automatic.
I tried to “set_param(gcb, ‘LinkStatus’, ‘inactive’)” in the initialization of my libraries blocks but then when I run my simulation, it seems to create big issues.
Do you have any ideas in order to deal with it ?

@Philippe – You will need to set your masked block to be self modifiable in the library. You can do this with:

set_param(blk,'MaskSelfModifiable','on')

Hi Seth, thanks for all your help in your tutorials.

This is my situation. I have a similar Problem than Philippe. I’m creating a masked Subsystem that includes basically Simulink blocks, SimPowerSystems blocks and Matlab functions. According to one masked parameter, I should add or delete blocks to the main structure, so I’m using the instruction Simulink.SubSystem.deleteContents(blk) to delete the whole Subsystem, and create it again with the code I write in the Initialization Pane of the mask (the structure could be huge so i think it’s easier to do it in that way).
My problem comes when I try to connect the blocks using add_line. Everything works fine if I change the parameter in the unlocked library (I get the number of blocks according to this parameter and they connect each other fine), but when I add my block to a new model, and I change this parameter, i get something like : ‘Initialization commands cannot be evaluated. –> The Destination port already has a line connection”. But if I comment the code about add_line, everything works perfect, obviously without the line connections, so it seems the problem is the add_line instruction. Any idea about where could be the problem? Is there some limitation about which changes could you do in a self-modifying block from a library?

Thanks in advance

Add A Comment

What is 2 + 7?

Preview: hide

These postings are the author's and don't necessarily represent the opinions of MathWorks.