Code covered by the BSD License  

Highlights from
Simulink Signal Viewing using Event Listeners and a MATLAB UI.

image thumbnail

Simulink Signal Viewing using Event Listeners and a MATLAB UI.

by

 

28 May 2009 (Updated )

This demo shows how to use block listeners to view model signals in a MATLAB user interface.

Editor's Notes:

This file was selected as MATLAB Central Pick of the Week

simpleGUI
function varargout = simpleGUI
% This function creates a simple user interface for running a Simulink
% model and displaying signals in the model on a MATLAB user interface.
%
% Specifically the UI works with a model called 'simpleModel.mdl', that
% contains the three blocks
%
%                    Sine Wave --> Gain --> Scope
%
% The UI allows the model to be started and stopped, and allows the value
% of the gain to be tuned.  The model does not have to be open to use the
% UI (and it's recommended for it to be closed).
%
% The UI allows the model to be run in either simulation mode (requiring a
% Simulink license) or as a generic real-time (GRT) executable (since the
% model must be "built" this requires an RTW license).
%
% In Simulation Mode: The value of both the signal being fed into the
% Gain block and the signal being fed into the Scope block are displayed on
% an axis on the UI. 
% In GRT/External Mode: Only the signal being fed into the scope is
% displayed.  This is because External Mode only allows data from
% certain types of blocks to be uploaded.  In this model the only
% block that is the Scope block.
%
% It is intended as a demonstration program to show various aspects of 
% using MATLAB, Simulink and RTW:
% 
%   - how to create a MATLAB UI using command line functionality
%   - how to start/stop a Simulink model using command line functionality
%   - how to add a listener to a Simulink block so that signals can be
%   viewed from a MATLAB UI.
%   - how to build a GRT executable using command line functionality
%   - how to interface with code running in "real-time" (For the purposes
%   of this UI the grt code is running on the host machine, so it is not
%   running in hard real-time, however it is using External Mode to
%   communicate with the code and hence shows how communication would be
%   performed if the code was truly running on an RTOS.
%
% NOTE: there are many different ways of creating a UI that talks
% to real-time code, and the appropriate way will depend on the exact
% functionality required, the RTOS, the hardware, the type of communication
% mechanism being used, and any API (application program interface) that is
% available.
%
% This code is not intended to be "bullet-proof", nor comprehensive.  It is
% by its nature a very simple application.

% Author: Phil Goddard (phil@goddardconsulting.ca)
% Date: Q4, 2009
% Version: 3.0  (If updated/changed, then also change the "About Box" info
%                in the localAboutPulldown function.)
% MATLAB version: R2008b
% Revision notes: Versions prior to 3.0 only displayed the Scope's input
%                 signal, not the Gain's input signal too.

% This UI hard codes the name of the model that is being controlled
modelName = 'simpleModel';
% Do some simple error checking on the input
if ~localValidateInputs(modelName)
    estr = sprintf('The model %s.mdl cannot be found.',modelName);
    errordlg(estr,'Model not found error','modal');
    return
end
% Do some simple error checking on varargout
error(nargoutchk(0,1,nargout));

% Create the UI if one does not already exist.
% Bring the UI to the front if one does already exist.
hf = findall(0,'Tag',mfilename);
if isempty(hf)
    % Create a UI
    hf = localCreateUI(modelName);
else
    % Bring it to the front
    figure(hf);
end

% populate the output if required
if nargout > 0
    varargout{1} = hf;
end

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Function to create the user interface
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function hf = localCreateUI(modelName)

try
    % Create the figure, setting appropriate properties
    hf = figure('Tag',mfilename,...
        'Toolbar','none',...
        'MenuBar','none',...
        'IntegerHandle','off',...
        'Units','normalized',...
        'Resize','off',...
        'NumberTitle','off',...
        'HandleVisibility','callback',...
        'Name',sprintf('Custom UI for controlling %s.mdl',modelName),...
        'CloseRequestFcn',@localCloseRequestFcn,...
        'Visible','off');
    
    % Create an axes on the figure
    ha = axes('Parent',hf,...
        'HandleVisibility','callback',...
        'Unit','normalized',...
        'OuterPosition',[0.25 0.1 0.75 0.8],...
        'Xlim',[0 10],...
        'YLim',[-1 1],...
        'Tag','plotAxes');
    xlabel(ha,'Time');
    ylabel(ha,'Signal Value');
    title(ha,'Signal Value v''s Time');
    grid(ha,'on');
    box(ha,'on');
    
    % Create an edit box containing the model name
    hnl = uicontrol('Parent',hf,...
        'Style','text',...
        'Units','normalized',...
        'Position',[0.05 0.9 0.15 0.03],...
        'BackgroundColor',get(hf,'Color'),...
        'String','Model Name',...
        'HandleVisibility','callback',...
        'Tag','modelNameLabel'); %#ok
    hnl = uicontrol('Parent',hf,...
        'Style','edit',...
        'Units','normalized',...
        'Position',[0.02 0.82 0.21 0.06],...
        'String',sprintf('%s.mdl',modelName),...
        'Enable','inactive',...
        'Backgroundcolor',[1 1 1],...
        'HandleVisibility','callback',...
        'Tag','modelNameLabel'); %#ok
    
    % Create a Mode (Simulation or GRT) panel
    hbg = uibuttongroup('Parent',hf,...
        'Units','normalized',...
        'Position',[0.02 0.6 0.21 0.2],...
        'Title','Mode',...
        'BackgroundColor',get(hf,'Color'),...
        'HandleVisibility','callback',...
        'SelectionChangeFcn',@localModeChanged,...
        'Tag','modeGroup');
    strings = {'Simulation','GRT'};
    positions = [0.6 0.3];
    tags = {'modeRBSim','modeRBGRT'};
    % The enable property is a function of whether an RTW license is
    % available
    if license('test','Real-Time_Workshop')
        enable = {'on','on'};
    else
        enable = {'on','off'};
        % Also pop-up a dialog telling the user what's happening
        str = sprintf('%s\n%s\n%s',...
            'A real-Time Workshop license isn''t available, or cannot be',...
            'checked out.  The UI is being rendered however only ',...
            'simulation functionality is being enabled.');
        hedlg = errordlg(str,'RTW License Error','modal');
        uiwait(hedlg);
    end
    for idx = 1:length(strings)
        uicontrol('Parent',hbg,...
            'Style','radiobutton',...
            'Units','normalized',...
            'Position',[0.15 positions(idx) 0.75 0.2],...
            'String',strings{idx},...
            'Enable',enable{idx},...
            'Backgroundcolor',get(hf,'Color'),...
            'HandleVisibility','callback',...
            'Tag',tags{idx});
    end
    
    % Create a parameter tuning panel
    htp = uipanel('Parent',hf,...
        'Units','normalized',...
        'Position',[0.02 0.38 0.21 0.2],...
        'Title','Parameter Tuning',...
        'BackgroundColor',get(hf,'Color'),...
        'HandleVisibility','callback',...
        'Tag','tunePanel');
    htt = uicontrol('Parent',htp,...
        'Style','text',...
        'Units','normalized',...
        'Position',[0.15 0.65 0.7 0.2],...
        'BackgroundColor',get(hf,'Color'),...
        'String','Gain:',...
        'HorizontalAlignment','left',...
        'HandleVisibility','callback',...
        'Tag','modelNameLabel'); %#ok
    hte = uicontrol('Parent',htp,...
        'Style','edit',...
        'Units','normalized',...
        'Position',[0.15 0.28 0.7 0.3],...
        'String','',...
        'Backgroundcolor',[1 1 1],...
        'Enable','on',...
        'Callback',@localGainTuned,...
        'HandleVisibility','callback',...
        'Tag','tuneGain');
    
    
    % Create a panel for operations that can be performed
    hop = uipanel('Parent',hf,...
        'Units','normalized',...
        'Position',[0.02 0.1 0.21 0.27],...
        'Title','Operations',...
        'BackgroundColor',get(hf,'Color'),...
        'HandleVisibility','callback',...
        'Tag','tunePanel');
    strings = {'Build','Start','Stop'};
    positions = [0.7 0.45 0.2];
    tags = {'buildpb','startpb','stoppb'};
    callbacks = {@localBuildPressed, @localStartPressed, @localStopPressed};
    enabled ={'off','on','off'};
    for idx = 1:length(strings)
        uicontrol('Parent',hop,...
            'Style','pushbutton',...
            'Units','normalized',...
            'Position',[0.15 positions(idx) 0.7 0.2],...
            'BackgroundColor',get(hf,'Color'),...
            'String',strings{idx},...
            'Enable',enabled{idx},...
            'Callback',callbacks{idx},...
            'HandleVisibility','callback',...
            'Tag',tags{idx});
    end
    
    % Create some application data storing the UI handles and various
    % pieces of information about the model's original state.
    
    % Can only do the following if a Simulink License is available
    simulinkLicenceAvailable = license('test','Simulink');
    if simulinkLicenceAvailable
        try
            % Load the simulink model
            ad = localLoadModel(modelName);
            
            % The gain value needs to be poked into the UI
            set(hte,'String',ad.gainValue);
            
            % Put an empty line on the axes for each signal that will be
            % monitored
            % Save the line handles, which will be useful to have in an
            % array during the graphics updating routine.
            nlines = length(ad.viewing);
            hl = nan(1,nlines);
            colourOrder = get(ha,'ColorOrder');
            for idx = 1:nlines
                hl(idx) = line('Parent',ha,...
                    'XData',[],...
                    'YData',[],...
                    'Color',colourOrder(mod(idx-1,size(colourOrder,1))+1,:),...
                    'EraseMode','xor',...
                    'Tag',sprintf('signalLine%d',idx));
            end
            ad.lineHandles = hl;

        catch ME %#ok
            simulinkLicenceAvailable = false;
        end
    end
    if ~simulinkLicenceAvailable
        % If no Simulink license available then disable all UI controls
        % Not all uicomponents (e.g. figure, axes,...) have an Enable
        % property so do this in a loop.  The loop catches those widgets
        % without an Enable property and does nothing for them.
        allHandles = findall(hf);
        arrayfun(@(h)set(h,'Enable','off'),allHandles,...
            'ErrorHandler',@(obj,evt)disp(''));
        
        % For the UI to be closed there needs to be a modelName field in
        % appdata so just create a dummy one
        ad.modelName = modelName;
        
        % Also pop-up a dialog telling the user what's happening
        str = sprintf('%s\n%s\n%s\n%s',...
            'A Simulink license isn''t available, or cannot be',...
            'checked out.  The UI is being rendered however all ',...
            'functionality is being disabled.  Check for an available',...
            'license then try again.');
        hedlg = errordlg(str,'Simulink License Error','modal');
        uiwait(hedlg);
    end
    
    % Create a Help pull-down menu
    % (Do this here these should be enabled even if there is no Simulink
    % license.)
    hhpd = uimenu('Parent',hf,...
        'Label','Help',...
        'Tag','helpmenu');
    labels = {'Application Help','About'};
    tags = {'apphelppd','aboutpd'};
    callbacks = {@localAppHelpPulldown,@localAboutPulldown};
    for idx = 1:length(labels)
        uimenu('Parent',hhpd,...
            'Label',labels{idx},...
            'Callback',callbacks{idx},...
            'Tag',tags{idx});
    end

    % Create the handles structure
    ad.handles = guihandles(hf);
    % Save the application data
    guidata(hf,ad);
    
    % Position the UI in the centre of the screen
    movegui(hf,'center')
    % Make the UI visible
    set(hf,'Visible','on');
catch ME
    % Get rid of the figure if it was created
    if exist('hf','var') && ~isempty(hf) && ishandle(hf)
        delete(hf);
    end
    % Get rid of the model if it was loaded
    close_system('simpleModel',0)   
    % throw up an error dialog
    estr = sprintf('%s\n%s\n\n',...
        'The UI could not be created.',...
        'The specific error was:',...
        ME.message);
    errordlg(estr,'UI creation error','modal');
end

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Function to ensure that the model actually exists
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function modelExists = localValidateInputs(modelName)

num = exist(modelName,'file');
if num == 4
    modelExists = true;
else
    modelExists = false;
end

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Callback Function for Mode radio buttons
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function localModeChanged(hObject,eventdata)

% get the application data
ad = guidata(hObject);
% Make changes to the UI depending on whether Simulation or GRT is required
switch get(eventdata.NewValue,'String')
    case 'Simulation'
        % Turn off the Build button
        set(ad.handles.buildpb,'Enable','off');
        % Turn on the Start button
        set(ad.handles.startpb,'Enable','on');
    case 'GRT'
        if ad.modelAlreadyBuilt
            % Turn off the Build button
            set(ad.handles.buildpb,'Enable','off');
            % Turn off the Start button
            set(ad.handles.startpb,'Enable','on');
        else
            % Turn on the Build button
            set(ad.handles.buildpb,'Enable','on');
            % Turn off the Start button
            set(ad.handles.startpb,'Enable','off');
        end
    otherwise
        % shouldn't be able to get in here
        errordlg('Selection Error',...
            'An illegal selection was made.', 'modal');
end

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Callback Function for Build button
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function localBuildPressed(hObject,eventdata) %#ok

% get the application data
ad = guidata(hObject);

try
    % throw up a wait bar as this'll take a while
    wStr = sprintf('%s\n%s',...
        'Please wait while the model builds.',...
        'Be patient as this may take several minutes.');
    hw = waitbar(0.5,wStr);
    % set the simulation mode to external
    set_param('simpleModel','SimulationMode','external');
    % Build the model
    rtwbuild(ad.modelName);
    % reset the simulation mode to its original value
    set_param('simpleModel','SimulationMode',ad.originalMode);
    % destroy the waitbar
    delete(hw);
    % Toggle the state of the buttons
    % Turn off the Build button
    set(ad.handles.buildpb,'Enable','off');
    % Turn on the Start button
    set(ad.handles.startpb,'Enable','on');
    % Set the already built flag so we don't build again
    ad.modelAlreadyBuilt = true;
    % Flush the graphics buffer
    drawnow
catch ME
    % Get rid of the waitbar
    if exist('hw','var') && ~isempty(hw) && ishandle(hw)
        delete(hw);
        drawnow;
    end
    % throw up an error dialog
    estr = sprintf('%s\n%s\n\n',...
        'The model could not be built.',...
        'The specific error was:',...
        ME.message);
    errordlg(estr,'Build error','modal');
    % Set the already built flag to false so another build attempt is
    % reqired
    ad.modelAlreadyBuilt = false;
end

% store the changed app data
guidata(gcbo,ad);

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Callback Function for Start button
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function localStartPressed(hObject,eventdata) %#ok

% get the application data
ad = guidata(hObject);

% Load the model if required (it may have been closed manually).
if ~modelIsLoaded(ad.modelName)
    load_system(ad.modelName);
end

% toggle the buttons
% Turn off the Start button
set(ad.handles.startpb,'Enable','off');
% Turn on the Stop button
set(ad.handles.stoppb,'Enable','on');

% disable Mode changes
set(get(ad.handles.modeGroup,'Children'),'Enable','off');

% Push the current gain value in the UI into the model
localGainTuned(ad.handles.tuneGain);

% reset the line(s)
for idx = 1:length(ad.lineHandles)
    set(ad.lineHandles(idx),...
        'XData',[],...
        'YData',[]);
end

% Perform a different operation depending on whether Simulation or GRT is
% required
switch get(get(ad.handles.modeGroup,'SelectedObject'),'Tag')
    case 'modeRBSim'
        % set the stop time to inf
        set_param(ad.modelName,'StopTime','inf');
        % set the simulation mode to normal
        set_param(ad.modelName,'SimulationMode','normal');
        % Set a listener on the Gain block in the model's StartFcn
        set_param(ad.modelName,'StartFcn','localAddEventListener');
        % start the model
        set_param(ad.modelName,'SimulationCommand','start');
        
    case 'modeRBGRT'
        % set the stop time to inf
        set_param(ad.modelName,'StopTime','inf');
        % set the simulation mode to external
        set_param(ad.modelName,'SimulationMode','external');
        % Start the grt code
        % NOTE: This brings up a dos box which will need to be closed 
        %       manually
        system(sprintf('%s -tf inf -w &',ad.modelName));
        % Connect to the code
        set_param(ad.modelName,'SimulationCommand','connect');
        % start the model
        set_param(ad.modelName,'SimulationCommand','start');
        % Attach the listener
        localAddEventListener;
    otherwise
        % shouldn't be able to get in here
        errordlg('Selection Error',...
            'Neither simulation nor GRT was attempted.', 'modal');
end

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Callback Function for Stop button
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function localStopPressed(hObject,eventdata) %#ok

% get the application data
ad = guidata(hObject);

% Perform a different operation depending on whether Simulation or GRT was
% being performed
switch get(get(ad.handles.modeGroup,'SelectedObject'),'Tag')
    case 'modeRBSim'
        % stop the model
        set_param(ad.modelName,'SimulationCommand','stop');
        
    case 'modeRBGRT'
        % stop the model
        set_param(ad.modelName,'SimulationCommand','stop');
        % disconnect from the code
        set_param(ad.modelName,'SimulationCommand','disconnect');
    otherwise
        % shouldn't be able to get in here
        errordlg('Selection Error',...
            'Neither simulation nor GRT was attempted.', 'modal');
end

% set model properties back to their original values
set_param(ad.modelName,'Stoptime',ad.originalStopTime);
set_param(ad.modelName,'SimulationMode',ad.originalMode);

% toggle the buttons
% Turn on the Start button
set(ad.handles.startpb,'Enable','on');
% Turn off the Stop button
set(ad.handles.stoppb,'Enable','off');

% enable Mode changes
set(get(ad.handles.modeGroup,'Children'),'Enable','on');

% Remove the listener on the Gain block in the model's StartFcn
localRemoveEventListener;

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Callback Function for gain tuning edit box
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function localGainTuned(hObject,eventdata) %#ok

% get the application data
ad = guidata(hObject);

% Check that a valid value has been entered
str = get(hObject,'String');
newValue = str2double(str);

% Do the change if it's valid
if ~isnan(newValue)
    % poke the new value into the model
    set_param(ad.tuning.blockName,ad.tuning.blockProp,str);
    % change the axes scale
    set(ad.handles.plotAxes,'Ylim',max(abs(newValue),1)*[-1 1]);
    % store the new value
    ad.gainValue = str;
    guidata(hObject,ad);
else
    % throw up an error dialog
    estr = sprintf('%s is an invalid Gain value.',str);
    errordlg(estr,'Gain Tuning Error','modal');
    % reset the edit box to the old value
    set(hObject,'String',ad.gainValue);
end


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Callback Function for deleting the UI
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function localCloseRequestFcn(hObject,eventdata) %#ok

% get the application data
ad = guidata(hObject);

% Can only close the UI if the model has been stopped
% Can only stop the model is it hasn't already been unloaded (perhaps
% manually).
if modelIsLoaded(ad.modelName)
    switch get_param(ad.modelName,'SimulationStatus');
        case 'stopped'
            % Reset the gain to its original value
            set_param(ad.tuning.blockName,ad.tuning.blockProp,ad.originalGainValue);
            % close the Simulink model
            close_system(ad.modelName,0);
            % destroy the window
            delete(gcbo);
        otherwise
            errordlg('The model must be stopped before the UI is closed',...
                'UI Close error','modal');
    end
else
    % destroy the window
    delete(gcbo);
end

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Callback Function for adding an event listener to the gain block
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function localAddEventListener

% get the application data
ad = guidata(gcbo);

% execute any original startFcn that the model may have had
if ~isempty(ad.originalStartFcn)
    evalin('Base',ad.originalStartFcn);
end

% Add the listener(s)
% For this example all events call into the same function
ad.eventHandle = cell(1,length(ad.viewing));
for idx = 1:length(ad.viewing)
    ad.eventHandle{idx} = ...
        add_exec_event_listener(ad.viewing(idx).blockName,...
        ad.viewing(idx).blockEvent, ad.viewing(idx).blockFcn);
end

% store the changed app data
guidata(gcbo,ad);

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Callback Function for executing the event listener on the gain block
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function localEventListener(block, eventdata) %#ok

% Note: this callback is called by all the block listeners.  No effort has
% been made to time synchronise the data from each signal.  Rather it is
% assumed that since each block calls this function at every time step and
% hence the time synchronisation will come "for free".  This may not be the
% case for other models and additional code may be required for them to
% work/display data correctly.

% get the application data
hf = findall(0,'tag',mfilename);
ad = guidata(hf);

% Get the handle to the line that currently needs updating
thisLineHandle = ...
    ad.lineHandles([ad.viewing.blockHandle]==block.BlockHandle);

% Get the data currently being displayed on the axis
xdata = get(thisLineHandle,'XData');
ydata = get(thisLineHandle,'YData');
% Get the simulation time and the block data
sTime = block.CurrentTime;
data = block.InputPort(1).Data;

% Only the last 1001 points worth of data
% The model sample time is 0.001 so this represents 1000 seconds of data
if length(xdata) < 1001
    newXData = [xdata sTime];
    newYData = [ydata data];
else
    newXData = [xdata(2:end) sTime];
    newYData = [ydata(2:end) data];
end

% Display the new data set
set(thisLineHandle,...
    'XData',newXData,...
    'YData',newYData);

% The axes limits may also need changing
newXLim = [max(0,sTime-10) max(10,sTime)];
set(ad.handles.plotAxes,'Xlim',newXLim);

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Callback Function for removing the event listener from the gain block
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function localRemoveEventListener

% get the application data
ad = guidata(gcbo);

% return the startFcn to its original value
set_param(ad.modelName,'StartFcn',ad.originalStartFcn);

% delete the listener(s)
for idx = 1:length(ad.eventHandle)
    if ishandle(ad.eventHandle{idx})
        delete(ad.eventHandle{idx});
    end
end
% remove this field from the app data structure
ad = rmfield(ad,'eventHandle');
%save the changes
guidata(gcbo,ad);

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Function to check that model is still loaded
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function modelLoaded = modelIsLoaded(modelName)

try
    modelLoaded = ...
        ~isempty(find_system('Type','block_diagram','Name',modelName));
catch ME %#ok
    % Return false if the model can't be found
    modelLoaded = false;
end

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Function to load model and get certain of its parameters
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function ad = localLoadModel(modelName)

% Load the simulink model
if ~modelIsLoaded(modelName)
    load_system(modelName);
end
% Create some application data storing various
% pieces of information about the model's original state.
% These will be used to "reset" the model to its original state when
% the UI is closed.
ad.modelName = modelName;
ad.tuning.blockName = sprintf('%s/Gain',ad.modelName);
ad.tuning.blockProp = 'Gain';
ad.originalGainValue = get_param(ad.tuning.blockName,ad.tuning.blockProp);
ad.gainValue = ad.originalGainValue;

% List the blocks that are to have listeners applied
ad.viewing = struct(...
    'blockName','',...
    'blockHandle',[],...
    'blockEvent','',...
    'blockFcn',[]);
% Every block has a name
ad.viewing(1).blockName = sprintf('%s/Scope',ad.modelName);
ad.viewing(2).blockName = sprintf('%s/Gain',ad.modelName);
% That block has a handle
% (This will be used in the graphics drawing callback, and is done here
% as it should speed things up rather than searching for the handle
% during every event callback.)
ad.viewing(1).blockHandle = get_param(ad.viewing(1).blockName,'Handle');
ad.viewing(2).blockHandle = get_param(ad.viewing(2).blockName,'Handle');
% List the block event to be listened for
ad.viewing(1).blockEvent = 'PostOutputs';
ad.viewing(2).blockEvent = 'PostOutputs';
% List the function to be called
% (These must be subfunctions within this mfile).
ad.viewing(1).blockFcn = @localEventListener;
ad.viewing(2).blockFcn = @localEventListener;

% Save some of the models original info that this UI may change
% (and needs to change back again when the simulation stops)
ad.originalStopTime = get_param(ad.modelName,'Stoptime');
ad.originalMode =  get_param(ad.modelName,'SimulationMode');
ad.originalStartFcn = get_param(ad.modelName,'StartFcn');

% We'll also have a flag saying if the model has been previously built
ad.modelAlreadyBuilt = false;


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Callback Function for viewing the documentation/help
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function localAppHelpPulldown(hObject,eventdata) %#ok

% Just view the help for the primary function in this file
doc(mfilename);

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Callback Function for viewing an about box
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function localAboutPulldown(hObject,eventdata) %#ok

% Create an about box
str = {[mfilename,' was written by Phil Goddard, the Principal of Goddard Consulting.'];...
    'Feel free to send comments to phil@goddardconsulting.ca';...
    ' ';...
    'Version 3.0';...
    'Q4 2009'};
msgbox(str,'About Box','Help','modal')






Contact us