Saturday, August 31, 2013

MATLAB GUI and Timer Object

I shouldn't really started this post at all since I have little time to 'beautify' the post, but what's described in this post can be very useful for someone that needs to have the GUI update itself at a fixed time interval, say, plotting the latest forecast data. Note that it doesn't have to be a fixed timer interval, in fact if you put enough thought into this, the schedule for the updates can be very flexible (by using database, etc).

Be warned though, the quality of the post is lacking, but I will make sure the sample application is running as expected so all you need to do is to expand on it and plug in all the pieces you need/have.

If you are not familiar with MATLAB GUI, you should read up on it (and unfortunately this post is probably not for you). If you are fairly familiar with MATLAB GUI, but haven't used  the timer object much. Here is the documentation, it is best if you try out a few examples that uses timer object without the GUI, just to get a feel for it.

Now, without further ado, below is a walk through of creating a MATLAB GUI-based digital clock (from scratch).

1. Type GUIDE in matlab, and choose to create a blank gui.

2. Create a static text on the GUI, make it and its fontsize big, and tag it as lbl_timeNow

3. Save the GUI (with the name, say, myClock), and open up its m-file.

4. In the OpeningFcn (prefixed with whatever name), insert the following code

timer_obj = timer(...
    'StartFcn',         @user_timer_start, ...              % start function
    'TimerFcn',         {@user_timer_update, hObject}, ...  % timer function, has to specific the handle to the GUI,
    'StopFcn',          @user_timer_stop, ...               % stop function
    'ErrorFcn',         @user_timer_err, ...                % error function
    'ExecutionMode',    'fixedRate', ...                    %
    'Period',           0.1, ...                           % updates every xx seconds
    'TasksToExecute',   inf, ...
    'BusyMode',         'drop');


start(timer_obj);        % start the timer object

setappdata(hObject, 'timer_obj', timer_obj');  % save the timer object as app data

Effectively, we just created and started a timer whose TimerFcn gets executed every 0.1 second. And the timer is saved as the app data so when we try to close the GUI, we can easily get our hands on the timer and get rid of it at the same time. 

5. Implement the user_timer_update function (which is set as the TimerFcn of the timer). Insert the following function to the m file. Notice how it has three input parameters, the last of which was past in in step 5 with '{@user_timer_update, hObject},'.

function user_timer_update(src,evt, fig_handle)

handles = guihandles(
fig_handle);

set(handles.lbl_timeNow, 'string', datestr(now, 'yyyy-mm-dd HH:MM:SS'));


6. Put in the other timer functions, StartFcn, StopFcn, ErrorFcn into the m file. They are just dump text printer for now. 

function user_timer_start(src, evt)
disp('Timer started!');

function user_timer_stop(src, evt)
disp('Timer stop');

function user_timer_err(src, evt)
disp('Timer error');


7.  We are almost done, just need to make sure the timer is removed when we close the GUI. So go to the GUIDE editor, and select 'CloseRequestFcn' property of the figure, it should populate the function in the m file for you. Now, before delete(hObject), put in

stop(getappdata(hObject, 'timer_obj')); % stops the timer 
delete(getappdata(hObject, 'timer_obj'));  % delete the timer object 

8. Now, here is a list of things that you may want to do: 

  • make the gui look pretty 
  • properly implement the other timer functions, StartFcn, StopFcn, etc. 


Here is what it looks like and here are .fig and .m files. 



Well. That's all for now. Good luck. 

4 comments:

  1. Very helpfull tutorial, too many thanks for you.

    ReplyDelete
  2. I have to agree with the above anon - this was honestly quite helpful.
    The line "handles = guihandles(fig_handle);" made all the difference - and setting up for it in TimerFcn.
    Thank you many, many times.

    ReplyDelete
  3. Here is a bit of extra information on the post. I was trying to update the interval variable after each execution so that I can control the amount of wait time for different ‘actions’. Unfortunately, it seems that you can not simply change the interval within the timer object, and I ended up having to create three timer objects and implemented some complex logic (to me) to start and stop the timer object at the right time. It was a pain.

    ReplyDelete
  4. Thank you Wei Shang! This is so useful!

    ReplyDelete