4

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?

Dante
  • 611
  • 1
  • 7
  • 21
  • 3
    Check [`timer`](http://www.mathworks.es/es/help/matlab/matlab_prog/use-a-matlab-timer-object.html). Or, if you want it more simple, [`pause`](http://www.mathworks.es/es/help/matlab/ref/pause.html) – Luis Mendo Jun 05 '14 at 21:20
  • how long does your code take? and how accurate do you need to be? – bla Jun 05 '14 at 21:21
  • @LuisMendo: wow... you typed this comment as I was writing my answer! – rayryeng Jun 05 '14 at 21:27
  • Accuracy doesn't matter. I want to make an animated figure with it! – Dante Jun 05 '14 at 21:52
  • 2
    Don't forget [`drawnow`](http://www.mathworks.es/es/help/matlab/ref/drawnow.html) after you tell Matlab to update the plot – Luis Mendo Jun 05 '14 at 21:56
  • 4
    @user96402 if that's the case, you can record the movie using `getframe`, and then just play it at 1 fps... – bla Jun 05 '14 at 22:04
  • 1
    @user-96402: Yes. If you wanted to draw an animation, then you shouldn't need to use a `for` loop. Getting frames, and playing them at a specified frame rate is good enough. – rayryeng Jun 05 '14 at 22:07
  • 1
    +1 to natan's suggestion. Here are some examples of that approach: http://stackoverflow.com/a/11054155/97160 – Amro Jun 05 '14 at 22:07
  • @Amro: That's an awesome post. I have favourited and given you +1. Thanks for the resource! – rayryeng Jun 05 '14 at 22:40

4 Answers4

5

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 
rayryeng
  • 102,964
  • 22
  • 184
  • 193
  • 1
    @LuisMendo: ahaha no problem. Just means we are on the same wavelength – rayryeng Jun 05 '14 at 21:30
  • Actually, the code should pause for the values of `diff(times)` not for the values of `times`. Because elapsed times should not be taken in account... :-) May I change the code in your post? –  Jun 05 '14 at 21:38
  • @CST-Link: AHA, yes of course. And yes please feel free. Get your +2 rep :) – rayryeng Jun 05 '14 at 21:40
  • @rayryeng Hopefully you'll agree with my changes, thanks for the opportunity. :-) –  Jun 05 '14 at 21:43
5

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...

Community
  • 1
  • 1
  • 1
    you might wanna stick a small pause inside the while loop to reduce the [busy-waiting](https://en.wikipedia.org/wiki/Busy_waiting) – Amro Jun 05 '14 at 21:44
  • @Amro Neat! Please go ahead and do the modifs in the code if you feel so. :-) –  Jun 05 '14 at 21:46
  • 1
    one more thing (last comment I promise!): you could also use explicit tic/toc indicators (as in: `tval = tic;` and `toc(tval)`), just in case the "code" is using its own tic/toc timers. – Amro Jun 05 '14 at 21:56
2

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...

bla
  • 25,846
  • 10
  • 70
  • 101
2

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)
Luis Mendo
  • 110,752
  • 13
  • 76
  • 147
  • 1
    you could instead set `t.TasksToExecute = 10`. The timer function would simply be the code to be executed at each interval. – Amro Jun 05 '14 at 21:46
  • @Amro Nice! This is my first use of `timer` in Matlab. I was missing that property. Thanks; I've updated my answer – Luis Mendo Jun 05 '14 at 21:47