I'm trying to figure out how to have a timer add time once it has begun. The idea is if a person clicks certain buttons in a GUI the timer increases by a given amount of time that is determined by a different variable. When I couldn't figure that out, I decided to just make a second timer that starts on a button click but the second timer won't display even though the code is the exact same so now I'm really at a loss.
enter image description here
enter image description here
As far as I know, there's no way to adjust a running timer. I would recommend trying to use tic/toc. Put your time limit in some variable (tLimit), get the start time with tic, and then compute the elapsed time with toc and compare to tLimit.
tLimit = <some number>;
tStart = tic;
Then later in the code you check how much time has elapsed:
if toc(tStart) > tLimit
% done
end
If you need to add time:
tLimit = tLimit + tExtra
If you really want to run your check in a timer object, you could create a function which does the time comparison, and have your timer run that:
function timeCheck(timerObj,~)
global tStart
global tLimit
if toc(tStart) > tLimit
fprintf('Time''s up! %0.1f seconds elapsed\n', toc(tStart));
stop(timerObj);
end
end
Then:
global tStart
global tLimit
tLimit = <some number>;
t = timer;
t.TimerFcn = #timeCheck;
t.ExecutionMode = 'fixedRate';
tStart = tic;
start(t);
Related
I have a Matlab code that runs a system script. The script may be stopped due to the command runs. I want to know if there is a way that the program knows if it has taken a long time and do something else. Here is the code:
tic;
[status,cmdout]=system(iperfcmd); % The program can be blocked here
toc; % I want to know if it has taken a long time (like 5 seconds) for the system call and kill it.
How about performing the system call asynchronously (https://uk.mathworks.com/help/parallel-computing/parallel.pool.parfeval.html) and polling from the main thread, something like this:
% Setup
tMax = 5; % Maximum time to wait for system call
pollDelay = 1; % Time between polls
timeOut = false;
% Run system call asynchronously
F = parfeval(#timeSystem,3,'iperfcmd');
tic
% Poll at regular intervals, break out if it finishes or exceeds time limit
while strcmp(F.State,'running') && ~timeOut
t = toc;
pause(pollDelay)
if t>tMax
timeOut = true; % This terminates the loop (alternatively use break)
end
end
if strcmp(F.State,'finished')
[status,cmdout,runTime]=fetchOutputs(F);
else
% Handle hanging system call here
cancel(F) % Cancelling the FutureEvent might terminate the system call?
end
function [status,cmdout,runTime] = timeSystem(command)
tStart = tic;
[status,cmdout] = system(command)
runTime = toc;
end
Hopefully that works for you. It's untested tested due to not having iperfcmd
Assign toc to a variable and then do logic on that value
tic
[status,cmdout]=system(iperfcmd);
elapsedTime = toc;
elapsedTime > 5
In MATLAB, I want to time a function written by someone else, and their function might use tic/toc internally. I want my own tic/toc. But if the inner function calls tic, then the outer timer gets reset.
How can I avoid this? I don't want to use timeit because timeit will call the inner function multiple times, which I don't want.
MWE:
Outer script:
tic
inner_function()
elapsed_time = toc;
fprintf('Function took %f seconds\n', elapsed_time)
Inner function:
function [] = inner_function()
pause(2)
tic
toc
end
Then:
>> outer_script
Elapsed time is 0.000024 seconds.
Function took 0.000232 seconds
If you comment out the tic/toc in inner_function() you get this, which is what I want:
>> outer_script
Function took 2.000362 seconds
Just for a little more context, the outer script is mine, and I use it to test functions written by my students. I want to allow them to use tic/toc however they want in their code, but I also want to be able to time their code independently.
You can do this by assigning your tic calls to a variable. Give your desired timer to toc later on as an argument.
function [] = inner_function()
pause(2)
tic
toc
end
Rerunning a modified example,
clock2 = tic;
inner_function()
elapsed_time = toc(clock2);
fprintf('Function took %f seconds\n', elapsed_time)
Elapsed time is 0.000009 seconds.
Function took 2.009997 seconds
I am using Matlab to develop an application which performs several mathematical operations, whose parameters can be changed when the mouse is clicked, as in the example below.
while time<endtime
calculate_manythings;
if ~mod(time,checkmouse)
mouseinput_timeout(timemouse, gca);
change_calculation_parameters;
end
time=time+1;
end
At the moment, I am pausing the operations periodically to check for mouse events, but this is slow and unpractical. How can I monitor these continually and run the code at the same time? Could I make the mouse event checks a background process using parfeval, for example?
Many thanks,
Marta
you can use callback functions. here I used 'ButtonDownFcn':
timeinterval = 1; % seconds between mouse clicks
% generate axes with callback function
h = plot(rand(1,2),'LineWidth',6);
set(gca,'ButtonDownFcn',#callback);
% reset Tag and time
h.Tag = '';
tic;
while true
drawnow;
if strcmp(h.Tag,'Pressed') % if pressed
t = toc; % check time passed
if t >= timeinterval
% change parameters
disp('Pressed');
h.Color = rand(1,3);
% reset timer
tic;
end
% reset Tag
h.Tag = '';
end
end
and the callback function is:
function callback(src,~)
src.Children(1).Tag = 'Pressed';
end
Is there any way to extract the elapsed time from the beginning of each period from a timer object in MATLAB?
Say we have a timer object like this:
t=timer('ExecutionMode', 'fixedRate', ...
'Period', 15, ...
'TimerFcn',#(x,y)disp('Hello World!'))
The y contains the absolute timestamp. Store it when the timer is stated and take the difference:
function my_callback(m,x,y)
persistent starttime
switch m
case 'start'
starttime=y.Data.time;
case 'timer'
disp(datenum(y.Data.time-starttime)*24*60*60);
otherwise
error('unknown argument');
end
end
With a timer:
t=timer('ExecutionMode', 'fixedRate','Period', 15,'StartFcn',#(x,y)my_callback('start',x,y),'TimerFcn',#(x,y)my_callback('timer',x,y))
start(t)
Alternative solution using userdata:
t=timer('ExecutionMode', 'fixedRate','Period', 15,'StartFcn',#(x,y)set(x,'UserData',y.Data.time),'TimerFcn',#(x,y)disp(datenum(y.Data.time-get(x,'UserData'))*24*60*60))
Approach using tic, toc and 'UserData'
There is no direct method on the timer-object to read the elapsed time since its last call. It is possible to use a construct with tic and toc to achieve what you want.
The generic field 'UserData' can be used to add user-data to the timer object. We can write this value with set() and read it with get(). So we set this value with tic in the callback-function and get it back later to compute the time difference using toc.
More specifically, here is the callback-function:
function timerCallback(timerObj,event) %#ok<INUSD>
disp('Hello World!');
set(timerObj,'UserData',tic);
Now we can write a wrapper-function to get the elapsed time:
function retval = getElapsedTime(timerObj)
retval = toc(get(timerObj,'UserData'));
Example usage of proposed approach
To see if this approach works, we use pause to wait in a for loop and read the elapsed time approximately every second. Here is a complete example:
function timer_example
t = timer('ExecutionMode', 'fixedRate', ...
'Period', 5, ...
'TimerFcn', #timerCallback); % create timer
start(t); % start timer
pause on; % make sure pause can be used
for i = 1:10
pause(1); % wait a second
disp(getElapsedTime(t)); % display the elapsed time
end
stop(t); % stop timer
delete(t); % delete timer
function timerCallback(timerObj,event) %#ok<INUSD>
disp('Hello World!');
set(timerObj,'UserData',tic);
function retval = getElapsedTime(timerObj)
retval = toc(get(timerObj,'UserData'));
This gives the following output:
>> timer_example
Hello World!
1.0163
2.0173
3.0235
4.0285
Hello World!
0.0366
1.0390
2.0427
3.0461
4.0470
Hello World!
0.0515
Use tic as StartFcn of your timer and then use toc to elicit elapsed time, so:
timerObj = timer; %create timer object
timerObj.ExecutionMode = 'fixedSpacing';
timerObj.Period = 15;
timerObj.StartFcn = #(~,~)tic; % start ticking when timer starts
timerObj.TimerFcn = #myTimerFunc;
myTimerFunc is:
function [] = myTimerFunc(timerObj,event)
% use toc
disp(toc);
end
I have a for loop like this
for t = 0: 1: 60
// my code
end
I want to execute my code in 1st, 2nd, 3rd, ..., 60th seconds. How to do this? Also how can I run my code at arbitrary times? For example in 1st, 3rd and 10th seconds?
What you can do is use the pause command and place how many seconds you want your code to pause for. Once you do that, you execute the code that you want. As an example:
times = 1:60;
for t = [times(1), diff(times)]
pause(t); % // Pause for t seconds
%// Place your code here...
...
...
end
As noted by #CST-Link, we should not take elapsed time into account, which is why we take the difference in neighbouring times of when you want to start your loop so that we can start your code as quickly as we can.
Also, if you want arbitrary times, place all of your times in an array, then loop through the array.
times = [1 3 10];
for t = [times(1), diff(times)]
pause(t); %// Pause for t seconds
%// Place your code here...
...
...
end
Polling is bad, but Matlab is by default single-threaded, so...
For the first case:
tic;
for t = 1:60
while toc < t, pause(0.01); end;
% your code
end;
For the second case:
tic;
for t = [1,3,10]
while toc < t, pause(0.01); end;
% your code
end;
The pause calls were added following the judicious observation of Amro about busy waiting. 0.01 seconds sounds like a good trade between timing precision and "amount" of spinning...
while pause is most of the time good enough, if you want better accuracy use java.lang.Thread.sleep.
For example the code below will display the minutes and seconds of your computer clock, exactly on the second (the function clock is accurate to ~ 1 microsecond), you can add your code instead of the disp command, the java.lang.Thread.sleep is just to illustrate it's accuracy (see after the code for an explanation)
while true
c=clock;
if mod(c(6),1)<1e-6
disp([c(5) c(6)])
java.lang.Thread.sleep(100); % Note: sleep() accepts [mSecs] duration
end
end
To see the difference in accuracy you can replace the above with java.lang.Thread.sleep(999); vs pause(0.999) and see how you sometimes skip an iteration.
For more info see here.
EDIT:
you can use tic\ toc instead of clock, this is probably more accurate because they take less time...
You can use a timer object. Here's an example that prints the numbers from 1 to 10 with 1 second between consecutive numbers. The timer is started, and it stops itself when a predefined number of executions is reached:
n = 1;
timerFcn = 'disp(n), n=n+1; if n>10, stop(t), end'; %// timer's callback
t = timer('TimerFcn' ,timerFcn, 'period', 1, 'ExecutionMode', 'fixedRate');
start(t) %// start the timer. Note that it will stop itself (within the callback)
A better version, with thanks to #Amro: specify the number of executions directly as a timer's property. Don't forget to stop the timer when done. But don't stop it too soon or it will not get executed the expected number of times!
n = 1;
timerFcn = 'disp(n), n=n+1;'; %// this will be the timer's callback
t = timer('TimerFcn', timerFcn, 'period', 1, 'ExecutionMode', 'fixedRate', ...
'TasksToExecute', 10);
start(t) %// start the timer.
%// do stuff. *This should last long enough* to avoid stopping the timer too soon
stop(t)