matlabideas

All things MATLAB. And Simulink.

GUIDE’ing Simulink with MATLAB

Introduction

Some of us Simulink users may find ourselves needing a graphical user interface (GUI) to run and interact with our dynamic simulation. For instance, we may need to modify block parameters or visualise results during the simulation, and not afterwards. Fortunately, you can.

Although Simulink does provide a programmable interface that you can call from MATLAB, this capability is rarely put into use (in fact, it is hardly even known by most users.) This article describes some of the ways in which you can utilise Simulink’s interface in MATLAB GUI.

Getting (Your Model) Started

If you look under Simulink > Functions in the Help Browser, you’ll notice that there is a huge list of functions available. You won’t be needing most of them, but knowing a few of these functions comes in handy at times.

Figure 1: List of Simulink Functions in Help Browser

Below are some of the functions that I use from time to time:

open_system(‘sys’)

Opens Simulink model

close_system(‘sys’)

Closes Simulink model

paramValue = get_param(object, paramName)

Gets properties of Simulink model or the blocks

set_param(object, paramName, Value)

Sets properties of Simulink model or the blocks
bdclose(‘sys’) Closes Simulink model unconditionally

As you can see, most of these functions are self-explanatory, and you may read about these functions from the help browser if you need more information on them. (The people at MathWorks have done a wonderful job putting up the help content, and I must admit that it’s quite a reliable answer source for most of my questions. Hence, we should all make good use of it.)

There are two functions that I would like to elaborate further: the get_param function and the set_param function. As you can tell, they are just two sides of the same coin. One allows you to get information from your model, and the other allows you to modify your model (assuming your model is already open.)

get_param

The get_param(object, paramName) function allows you to acquire information from your model. For example; if you want to check if you’re model is already running, you can type the following:

>> get_param(‘TestModel’,‘SimulationStatus’)

ans =

stopped

Likewise, the argument object also allows you to refer to the blocks within your model. For example; if you want to know the value of a manual switch (which changes between value of 1 and 0):


>> get_param(‘TestModel/Manual Switch’,‘sw’)

ans =

0

set_param

The set_param(object, paramName, Value)function allows you to modify parameters in your model. For example; you can change the simulation status with the following commands:

set_param(‘TestModel’,‘SimulationCommand’,‘start’)

set_param(‘TestModel’,‘SimulationCommand’,‘pause’)

set_param(‘TestModel’,‘SimulationCommand’,‘stop’)

Once again, it should be obvious what these commands will perform. The same can be done to Simulink blocks; you can change the block properties such as the sampling time, gain values, threshold, etc.

With this, you can easily interact with your model without touching your Simulink window, but through the command prompt or a script instead.

(Note: One of the common pitfalls with set_param and get_param is that when users have to work with numerical data, they tend to treat the parameter values as numerical data type, and this is incorrect. Simulink parameters should be treated as string types, and this applies to all numerical parameters such as ‘value’, ‘sampling time’, ‘frequency’, etc.)

Callback Functions

That should cover for most of us Simulink users. But sometimes we need more than just operating Simulink from MATLAB; can we call MATLAB functions from our Simulink environment? This could be useful, for instance, if we need to perform data analysis every time we finish running or when we pause our simulation. Another example would be when we want to load different parameter configurations for our model, and we have saved these configurations in different MAT-files.

We can automate these tasks using callback functions. There are two places where you can add callback functions: File>Model Properties if we want to specify callback functions for our model, or if we want to specify callback functions for some of the blocks, we can do so by going to the block properties.

Figure 2: Callback functions at Model Properties

Figure 3 Callback functions at Block Properties

As you can see, there are many different callback functions that you can introduce into your model. To use them, you just have to select on the desired callback function, and add in the MATLAB code that you would want to be executed. For instance, if I want to create a block that loads one of my models when I double-click on it, I can add in the following line in my OpenFcn callback:

open_system(‘myTestModel’)

