Python Forum
Running loop at specific frequency - Printable Version

+- Python Forum (https://python-forum.io)
+-- Forum: Python Coding (https://python-forum.io/forum-7.html)
+--- Forum: General Coding Help (https://python-forum.io/forum-8.html)
+--- Thread: Running loop at specific frequency (/thread-33372.html)



Running loop at specific frequency - mdsousa - Apr-19-2021

Hi

I am trying to get my while loop to run at a specific frequency (30Hz) and am having trouble getting it to work. I'm going with 30Hz x 60 seconds should give me a max run of 1800 loops. I am also checking start/end times and taking differences to determine a pause time.

Typical output from my script (I'd like to figure out if this can get close to the 1800 mark):
Output:
Number of loops: 1251 Not paused: 0 Time delta is : 60.01318955421448
This is my test code:
#!/usr/bin/env python

import time
import pause

frequency = 30 # Hz
period = (1.0/frequency)*1000

timeToRun = 1 # how many minutes to run
t_end = time.time() + 60 * timeToRun # run for timeToRun minutes

notPaused = 0
numRuns = 0

elapsedDiffList = []

startTime = time.time()
while time.time() <= t_end:
    timeNowMilli = time.time_ns()/1000000 # time from nanoseconds to milliseconds
    timeEndMilli = time.time_ns()/1000000

    pause.milliseconds(1)

    elapsedDiff = timeEndMilli - timeNowMilli

    if elapsedDiff < period:  # done before our schedule -- pause awhile
        timeToPause = period-elapsedDiff
        pause.milliseconds(timeToPause)
    else:  # took longer than scheduled -- send next message right away without pause
        elapsedDiffList.append(elapsedDiff)  # incase I get an extra long loop
        notPaused += 1
    numRuns += 1

endTime = time.time()
time_delta = (endTime-startTime)
print()
print("Number of loops: " + str(numRuns))
print("Not paused:    ", str(notPaused))
print('Time delta is : ' + str(time_delta))
print(*elapsedDiffList, sep=", ")
It doesn't feel like I'm getting a 30Hz loop out of this. Any idea what I'm missing?

Thanks...


RE: Running loop at specific frequency - jefsummers - Apr-19-2021

Alternative - the idea here is to burn cpu cycles until you reach the time to leave the gate. Will work as long as you don't have "not paused" cycles.

import time

start = time.perf_counter()
end_time = start + 60
count = 0

for division in range(1800):
    while time.perf_counter() < start + division/30:
        pass
    count = count + 1
elapsed = time.perf_counter() - start
print(f'Count {count} Elapsed {elapsed}')
Output:
Count 1800 Elapsed 59.966831974



RE: Running loop at specific frequency - mdsousa - Apr-20-2021

Thanks jefsummers

I'm giving this a try. I don't quite understand what it's doing in the line:
while time.perf_counter() < start + division/30:
I'm going to have think about it and see how it gives accurate time pauses.

Thanks...


RE: Running loop at specific frequency - jefsummers - Apr-21-2021

time.perf_counter() is the current time in seconds, with the decimal part out to the accuracy of the system
start is the time everything started
division is which "tick" you are on - 60 seconds times 30 ticks per second = 1800 ticks So, division/30 is the amount to add to start to get the time at which the "gate opens"
BTW - can eliminate the end_time line - that was in there when I was going a different path.