How to Stop a MATLAB Timer Object From The Function's Workspace After It's Executed - matlab

Say I've got a function that evaluates to:
function test_timer()
a = timer ;
set(a, 'executionMode', 'fixedRate','TimerFcn','disp(rand)')
start(a)
end
..and I've accidentally left out 'stop(a)' within the function's clause.
How do you stop the timer object (or all timer objects) from running without closing MATLAB using the command window?

You can use timerfind to find the timers you would like to stop.
Like this:
tmr = timer('Name', 'timer1', 'TimerFcn', #(x,y)disp('Timer running'));
start(tmr);
stop(timerfind('Name', 'timer1'));
You can basically search any property you can define in timer function.
EDIT: You can use the delete function to delete the timers.
Let's create a couple of timers to find and delete them:
tmr1=timer('Name', 'timer1', 'Period', 5, 'TimerFcn', #(x,y)disp('Timer 1 running'));
tmr2=timer('Name', 'timer2', 'Period', 5, 'TimerFcn', #(x,y)disp('Timer 2 running'));
start(tmr1);
start(tmr2);
tmrList=timerfind('Period', 5); % Find the timers whose periods are 5 seconds.
stop(tmrList);
timerfind
Timer Object Array
Index: ExecutionMode: Period: TimerFcn: Name:
1 singleShot 5 1x1 function_handle arraytimer1
2 singleShot 5 1x1 function_handle arraytimer2
delete(tmrList);
timerfind
ans =
[]

Related

start 2 timers simultaneously in a matlab function

I have a program with 2 timer functions like this (p_maj_input and p_maj_output_motion are equal so the period of both timer is the same):
maj_input = timer('ExecutionMode','fixedRate','Period',p_maj_input,'TasksToExecute', ...
floor(Tmeasurement/p_maj_input)-1,'TimerFcn',{#time_append,p_maj_input,HR_all,freq_HR, ...
BVP_all,freq_BVP,TEMP_all,freq_TEMP,ACC_x_all,ACC_y_all,ACC_z_all,freq_ACC,EDA_all,freq_EDA, ...
folder_all,all_dir,num_dir}); start(maj_input);
maj_output_motion=timer('ExecutionMode','fixedRate','Period',p_maj_output_motion,'TasksToExecute', ...
floor(Tmeasurement/p_maj_output_motion)-1,'TimerFcn',{#output_motion_append, ...
freq_MOTION,freq_mvt_score,freq_walk,p_maj_output_motion,p_maj_output_walk,folder_all,all_dir,num_dir});%,'StartDelay',min(5,p_maj_output_motion)); %startDelay must be min 5 for walk detection start(maj_output_motion);
In each timer callback function there is a loop over subfolders contained in a folder that is selected at the beginning of the program.
output_motion_append(obj,event,freq_MOTION,freq_mvt_score,freq_walk,p_maj_output_motion,p_maj_output_walk,folder_all,all_dir,num_dir)
fprintf('motion %d\n',obj.TasksExecuted)
toc
for folder_index=1:num_dir
[folder_original,folder_fictive] = subfolderFunction(all_dir, folder_all, folder_index);
fileName=strcat(folder_fictive,'\ACC.csv');
[ACC_time, ACC_x, ACC_y, ACC_z] = loadValuesE4_acc(fileName);
% Motion Amount
[agitation,agitation_ts] = identifyAgitation(ACC_x,ACC_y,ACC_z,ACC_time);
agitation=agitation';
len1=length(agitation);
if len1<=freq_MOTION*p_maj_output_motion
i_init1=1;
elseif len1>freq_MOTION*p_maj_output_motion
i_init1=len1-freq_MOTION*p_maj_output_motion+1;
end
writematrix([agitation(i_init1:len1)],strcat(folder_fictive,'\MOTION_output.csv'),'WriteMode','Append');
writematrix([mvt_score(i_init2:len2)],strcat(folder_fictive,'\neurologicScore_output.csv'),'WriteMode','Append');
end
end
Everything works fine if the number of subfolders is lower than 4 : the good values appear in the files on which is carried out the writematrix function. And the timer callback function are are called one after the other, so both timer work simultaneously.
However if there are 5 subfolders or more, it is not the good values and using the debugging I noticed that the first callback function is triggered the number of 'TasksToExecute', and then only the second callback function seems to be called. That is to say the 2 timers don't work simultaneously.
I have tried to increase p_maj_input and p_maj_output_motion to see if the problem is that matlab can't finish to run before another timer callback function is called but still for 5 subfolders I get the same problem.
Does anyone know where my problem is coming from?
This behavior occurs because one timer hasn't finished executing by the time it triggers again, so the second timer never has a chance to execute until the first timer is finished. If you change the ExecutionMode from 'fixedRate' to 'fixedSpacing', then you'll guarantee that there's time for the second timer to execute.
function duelingTimers()
disp('With ExecutionMode = fixedRate')
t1 = timer('ExecutionMode','fixedRate','Period',0.1,'TasksToExecute',5,'TimerFcn',#timerFcn1);
t2 = timer('ExecutionMode','fixedRate','Period',0.1,'TasksToExecute',5,'TimerFcn',#timerFcn2);
cleanup = onCleanup(#()delete([t1,t2]));
function timerFcn1(~,~)
pause(0.2)
disp('Timer 1');
end
function timerFcn2(~,~)
pause(0.2)
disp('Timer 2');
end
start(t1),start(t2)
wait(t1)
wait(t2)
disp(newline)
disp('With ExecutionMode = fixedSpacing')
t1.ExecutionMode = 'fixedSpacing';
t2.ExecutionMode = 'fixedSpacing';
start(t1),start(t2)
wait(t1)
wait(t2)
end

Getting the number of function calls of fminsearch for each iteration

options = optimset('Display','iter','MaxIter',3,'OutputFcn',#outfun);
[x,fval,~,output] = fminsearch(#(param) esm6(param,identi),result(k,1:end-1),options);
This code will find the local Minimum of my esm6 function and due to the 'Display' Option it will Output strings like this
Iteration Func-count min f(x) Procedure
0 1 36.9193
1 5 35.9815 initial simplex
2 7 35.4924 contract inside
3 9 35.4924 contract inside
4 11 33.0085 expand
So in the command window, i get the function Count for each Iteration step. The structure output, which is created by fminsearch has only the total amount of func-count in it. Is there a way to receive all the Information, that is outputed in the command window also in the Output-structure?
EDIT:
I think i'm pretty Close to the solution. I wrote this outputfunction:
function stop = outfun(x,optimvalues,state);
stop = false;
if state == 'iter'
history = evalin('base','history');
history = [history; optimvalues.iteration optimvalues.funcCount];
assignin('base','history',history);
end
end
due to http://de.mathworks.com/help/matlab/math/output-functions.html this should work, but in fact, matlab tells me,
??? Reference to non-existent field 'funcCount'.
any idea, why this happens?

View start time of Matlab timer object

How do you view and amend the start time of a timer object in Matlab? The closest I can get is the "StartDelay" element of the timer object :
all_timers = get(timerfind);
where each element of the returned structure array is one timer object. The various elements of the structure are (for example):
AveragePeriod: NaN
BusyMode: 'drop'
ErrorFcn: ''
ExecutionMode: 'singleShot'
InstantPeriod: NaN
Name: 'timer-1'
ObjectVisibility: 'on'
Period: 1
Running: 'on'
StartDelay: 7.200175000000000e+003
StartFcn: ''
StopFcn: ''
Tag: ''
TasksExecuted: 0
TasksToExecute: Inf
TimerFcn: #myFcn
Type: 'timer'
UserData: []
According to:
http://www.mathworks.co.uk/help/matlab/ref/timer-class.html
"StartDelay" is: Number greater than or equal to 0 that specifies the delay, in seconds, between the start of the timer and the first execution of the function specified in TimerFcn.
but unless I know when the timer object was started/created/initiated, the StartDelay is no real help?
The startFun can be used to evaluate a function on timer start, which could store the start time in the userData of the timer
Most simple
Define a function such as;
function myStartFcn(hTimer,~)
hTimer.UserData = now;
end
and set this to be the startFcn of the timer
hTimer = timer();
hTimer.StartFcn = #myStartFcn
A better? example
userData is a useful field we may want to use it for many things, in which case making it a structure and setting this as a field would be better. also now gives datenum format which may not be ideal, clock is another possibility;
function myStartFcn(hTimer,~)
tempStruct = hTimer.UserData;
tempStruct.startTime = clock;
hTimer.UserData = tempStruct;
end
Also it may be worth clearing this when the timer is stopped and storing the last run time in seconds
function myStopFcn(hTimer,~)
tempStruct = hTimer.UserData;
tempStruct.lastRunTime = etime(clock,tempStruct.startTime)
tempStruct.startTime = []
hTimer.UserData = tempStruct;
end

Using fixedRate timer in MATLAB with different data for each interval (trying to replace for loop with timer)

Is there a way to have a MATLAB timer pass different data on each subsequent call to the timer function? My goal is to cycle through intervals at a fixed rate, and the pause function inside a loop is not precise enough.
I have workng MATLAB code that uses a for loop to send data via serial ports, then wait a specified time before the next iteration of the loop. The serial communication varies in speed, so if I specify 300 seconds as the period, the loop actually executes every 340-360 seconds. Here is the existing code:
clear all;
testFile = input('What is the name of the test data file (with extension): ', 's');
measurementData = csvread(testFile);
intervalDuration = input('What is the measurement change period (seconds): ');
intervalNumber = size(measurementData,2);
% Set up the COM PORT communication
sensorComPort = [101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120];
controllerComPort = [121,122,123,124];
for j=1:intervalNumber
tic
fprintf('\nInterval # %2d\n',rem(j,24));
sensorMeasurementPS = [measurementData(1,j),measurementData(2,j),measurementData(3,j),measurementData(4,j),measurementData(5,j), measurementData(6,j),measurementData(7,j),measurementData(8,j),measurementData(9,j),measurementData(10,j), measurementData(11,j),measurementData(12,j),measurementData(13,j),measurementData(14,j),measurementData(15,j), measurementData(16,j),measurementData(17,j),measurementData(18,j),measurementData(19,j),measurementData(20,j)];
serialSensorObj = startsensorPSWithoutReset(sensorComPort, sensorMeasurementPS);
serialSensorObj = changeMeasurement(serialSensorObj, sensorMeasurementPS);
rc = stopsensorPS(serialSensorObj);
controllerMeasurementPS = [measurementData(21,j),measurementData(22,j),measurementData(23,j),measurementData(24,j)];
serialControllerObj = startControllerPSWithoutReset(controllerComPort, controllerMeasurementPS);
serialControllerObj = changeMeasurement(serialControllerObj, controllerMeasurementPS);
rc2 = stopControllerPS(serialControllerObj);
pause(intervalDuration);
t = toc;
fprintf('Elapsed time = %3.4f\n',t);
end
clear serialSensorObj;
clear serialControllerObj;
The serial functions are specified in other files and they are working as intended.
What I need to do is have the serial communication execute on a more precise 5-minute interval. (The actual timing of the commands inside the interval will still vary slightly, but the commands will kick off every 5 minutes over the course of 24 hours. The current version loses time and gets out of sync with another system that is reading the measurements I'm setting by serial port.)
My first thought is to use a MATLAB timer with the fixedRate execution mode, which queues the function at fixed intervals. However, it doesn't appear that I can send the timer function different data for each interval. I thought about having the timer function change a counter in the workspace, similar to j in my existing for loop, but I know that having functions interact with the workspace is not recommended.
Here's what I've come up with so far for the timer method:
function [nextJ] = changeMeasurement_fcn(obj,event,j,sensorComPort,controllerComPort)
tic
fprintf('\nInterval # %2d\n',rem(j,24));
sensorMeasurementPS = [measurementData(1,j),measurementData(2,j),measurementData(3,j),measurementData(4,j),measurementData(5,j), measurementData(6,j),measurementData(7,j),measurementData(8,j),measurementData(9,j),measurementData(10,j), measurementData(11,j),measurementData(12,j),measurementData(13,j),measurementData(14,j),measurementData(15,j), measurementData(16,j),measurementData(17,j),measurementData(18,j),measurementData(19,j),measurementData(20,j)];
serialSensorObj = startSensorPSWithoutReset(sensorComPort, sensorMeasurementPS);
serialSensorObj = changeMeasurement(serialSensorObj, sensorMeasurementPS);
rc = stopSensorPS(serialSensorObj);
controllerMeasurementPS = [measurementData(21,j),measurementData(22,j),measurementData(23,j),measurementData(24,j)];
serialControllerObj = startControllerPSWithoutReset(controllerComPort, controllerMeasurementPS);
serialControllerObj = changeMeasurement(serialControllerObj, controllerMeasurementPS);
rc2 = stopControllerPS(serialControllerObj);
t2 = toc;
fprintf('Elapsed time = %3.4f\n',t2);
and this is how I would call it from the main m file:
t = timer('TimerFcn',#changeMeasurement,'ExecutionMode','fixedRate','period',intervalDuration);
% then I need some code to accept the returned nextJ from the timer function
This feels a bit sloppy so I'm hoping there's a built-in way to have a timer cycle through a data set.
Another idea I had was to keep the for loop but change the pause function to use a value calculated based on how much time would add up to 5 minutes for the iteration.
To summarize my question:
a) Can I have a timer pass different data to the timer function on each iteration?
b) Is that a good way to go about cycling through the intervals in my data on a precise 5-minute interval?
Thanks!
I stumbled on this page: http://www.mathworks.com/company/newsletters/articles/tips-and-tricks-simplifying-measurement-and-timer-callbacks-with-nested-functions-new-online-support-features.html
and learned that timer callback functions can be nested inside other functions (but not regular scripts).
Using that information, I cut my scenario to the basics and came up with this code:
function timerTestMain_fcn
testFile = input('What is the name of the test data file (with extension): ', 's');
testData = csvread(testFile);
intervalDuration = input('What is the voltage change period (seconds): ');
intervalNumber = size(testData,2);
t = timer('ExecutionMode','fixedRate','period',intervalDuration,'TasksToExecute',intervalNumber);
t.TimerFcn = {#timerTest_fcn};
start(t);
wait(t);
delete(t);
function timerTest_fcn(obj,event)
tic
event_time = datestr(event.Data.time);
interval_id = t.TasksExecuted;
data_value = testData(1,interval_id);
txt1 = 'Interval ';
txt2 = num2str(interval_id);
txt3 = ' occurred at ';
txt4 = ' with data value of ';
txt5 = num2str(data_value);
msg = [txt1 txt2 txt3 event_time txt4 txt5];
disp(msg)
t2 = toc;
fprintf('Elapsed time = %3.4f\n',t2);
end
end
The test data file it requests must be a csv containing a row vector. For example, you could put the values 11,12,13,14,15 across the first row of the csv. The output message would then say 'Interval 1 occurred at [time] with data value of 11', 'Interval 2 occurred at [time] with data value of 12', etc.
The key is that by nesting the functions, the timer callback can reference both the test data and the timer attributes contained in the outer function. The TasksExecuted property of the timer serves as the counter.
Thanks to anyone who thought about my question. Comments welcome.

MATLAB change repeating timer period

Is it possible to change the Period of a repeating timer (in TimerFcn)?
Intuitively, when programming for Windows, I would handle WM_TIMER messages and use SetTimer to edit the period of a timer, but a similar approach doesn't seem to work in MATLAB, because the timer needs to be restarted in order to change the Period property. This messes up execution, which can be best described as changing the period to near-zero. No errors are produced.
Here's some example code that's used to create a task array: each task item consists of something to do and a delay. The array is basically walked by a timer, which should change its Period based on the current task delay.
function obj = Scheduler(~)
obj.scheduletimer = timer(...
'TimerFcn',#obj.OnTimer,...
'BusyMode','queue',...
'TasksToExecute',length(obj.tasklist),...
'ExecutionMode','fixedRate');
end
function OnTimer(obj,source,event)
obj.Start(); // Executed task, schedule next
end
function Start(obj)
// Stop timer if needed
if(strcmp(obj.scheduletimer.Running,'on'))
stop(obj.scheduletimer);
end;
// Set new period and resume
if(~isempty(obj.tasklist))
obj.scheduletimer.Period = obj.tasklist(1).something;
start(obj.scheduletimer);
end;
end
When I don't mess with the timer in OnTimer, everything obviously works fine, but I'd like to change the Period each iteration.
Edit: I've tried to implement the pingpong solution suggested by Pursuit, but it's still not working. Note that the switching timers idea does work, but periods still don't seem to be applied.
function obj = Scheduler(~)
obj.timer1 = timer(...
'TimerFcn',#obj.OnTimer);
obj.timer2 = timer(...
'TimerFcn',#obj.OnTimer);
end
function OnTimer(obj,source,event)
obj.Start(); // Executed task, schedule next
end
function Start(obj)
if(strcmp(obj.timer1.Running,'on'))
obj.timer2.Period = obj.tasklist{1}{2};
start(obj.timer2);
else
obj.timer1.Period = obj.tasklist{1}{2};
start(obj.timer1);
end;
end
Ugh.
Use two timers, (e.g. timerNamePing and timerNamePong). At the end of the action for each timer setup the next timer to execute once in single shot mode with some delay.
This avoids the need to constantly tear down and create new timers, and avoids the error which occurs when you try and edit a timer which is currently executing.
Here is a working example to demonstrate:
function setupPingPong
timerPing = timer;
timerPong = timer;
timerPing.TimerFcn = #(~,~)pingPongActivity(true, timerPing, timerPong);
timerPing.Name = 'PingTimer';
timerPong.TimerFcn = #(~,~)pingPongActivity(false, timerPing, timerPong);
timerPong.Name = 'PongTimer';
timerPing.StartDelay = 0;
start(timerPing);
function pingPongActivity(isPing, timerPing, timerPong)
if isPing
disp(['PING (' datestr(now,'yyyy-mm-dd HH:MM:SS.FFF') ')'])
else
disp(['PONG (' datestr(now,'yyyy-mm-dd HH:MM:SS.FFF') ')'])
end
delayTime = ceil(rand*10);
display([' delaying ' num2str(delayTime) ' sec.'])
if isPing
nextTimer = timerPong;
else
nextTimer = timerPing;
end
set(nextTimer,'StartDelay', delayTime);
start(nextTimer);
Once this is going, to stop the madness, I use:
t = timerfind; stop(t); delete(t)
I use the 'StopFcn' property in timer object again to restart the counter.
something like this ('TimerScale' changes the next period)
init :
Timer_OBJ = timer( 'ExecutionMode', 'singleShot', ...
'StartDelay', SystemTicksSecs/TimerScale, ...
'TimerFcn', #(src,evt)obj.TimerCallBack,...
'StopFcn', #(src,evt)obj.TimerStopCallBack );
start(Timer_OBJ);
and inside TimerStopCallBack
set(Timer_OBJ, 'StartDelay', SystemTicksSecs/TimerScale);
start(Timer_OBJ);