If you want to know which callback to use, you may search for “Common Block Parameters” in the Help Browser and you should see the list of callback functions and the kind of situations that triggers their execution. I won’t delve into further details here, as I have seen some good articles floating around the web. Here is the link to a page which shows you how some of the more common callback functions can be put to use: http://www.mathworks.com/support/tech-notes/1800/1818.html

As for the others: Google is your friend. =)

Adding Event Listeners (For blocks)

You can add event listeners in your Simulink model so that when a block method executes, a MATLAB program is called to perform some task. The block events that you can register to are as follows:

‘PreDerivatives’

Before a blocks Derivatives method executes

‘PostDerivatives’

After a blocks Derivatives method executes

‘PreOutputs’

Before a blocks Outputs method executes.

‘PostOutputs’

After a blocks Outputs method executes

‘PreUpdate’

Before a blocks Update method executes

‘PostUpdate’

After a blocks Update method executes

One of the common use of the event listener is to interact with your MATLAB GUI in real time. For example, if you want to update your plot in sync with your simulation, you may do so with the event listener.

Below is a sample function that does the starts a Simulink model and adds the event listener that plots the output of the block ‘SineWave’:

function SampleFunction

ModelName = 'TestModel';

% Opens the Simulink model
open_system(ModelName);

% Simulink may optimise your model by integrating all your blocks. To
% prevent this, you need to disable the Block Reduction in the Optimisation
% settings.
set_param(ModelName,'BlockReduction','off');

% When the model starts, call the localAddEventListener function
set_param(ModelName,'StartFcn','localAddEventListener');

% Start the model
set_param(ModelName, 'SimulationCommand', 'start');

% Create a line handle
global ph;
ph = line([0],[0]);

% When simulation starts, Simulink will call this function in order to
% register the event listener to the block 'SineWave'. The function
% localEventListener will execute everytime after the block 'SineWave' has
% returned its output.
function eventhandle = localAddEventListener

eventhandle = add_exec_event_listener('TestModel/SineWave', ...
										'PostOutputs', @localEventListener);

% The function to be called when event is registered.
function localEventListener(block, eventdata)

disp('Event has occured!')
global ph;

% Gets the time and output value
simTime = block.CurrentTime;
simData = block.OutputPort(1).Data;

% Gets handles to the point coordinates
xData = get(ph,'XData');
yData = get(ph,'YData');

% Displaying only the latest n-points
n = 200;

if length(xData) <= n
	xData = [xData simTime];
	yData = [yData simData];
else
	xData = [xData(2:end) simTime];
	yData = [yData(2:end) simData];
end

% Update point coordinates

set(ph,...
	'XData',xData,...
	'YData',yData);

% The axes limits need to change as you scroll
samplingtime = .01;

%Sampling time of block 'SineWave'
offset = samplingtime*n;
xLim = [max(0,simTime-offset) max(offset,simTime)];
set(gca,'Xlim',xLim);
drawnow;

(Note: This is not meant to be a complete program. One thing that I did not show here is that you should also remove the listener using delete (eventhandle) when you have completed your simulation.)

Figure 4: TestModel

Figure 5: Live Update for your Plot

Gluing it together with GUIDE (Bringing it over in guide)

Knowing all of this code, you can easily build a GUI that interacts with your simulation model. The codes that I have mentioned above can be easily plugged into your GUI interface.

I do not intend to make this article a “How-to” for GUI, so you’ll have to read that out on your own. (At MATLAB’s command window, type ‘doc guide’and you should find all the details you need to get started.)

Below is a sample GUI that you can build fairly quickly:

Figure 6: Example GUI connected to Simulink

The example here is largely based on Phil Goddard’s submission: “Simulink Signal Viewing using Event Listeners and a MATLAB UI” in the MATLAB Central’s File Exchange. His example illustrates the integration of the MATLAB UI, Simulink model and a generic real time model using the event listeners. So if you want to find out more, here is the link: http://www.mathworks.com/matlabcentral/fileexchange/24294-simulink-signal-viewing-using-event-listeners-and-a-matlab-ui

“Tim Toady”: There is more than one way to do it

