How to make a delay at ~100-200us

Question:

I would like to try some hardware testing with python. I have to send commands to the hardware where there is a specification for consecutive bytes transmission time interval (~100-200us). However, I found the sleep() method in time module unstable when the delay time is too small. Is there any way/operations that takes ~100-200us?

I also wonder what is the accuracy of the function time(), can it really time a 100us interval?

from time import time, sleep
a = []
start = time()
for i in range(10):
    sleep(200e-6)
    a.append(time()-start)

this is what ‘a’ looks like:

[0.0010325908660888672,
 0.004021644592285156,
 0.006222248077392578,
 0.008239507675170898,
 0.009252071380615234,
 0.01157999038696289,
 0.013728857040405273,
 0.014998674392700195,
 0.016725540161132812,
 0.0187227725982666]
Asked By: Mayan

||

Answers:

About accuracy of time.sleep

It looks like time.sleep() only has millisecond resolution. Though it could range between a few milliseconds to over 20 milliseconds (best case scenarios), based on what OS you are using, it does not look like you will get accurate microsecond sleep execution from it.

References

  1. Must See This: How accurate is python's time.sleep()?
  2. usleep in Python
  3. https://github.com/JuliaLang/julia/issues/12770
  4. https://gist.github.com/ufechner7/1aa3e96a8a5972864cec

Another Option:

You could potentially then look for creating a C/C++ wrapper around the timer-code to use it from Python.

Answered By: CypherX

The time module is not unstable, it is the underlying OS that you are running on. The request of sleeping is just passed on to the OS. In the documentation, one can read that the actual sleep time may be less then requested as any caught signal suspends the sleep, or it can be longer than requested as of scheduling reasons.If you need very high accuracy, you can use an Real-Time OS.

Answered By: Daniel

The minimum and accuracy of time.sleep is depending on the OS and python build package. But, normally it’s limited in millisecond level.

There is usleep function for microsecond sleep which is from foreign function library. But, the function is blocked and changed both behavior and accuracy across other OS, and also conflict to some python versions.
There are also several way to call other C C++ library, but it’ll crash when you put a little load which is useless for deploying application.

However, there are still tricks to reach that short of delay. There are 2 kinds using delay: delay one time and delay repeat frequently.

  • If the application purpose is for testing or it only need short delay
    sporadically, then we can use a simple loop to sleep and performance
    counter to check the time exit sleep. (Performance counter is clock
    with the highest available resolution to measure a short duration. It
    does include time elapsed during sleep and is system-wide.)
  • In another case, if the application need to call it very frequently and
    the goal is to distribute final app to client with high performance,
    CPU energy saving. We will need multiple thread and even multiple
    process to apply sleep millisecond, then syncronize on starting point
    with different micro…nano second and compare via performance
    counter to produce stable fast clock program. This will be complex and depend on
    the application to design structure.

The function for simple case is simple:

import time;

def delayNS(ns, t=time.perf_counter_ns): ## Delay at nano second
    n=t(); e=n+ns;
    while n<e : n=t(); ## Dream Work take so much energy :)

CAUTION that when you break down the stable minimum sleep limit, the delay effect cause by computation and OS background app and hardware communicate will rise up. You will need to short the name of class and variable and function and use simple syntax in script to reach highest speed as posible.

Below is the delay function that easier to read, but slower:

def sleepReal(dSec, upTime=time.perf_counter):## Can be short as 0.0000001 second or 100ns. The shorter, the less accurate
    now=upTime();  end=now+dSec;
    while now<end : now=upTime(); #Dream Work
  • function time.perf_counter() will return value (in fractional
    seconds) of a performance counter.
  • function time.perf_counter_ns() will return value (in nanoseconds) of a performance counter. This function is better because it avoid the precision loss caused by the float type. And also faster in real test.

Before apply function, you should check the delay effect when break the limit:

##### CalSpeed.py #####
import time, random;
ran=random.random;
upTIME=time.perf_counter_ns; ## More accuracy and faster
##upTIME=time.perf_counter;
def Max(x,y): return (x if x>y else y);

#####################
i=0;
nCycleUpdate=100000;   ### <<< EDIT CYCLE PRINT OUT, LET'S CHANGE IT TO  1, 10, 100, 1000, 10000, 100000, 1000000
def DreamWorks(): ### <<< YOUR DREAM WORK TO CHECK PERFORMANCE
    return True;
    #Yawwwww=ran()*ran(); ## < ~77% speed of return True
    #pass; ## < ~92% speed of return True
#####################

crT=upTIME();
limLog=nCycleUpdate-1;
iCycle=0;
def logSpeed():
    global crT, limLog, iCycle, nCycleUpdate,  i;
    iCycle+=1;
    i+=1;
    ###DreamWorks(); ### <<< YOUR WORK < ~72% speed of not dreaming
    if iCycle>limLog:
        iCycle=0;
        icrT=upTIME();
        dT=(icrT-crT)/nCycleUpdate;
        print("Count: "+str(i)+"   dT= "+str(dT)+" ns   T= "+str(icrT/1000000000)+" s   fdT= "+str(round(1000000000/Max(0.001,dT)))+" Hz   fR= "+str(i*1000000000/icrT)+" Hz" );
        ##print("Count: "+str(i)+"   dT= "+str(dT*1000000000)+" ns   T= "+str(icrT)+" s   fdT= "+str(round(1/Max(0.000000000001,dT)))+" Hz   fR= "+str(i/icrT)+" Hz" );
        #print("f = "+str(i*1000000000/icrT)+" Hz"); # < not much difference due to the costly divide calculate
        crT=icrT;
        

while True : logSpeed();

Result of check calculate speed:
enter image description here

When you change the nCycleUpdate larger, the display work will less and it complete more compute task. You can try resize/maximize the terminal window and add print task to see the change speed effect. If you try to paint or write file, the task complete will decrease more. So, the delay task for simple case is a check time task that has less computation step as possible.

enter image description here

Answered By: phnghue
Categories: questions Tags: , , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.