user3669833
user3669833

Reputation: 33

Use Tic Toc to Control Loop Speed

I am writing a code that is outputting to a DAQ which controls a device. I want to have it send a signal out precisely every 1 second. Depending on the performance of my proccessor the code sometimes takes longer or shorter than 1 second. Is there any way to improve this bit of code? Elapsed time is 1.000877 seconds. Elapsed time is 0.992847 seconds. Elapsed time is 0.996886 seconds.

for i= 1:100
    tic
    pause(.99)
    toc
end

Upvotes: 2

Views: 367

Answers (3)

Ben Voigt
Ben Voigt

Reputation: 283614

If you want your DAQ to update exactly every second, use a DAQ with a FIFO buffer and a clock and configured to read a value from the FIFO exactly once per second.

Even if you got your MATLAB task iterations running exactly one second apart, the inconsistent delay in communication with the DAQ would mess up your timing.

Upvotes: 0

Daniel
Daniel

Reputation: 36710

This is a inproved version of shimizu's answer. The main issue is a minimal clock drift. Each iteration the time stamp is taken and then then the timer is reset. The clock drifts by the execution time of these two commands.

A secondary minor improvement combines pause and the tic-toc technique to lower the cpu load.

ntimes = 100;
times = zeros(ntimes,1);
time_dur = 0.99;
t = tic;
for ix= 1:ntimes
    pause((time_dur*ix-toc(t)-0.1))
    while toc(t) < time_dur*ix
    end
    times(ix) = toc(t);
end
mean(diff(times))
std(diff(times))

Upvotes: 1

shimizu
shimizu

Reputation: 998

Using pause is known to be fairly imprecise (on the order of 10 ms). Matlab in recent versions has optimized tic toc to be low-overhead and as precise as possible (see here).

You can make use of tic toc to be more precise than pause using the following code:

ntimes = 100;
times = zeros(ntimes,1);
time_dur = 0.99;

for i= 1:ntimes
    outer = tic;

    while toc(outer) < time_dur

    end

    times(i) = toc(outer);
end
mean(times)
std(times)

Here is my outcome for 50 measurements: mean = 0.9900 with a std = 1.0503e-5, which is much more precise than using pause.

Using the original code with just pause, for 50 measurements I get: mean = 0.9981 with a std = 0.0037.

Upvotes: 3

Related Questions