MATLAB: Using timers in a class

classMATLABtimers

Hi all, I have the code below that is a simple 2 second timer that clears a flag to allow the program to exit the while loop and it works fine.
waitFlag = 1;
num = 0;
t = timer('TimerFcn', 'waitFlag=0;',...
'StartDelay', 2, ...
'ExecutionMode', 'singleShot');
start(t);
while (waitFlag) && (num == 0)
end
disp('Timer works');
Take that same concept and put it inside a class function and it doesn't work.
function ret = waitForSerial(obj)
waitFlag = 1;
t = timer('TimerFcn', 'waitFlag=0;',...
'StartDelay', 2, 'ExecutionMode', 'singleShot');
start(t);
% Wait for response to come in
% waitFlag becomes 0 when timer expires
% While is broken if timer expires or if serial data comes in
while (waitFlag) && (obj.comPort.NumBytesAvailable == 0)
end
disp("Done waiting");
if obj.comPort.NumBytesAvailable > 0
stop(t);
ret = obj.interpretMsg();
else
stop(t);
commsErr(obj, "COMs timeout");
ret = -2;
return
end
delete(t);
end
What happens is I guess the timer doesn't start, it doesn't trigger or it doesn't clear the waitFlag because the program never exits the while loop. If there is some special behaviour regarding timers/callbacks within classes, any help would be greatly appreciated.

Best Answer

The problem is most likely one of scope.I'm actually surprised that you first version works, but I never use the char array version of the TimerFcn. The documentation doesn't specify in which context that char expression is evaluated (I'll be raising a bug report for that), but it looks like it's in the base workspace. So your original code would only work in a script. In a function or class method, which have their own workspace, the timer wouldn't affect the local variable.
The best way to fix your problem is, assuming a handle class to:
a) make waitFlag a property of the class
classdef yourclass
properties (Access = private)
waitFlag
end
end
b) create a member function to handle the timer event
methods
function TimerCallback(this)
this.waitFlag = true;
end
c) use that callback as a timer function:
function ret = waitForSerial(this)
this.waitFlag = false;
t = timer('TimerFcn', @(~, ~) this.TimerCallback, ...
'StartDelay', 2, 'ExecutionMode', 'singleShot');
start(t);
while (this.waitFlag) && (this.comPort.NumBytesAvailable == 0)
end
%...
end
However, if the whole purpose of your timer is to wait a limited amount of time for some serial data, you may be better off with just attempting a read with a timeout. Overall it would be simpler and achieve the same result.