Using timer objects gets too complicated especially when you have to use more than one timer so I was trying to think of alternative approaches.
I want to avoid using pause, since it stops other functions from executing. I thought of using the tic toc functions to measure elapsed time but the code I have written below does not work as I expect.
time=tic;
if(abs(toc(time)))==3 %% if 3 second past
my function
end
How can I modify this code so that it executes the command after 3 seconds?
TLDR;
A tic/toc pair and a while loop is literally no different than using pause since they both block execution of any other functions. You have to use timer objects.
A More Detailed Explanation
In order to make this work, you'd need to use a while loop to monitor if the required amount of time has passed. Also, you'll want to use < to check if the time has elapsed because the loop condition isn't guaranteed to be evaluated every femtosecond and therefore it's never going to be exact.
function wait(time_in_sec)
tic
while toc < time_in_sec
end
% Do thing after 3 seconds
fprintf('Has been %d seconds!\n', time_in_sec)
end
The unfortunate thing about a while loop approach is that it prevents you from running multiple "timers" at once. For example, in the following case, it will wait 3 seconds for the first task and then wait 5 seconds for the second task requiring a total time or 8 seconds.
wait(3)
wait(5)
Also, while the while loop is running, nothing else will be able to execute within MATLAB.
A much better approach is to setup multiple timer objects and configure them with callbacks so that they can run at the same time and they will not block any operations within MATLAB while they run. When you need multiple timer objects (which you consider to be a pain) is exactly when you have to use timer objects.
If it's really that cumbersome, write your own function which does all of the boilerplate stuff for you
function tmr = wait(time_in_sec)
tmr = timer('StartDelay', time_in_sec, ...
'ExecutionMode', 'SingleShot', ...
'TimerFcn', #(s,e)status(time_in_sec));
tmr.start()
function status(t)
fprintf('Has been %d seconds!\n', t);
end
end
wait(3)
wait(5) % Both will execute after 5 seconds
Also since the timers are non-blocking (when the callback isn't running), I can execute commands immediately after starting the timers
wait(3)
disp('Started 3 second timer')
wait(5)
disp('Started 5 second timer')
If you try this with your while loop, you'll see the while loop's blocking behavior.
you need a while loop or something to wait for time to be 3 seconds.
something like this
time=tic;
while 1
if(abs(toc(time)))==3 %% if 3 second past
my function
break;
end
end
If you want to call my function every 3 seconds, then you should do something like this:
time=tic;
while 1
if mod((abs(toc(time))),3) == 0 %% if 3 second past
my function
end
end
Please make sure that you have some way of telling once you are done and then break the while loop.
You could set it to >= instead of ==. That will catch it if it misses the exact value.
Related
This question already has an answer here:
Matlab time limit for function execution
(1 answer)
Closed 5 years ago.
I run a matlab script multiple times per day and a lot of times it takes too long to execute. What I want to do is set off a timer that keeps track of how long the script has been running for and stops the script when it takes longer than a specified number of seconds
I have tested this principle on a simple script:
waittime = 5;
t = timer('TimerFcn','error(''Process ended because it took too long'')',waittime);
start(t)
pause(10);
What I would expect to happen is that this function waits for 5 seconds and afterwards it will execute the stop function which is the error('Process ended because it took too long') command.
When running this, the stop command will execute, however it does not stop the main script from running.
In my command window I see
Error while evaluating TimerFcn for timer 'timer-20'
Process ended because it took too long
Afterwards the script is not stopped, and keeps running for the full 10 seconds
I don't want this error to be cast over the TimerFcn function, I want this error to be cast over the running script such that it stops running.
Is there any way I can control the script/function over which the error is cast?
If you have access to the the script and can periodically check for the time inside the script, you can do something like this
waittime = 3;
endt=true;
t = timer('TimerFcn','endt=false; disp(''Timer!'')','StartDelay',waittime);
start(t);
i=1;
while endt==true
a=exp(i);
i=i+1;
pause(0.1);
end
If you do not have any bits that are periodic or do not have access to the script, I think your best bet is described here
Matlab: implementing what CTRL+C does, but in the code
Hope this is helpful
I agree with Ander Biguri that I don't think this is possible. What you can do is make the TimerFcn do something that causes an error somehwere else.
waittime = 5;
d=1;go=1;
t = timer('TimerFcn','clear d','StartDelay',waittime);
start(t)
while go
pause(0.1)
1/d;
end
Given this previous question, you'll probably have to resort to some Java tricks to do this, since throwing an error message doesn't interrupt the pause statement. However, if the script you're running can periodically break computation and perform checks on the state, you can incorporate a timer as follows:
% Initialization:
maxRunTime = 5;
tObj = timer('TimerFcn', #(~, ~) disp('Time''s up!'), 'StartDelay', maxRunTime);
% Script:
start(tObj);
while strcmp(get(tObj, 'Running'), 'on')
% Do some computations
end
delete(tObj);
This checks the running state of the timer to determine if the loop continues, so the timer function doesn't have to modify any variables or throw any errors.
Is it possible to put the calling of function into another thread? I tried spmd in the function but i get error saying that
MATLAB cannot determine whether "System" refers to a function or
variable.
tic
Speak('Testing');
toc
...next line of code...
function Speak(text)
spmd
NET.addAssembly('System.Speech');
speak = System.Speech.Synthesis.SpeechSynthesizer;
speak.Volume = 100;
speak.Speak(text);
end
end
I get elapsed time of approximately 2 seconds, which is pretty long for this purpose. I would prefer the speech continuing in the background and proceed to the next line of code in the meantime.
I have a MATLAB GUI that looks as shown in:
MATLAB GUI image
What I am trying to achieve is that MATLAB keep checking for midnight continuously, except for the pauses when the user makes any change to the interface. Hence, I am running a while loop in the background continuously as I need to check if it is midnight. If it is, I perform some functions. The function that contains this while loop is called after any user input change is detected i.e. at the end of all the callback functions for the pop-up menus,pushbuttons, textboxes etc. This is the reason I had the drawnow in the while loop, so that if the user makes any changes and wants to run some calculations, that will be detected. After the completion of the calculations, I again call the function which has this while loop.
The issue is, even though I use drawnow and pause in my while loop, sometimes, not always, MATLAB still hangs-up on me and the GUI becomes unresponsive and does not recognize any of the user inputs. Here is the while loop part of my code:
while 1
pause(0.1);
drawnow;
pause(0.1);
current_time=clock;
if current_time(4)==0
post_mortem;
end
end
I know the above code is not efficient as it will call post_mortem continuously in the midnight hour, that however is not my issue right now. My issue is that it hangs up on me at times even at noon for example. Does anybody have any solution to this? On searching for answers to previous similar questions, the solution seemed to be to use drawnow and pause, but that doesn't seem to be working for me either.
Any guidance would be appreciated.
Thank you
Since MATLAB is not multi-threaded, using a while loop to continuously check something (such as the time) is going to cause all sorts of blocking of other functionality. While drawnow and pause can potentially help with this, there are still some potential issues that can crop up.
A more elegant and reliable approach would be to use a timer object to check the time at a pre-specified interval. This way, any user interaction with the GUI will automatically be registered and any callbacks will execute without you having to call either pause or drawnow.
You can create and start the timer as soon as you create your GUI.
% Create the timer object
handles.mytimer = timer('ExecutionMode', 'FixedRate', ...
'Period', 1/5, ...
'BusyMode', 'drop', ...
'TimerFcn', #(s,e)timerCallback());
% Start the timer
start(handles.mytimer)
function timerCallback()
% Callback that executes every time the timer ticks
current_time = clock;
if current_time(4) == 0
post_mortem;
end
end
I am an amateur Matlab User who is attempting to write a code to run a specific function call every 10ms for a time span of 1 second. I am having trouble trying to get something to run for the exact amount of time; I have tried to use Tic and Toc but that's in seconds (I need millisecond precision). Here is some very basic code I have been playing with to try and get readings using a function called getvelocity. Any help would be appreciated, thanks!
function [ velocity ] = Vel()
i=1;
timerID=tic;
while (toc(timerID) <=2);
[v(i)]=vpx_GetTotalVelocity;
disp (v(i));
i=i+1;
end
velocity=mean(v);
end
The code above runs for two seconds; however, I want to run in ms precision.
Assuming the function you have is fast enough (not a trivial assumption) you can achieve it like so:
tic
for t = 0.01:0.01:1 %If you want the first function call to start right away you can change this to 0:0.01:0.99
while toc < t
end
t %Put your function call here.
end
Note that 0.01 sec is 10 ms
As stated in title.
I want to have a certain interval time for each loop, say 60 seconds.
My problem is I have a code inside a loop to perform measurement with a external device.
This measurement takes 5-10 seconds.
So I cannot simply use pause(60) inside the loop because the interval time depends on how long each measurement takes.
Is there any way to fix the time interval of loop?
Sounds like you'd be able to use parallel threading to achieve what you want. One thread kicks off the measurement every sixty seconds, using a worker thread so that the measurement doesn't block up the time interval.
Perhaps try the batch function with something like this:
while(True)
hBatch = batch(#doMeasurement);
pause(60);
measurement = fetchOutputs(hBatch){1}
end
Better would be to use the timer function:
t = timer('TimerFcn', #doMeasurement, 'Period', 60.0);
start(t)
You want something like this:
k=1; % or any value except 0
time1=clock;
while ~(k==0)
time2=clock;
k=etime(time2,time1);
% your statements
loop