time.sleep inside a while loop seems to not working correctly

2.3k Views Asked by At

I am using the phidget bridge 4 input to read load cell. I am trying to acquire the data at 1 Hz so I am using time.sleep(1) inside a while loop to read the data every second as needed. To be sure I am at 1 Hz, I am printing my value while the actuel time - the time of the beginning of the script and it appears to be more than 1000ms at each loop.

Code :

from Phidget22.Phidget import *
from Phidget22.Devices.VoltageRatioInput import *
import time

start_time = round(time.time()*1000)

A1 = -6.147057832630E-06
B1 = -0.000288253826519

def onVoltageRatioChange(self, voltageRatio):
    Masse = (voltageRatio - (B1) ) / (A1)
    self.masse = Masse


def runningChannel(channel, dataInterval):

        voltageRatioInput = VoltageRatioInput()
        voltageRatioInput.setChannel(channel)
        voltageRatioInput.setOnVoltageRatioChangeHandler(onVoltageRatioChange)
        voltageRatioInput.openWaitForAttachment(5000)
        voltageRatioInput.close()
        return voltageRatioInput.masse

if __name__ == '__main__':

    while True:
        print(str(round(time.time()*1000) - start_time) + " : " + str(runningChannel(1, 1000)))
        time.sleep(1)

Console :

0 : -0.6478727917378451
1353 : -0.7766034823455521
2530 : -0.648175863557032
3914 : -0.7572446275502878
5089 : -0.6493878254748858
6474 : -0.6990053837124224
7650 : -0.6493878254748858
9033 : -0.8542015809786906
10209 : -0.6509030218913868
2

There are 2 best solutions below

1
lyrjie On BEST ANSWER

You are forgetting that the runningChannel() call also takes some times to execute.
To do something (still approximately) every second, you can use this loop:

import time
while True:
    start_time = time.time()
    # your operations here
    time.sleep(1 - (time.time() - start_time))

It obviously will fail, if your operation takes more than a second

3
shayelk On

It seems like you have functions that might take a while to return (e.g. openWaitForAttachment(5000)). add that to the 1 second delay you added on purpose, and you get a delay that is always slightly bigger than 1 second. If you want to get over this problem, you'll have to keep track of time (for example, you can log the time at the start of each iteration, and after your logic ran wait only the remaining time)