Like the old Perl adage, Simulink provides you a variety of options to interface with the MATLAB environment. It’s really up to you, the user, to decide for the right tool for the job. While the work you need to do is not going to be as straightforward as just plainly using Simulink, you know it’s worthwhile when you need it. 😉

End of the Article:

Article by Tan Yu Ang, Application Engineer

13 responses to “GUIDE’ing Simulink with MATLAB

  1. Eyad July 31, 2012 at 4:42 pm

    hi
    your program is very helpful but i’m facing a problem . i use two listeners in my GUI and when i try to plot them they are always plotted on the same axes ( the last axes in the GUIis there a way to specify which axes to plot the data ?

    Like

    • matlabideas August 2, 2012 at 2:07 pm

      Hi Eyad,

      MATLAB plots on the last active axis. To plot on separate axes, you need to select before you plot.

      For instance, if you have two axes on the GUI (axes1 and axes2):
      axes (handles.axes1); plot(data1);
      axes (handles.axes2); plot(data2);

      Hope that helps. 😉

      Like

  2. Eyad August 2, 2012 at 5:25 pm

    the problem was that i didn’t pass the handles to the function I added the following to the LocalEventListener function
    hFigure = sample_gui();
    handles = guidata(hFigure)
    and now it works fine but there’s another problem when i tried to build the model on a realtime machine when i start the model it gives an error can’t find function “localAddEventListener”
    I hope you can help me with with that problem

    Like

  3. Eyad August 7, 2012 at 5:39 pm

    what I mean by a realtime machine is XPC target box
    I made a model and in it’s startfcn callback I put ‘localAddEventListener’
    the error appears when i try to build the model it can’t find the function localAddEventListener
    I built the gui with guide tool
    and here’s the program for it’s callbacks

    function varargout = sample_gui(varargin)
    % SAMPLE_GUI M-file for sample_gui.fig
    % SAMPLE_GUI, by itself, creates a new SAMPLE_GUI or raises the existing
    % singleton*.
    %
    % H = SAMPLE_GUI returns the handle to a new SAMPLE_GUI or the handle to
    % the existing singleton*.
    %
    % SAMPLE_GUI(‘CALLBACK’,hObject,eventData,handles,…) calls the local
    % function named CALLBACK in SAMPLE_GUI.M with the given input arguments.
    %
    % SAMPLE_GUI(‘Property’,’Value’,…) creates a new SAMPLE_GUI or raises the
    % existing singleton*. Starting from the left, property value pairs are
    % applied to the GUI before sample_gui_OpeningFcn gets called. An
    % unrecognized property name or invalid value makes property application
    % stop. All inputs are passed to sample_gui_OpeningFcn via varargin.
    %
    % *See GUI Options on GUIDE’s Tools menu. Choose “GUI allows only one
    % instance to run (singleton)”.
    %
    % See also: GUIDE, GUIDATA, GUIHANDLES

    % Edit the above text to modify the response to help sample_gui

    % Last Modified by GUIDE v2.5 29-Jul-2012 11:28:58

    % Begin initialization code – DO NOT EDIT
    gui_Singleton = 1;
    gui_State = struct(‘gui_Name’, mfilename, …
    ‘gui_Singleton’, gui_Singleton, …
    ‘gui_OpeningFcn’, @sample_gui_OpeningFcn, …
    ‘gui_OutputFcn’, @sample_gui_OutputFcn, …
    ‘gui_LayoutFcn’, [] , …
    ‘gui_Callback’, []);
    if nargin && ischar(varargin{1})
    gui_State.gui_Callback = str2func(varargin{1});
    end

    if nargout
    [varargout{1:nargout}] = gui_mainfcn(gui_State, varargin{:});
    else
    gui_mainfcn(gui_State, varargin{:});
    end
    % End initialization code – DO NOT EDIT

    % — Executes just before sample_gui is made visible.
    function sample_gui_OpeningFcn(hObject, eventdata, handles, varargin)
    % This function has no output args, see OutputFcn.
    % hObject handle to figure
    % eventdata reserved – to be defined in a future version of MATLAB
    % handles structure with handles and user data (see GUIDATA)
    % varargin command line arguments to sample_gui (see VARARGIN)

    % Choose default command line output for sample_gui
    handles.output = hObject;

    % Update handles structure
    guidata(hObject, handles);

    % UIWAIT makes sample_gui wait for user response (see UIRESUME)
    % uiwait(handles.figure1);

    % — Outputs from this function are returned to the command line.
    function varargout = sample_gui_OutputFcn(hObject, eventdata, handles)
    % varargout cell array for returning output args (see VARARGOUT);
    % hObject handle to figure
    % eventdata reserved – to be defined in a future version of MATLAB
    % handles structure with handles and user data (see GUIDATA)

    % Get default command line output from handles structure
    varargout{1} = handles.output;

    % — Executes on button press in pb1.
    function pb1_Callback(hObject, eventdata, handles)
    % hObject handle to pb1 (see GCBO)
    % eventdata reserved – to be defined in a future version of MATLAB
    % handles structure with handles and user data (see GUIDATA)

    cla(handles.axes2)
    cla(handles.axes3)

    set_param(bdroot,’simulationcommand’,’start’);
    status=get_param(bdroot,’simulationstatus’);
    set(handles.txt1,’String’,status);

    global ph;
    ph(1) = line([0],[0]);
    ph(2) = line([0],[0]);

    function eventhandle= localAddEventListener
    eventhandle{1}=add_exec_event_listener(‘simple_model/Gain’,’PostOutputs’,@localEventListener)
    fprintf(‘!!!!!!!!!!!!!!!!!!!!!!!!!!!!!listener!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!’)

    eventhandle{2}=add_exec_event_listener(‘simple_model/Sine Wave’,’PostOutputs’,@localEventListener2)
    fprintf(‘!!!!!!!!!!!!!!!!!!!!!!!!!!!!!listener2!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!’)

    function localEventListener(block, eventdata)
    hFigure = sample_gui();
    handles = guidata(hFigure);

    %disp(‘Event has occured’)
    global ph;

    simTime = block.CurrentTime;
    simData = block.OutputPort(1).Data;
    xData = get(ph(1),’XData’);
    yData = get(ph(1),’YData’);
    n=20000;
    if length(xData)<= n
    xData=[xData simTime];
    yData=[yData simData];
    else
    xData=[xData(2:end) simTime];
    yData=[yData(2:end) simData];
    end
    %plot(handles.axes2,xData,yData)

    set(ph(1),'XData',xData,'YData',yData);
    plot(handles.axes3,ph(1).XData,ph(1).YData,'r')

    function localEventListener2(block, eventdata)

    hFigure = sample_gui();
    handles = guidata(hFigure);
    %disp('Event has occured')
    global ph;

    simTime = block.CurrentTime;
    simData = block.OutputPort(1).Data;
    %plot(handles.axes2,simTime,simData)
    xData = get(ph(2),'XData');
    yData = get(ph(2),'YData');
    n=20000;
    if length(xData)<= n
    xData=[xData simTime];
    yData=[yData simData];
    else
    xData=[xData(2:end) simTime];
    yData=[yData(2:end) simData];
    end
    %plot(handles.axes3,xData,yData)

    set(ph(2),'XData',xData,'YData',yData);
    plot(handles.axes2,xData,yData,'r')

    % — Executes on button press in pb2.
    function pb2_Callback(hObject, eventdata, handles)
    % hObject handle to pb2 (see GCBO)
    % eventdata reserved – to be defined in a future version of MATLAB
    % handles structure with handles and user data (see GUIDATA)
    set_param(bdroot,'simulationcommand','stop');
    status=get_param(bdroot,'simulationstatus');
    set(handles.txt1,'String',status);

    % — Executes during object creation, after setting all properties.
    function txt1_CreateFcn(hObject, eventdata, handles)
    % hObject handle to txt1 (see GCBO)
    % eventdata reserved – to be defined in a future version of MATLAB
    % handles empty – handles not created until after all CreateFcns called
    status=get_param(bdroot,'simulationstatus');

    set(hObject,'String',status);

    % — Executes during object creation, after setting all properties.
    function txt2_CreateFcn(hObject, eventdata, handles)
    % hObject handle to txt2 (see GCBO)
    % eventdata reserved – to be defined in a future version of MATLAB
    % handles empty – handles not created until after all CreateFcns called

    %status=get_param(bdroot,'simulationstatus');
    %while strcmp(status,'running')
    %time=get_param(bdroot,'simulationtime')
    %set(hObject,'String',time);
    %wait(1000)
    %end

    % — Executes on button press in pb3.
    function pb3_Callback(hObject, eventdata, handles)
    % hObject handle to pb3 (see GCBO)
    % eventdata reserved – to be defined in a future version of MATLAB
    % handles structure with handles and user data (see GUIDATA)

    time1=get_param(bdroot,'simulationtime');
    set(handles.txt2,'String',time1);

    % — Executes on slider movement.
    function slider1_Callback(hObject, eventdata, handles)
    % hObject handle to slider1 (see GCBO)
    % eventdata reserved – to be defined in a future version of MATLAB
    % handles structure with handles and user data (see GUIDATA)

    % Hints: get(hObject,'Value') returns position of slider
    % get(hObject,'Min') and get(hObject,'Max') to determine range of slider
    slider_position = get(hObject,'Value');
    value = num2str(slider_position);

    % Update the model's gain value
    set_param([bdroot '/Gain'],'Gain',value);
    %x=get_param(workspace,'txt3');
    %set(handles.txt3,'String',yout);

    % — Executes during object creation, after setting all properties.
    function slider1_CreateFcn(hObject, eventdata, handles)
    % hObject handle to slider1 (see GCBO)
    % eventdata reserved – to be defined in a future version of MATLAB
    % handles empty – handles not created until after all CreateFcns called

    % Hint: slider controls usually have a light gray background.
    if isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
    set(hObject,'BackgroundColor',[.9 .9 .9]);
    end

    % — Executes on button press in pb4
    function pb4_Callback(hObject, eventdata, handles)
    % hObject handle to pb4 (see GCBO)
    % eventdata reserved – to be defined in a future version of MATLAB
    % handles structure with handles and user data (see GUIDATA)
    x=evalin('base','a')
    y=length(x)
    set(handles.txt3,'String',x(y,1));

    % — Executes on key press with focus on pb3 and none of its controls.
    function pb3_KeyPressFcn(hObject, eventdata, handles)

    % hObject handle to pb3 (see GCBO)
    % eventdata structure with the following fields (see UICONTROL)
    % Key: name of the key that was pressed, in lower case
    % Character: character interpretation of the key(s) that was pressed
    % Modifier: name(s) of the modifier key(s) (i.e., control, shift) pressed
    % handles structure with handles and user data (see GUIDATA)

    % — Executes on button press in pb5.
    function pb5_Callback(hObject, eventdata, handles)
    % hObject handle to pb5 (see GCBO)
    % eventdata reserved – to be defined in a future version of MATLAB
    % handles structure with handles and user data (see GUIDATA)

    time=evalin('base','b.time'); %the variable name is b type structure
    bb=evalin('base','b.signals.values');
    plot(handles.axes1,time,bb);

    xlabel(handles.axes1,'Time');
    ylabel(handles.axes1,'Signal Value');
    title(handles.axes1,'Signal Value v''s Time');
    grid(handles.axes1,'on');
    box(handles.axes1,'on');

    % handles.realtimedata
    % plot(handles.axes2,handles.realtimedata);
    %
    % xlabel(handles.axes2,'Time');
    % ylabel(handles.axes2,'Signal Value');
    % title(handles.axes2,'Signal Value v''s Time');
    % grid(handles.axes2,'on');
    % box(handles.axes2,'on');

    % cc=evalin('base','c.signals.values');
    % plot(handles.axes2,time,cc,'r');
    %
    %
    % xlabel(handles.axes2,'Time');
    % ylabel(handles.axes2,'Signal Value');
    % title(handles.axes2,'Signal Value v''s Time');
    % grid(handles.axes2,'on');
    % box(handles.axes2,'on');

    % — Executes during object deletion, before destroying properties.
    function axes1_DeleteFcn(hObject, eventdata, handles)
    % hObject handle to axes1 (see GCBO)
    % eventdata reserved – to be defined in a future version of MATLAB
    % handles structure with handles and user data (see GUIDATA)

    % — Executes during object creation, after setting all properties.
    function axes2_CreateFcn(hObject, eventdata, handles)
    % hObject handle to axes2 (see GCBO)
    % eventdata reserved – to be defined in a future version of MATLAB
    % handles empty – handles not created until after all CreateFcns called

    % Hint: place code in OpeningFcn to populate axes2

    % — Executes during object deletion, before destroying properties.
    function axes3_DeleteFcn(hObject, eventdata, handles)
    % hObject handle to axes3 (see GCBO)
    % eventdata reserved – to be defined in a future version of MATLAB
    % handles structure with handles and user data (see GUIDATA)

    Like

  4. Eyad August 16, 2012 at 2:32 pm

    any ideas guys ?

    Like

  5. Eyad August 23, 2012 at 2:26 am

    no i didn’t

    Like

  6. Nelle May 7, 2013 at 9:10 am

    Hi friends, its great paragraph regarding tutoringand
    entirely explained, keep it up all the time.

    Like

  7. Ehtisham Safdar January 31, 2015 at 8:40 pm

    Hello there, I am really thankful to you for sharing such an article. It works fine and the simulation runs at the normal speed as long as I work with the same model that you have presented but when I apply the same concept for acquiring the data from a National Instrument DAQ Device my application slows down a lot and it takes ages to complete the 15 sec of data acquisition. I figured out by doing some hit and trials that the application runs fine when i lower the sampling rate to 20 samples per seconds which is currently 2000 samples per second. By lowering down the sample rate I lose a huge amount of required data. Please suggest any good solution for this.
    Waiting for your prompt response.

    Like

    • matlabideas February 1, 2015 at 4:36 pm

      Hey there.

      Simulink environment is never designed for real-time applications. For real-time applications, you should look at the xPC Target extension or third party products such as Quanser’s QUARC RT.

      Normally, if I were to write a real time applications, I’d just stick to MATLAB and the DAQ’s API. Most DAQs have C-APIs which offer better control over your data acquisition, for example maybe an access to an internal circular buffer. At the risk of being Captain obvious: it works like this: the device uses 2 or more buffers for a single channel. When buffer1 is filled up with acquired samples, you can load the data and refresh your plot while the sampling continuous uninterrupted, only switched to the next buffer in queue (buffer2) and so on. Even then, you shouldn’t have to refresh the plot at 20 kHz (our computer screens refresh at 60Hz at most, so most of the work done is not visible anyway.)

      You could also implement a similar circular buffer within MATLAB (or Simulink, for that matter), but expect some delays between scans. This is the easiest way to do it if real time isn’t so critical that you can’t miss a fraction of a second. Having said that, I personally think this approach should be avoided unless the real time limitations are properly documented.

      HTH

      Like

    • Koen Vermue December 19, 2016 at 8:12 am

      Hi all,
      Thanks for all the detailed explaining.
      I have been building my own GUI, based upon the example of Phil Goddard’s, (http://www.mathworks.com/matlabcentral/fileexchange/24294-simulink-signal-viewing-using-event-listeners-and-a-matlab-ui). The main difference between his ans my work concerns the size of the simulink model. I get into trouble very quickly with the ability to simulation it in realtime (already after adding 6 event listeners). Before adding the event listeners for the communication between my matlab GUI and simulink model, it did run very quickly (<0.0005s sampletime). Now afterwards, it is not able to achieve 0.05s sampletime… A bit of overhead is okay but this seems to much, which makes me doubt about my implementation. Are there more engineers out there seeing the same thing? How did you solve it? Are there some rules to keep in mind while using the eventlistener-method for keeping simulation realtime?

      Thanks in advance!!!

      KV

      Like

Leave a comment