Задержка time.sleep() мягко говоря не соответствует действительности
Вот мой тестовый код
for i in range(int(steps)):
start = time.time()
step.write(1)
step.write(0)
time.sleep(0.00001)
print(time.time()- start)
а вот его результат с задержкой
0.015957355499267578
0.015957355499267578
0.01595783233642578
0.015956640243530273
0.01595759391784668
0.015957355499267578
0.015957117080688477
0.014960289001464844
0.01595759391784668
а вот без задержки
0.000997304916381836
0.000997304916381836
0.000997304916381836
0.000997304916381836
0.000997304916381836
0.000997781753540039
0.0019941329956054688
0.0009975433349609375
0.0009980201721191406
вопрос: какого чёрта и как можно это исправить
Ответы (3 шт):
Вообще считается, что разрешающая способность time.sleep() менее 1ms не гарантируется.
Под Windows 7 у меня чётко упирается в это значение:
D:\Programming\Python\1>python -m timeit "time.sleep(1.0/500)"
200 loops, best of 5: 2 msec per loop
D:\Programming\Python\1>python -m timeit "time.sleep(1.0/1000)"
500 loops, best of 5: 1e+03 usec per loop
D:\Programming\Python\1>python -m timeit "time.sleep(1.0/2000)"
200 loops, best of 5: 1e+03 usec per loop
D:\Programming\Python\1>python -m timeit "time.sleep(1.0/5000)"
200 loops, best of 5: 1e+03 usec per loop
D:\Programming\Python\1>python -m timeit "time.sleep(1.0/10000)"
500 loops, best of 5: 1e+03 usec per loop
Под Linux'ом, что оказался под рукой, разрешающая способность выше. Но точность сильно падает при уменьшении задержки ниже 1ms:
tests/_fast_> python -m timeit "time.sleep(1.0/500)"
100 loops, best of 3: 2.1 msec per loop
tests/_fast_> python -m timeit "time.sleep(1.0/1000)"
1000 loops, best of 3: 1.07 msec per loop
tests/_fast_> python -m timeit "time.sleep(1.0/2000)"
1000 loops, best of 3: 559 usec per loop
tests/_fast_> python -m timeit "time.sleep(1.0/5000)"
1000 loops, best of 3: 257 usec per loop
tests/_fast_> python -m timeit "time.sleep(1.0/10000)"
10000 loops, best of 3: 157 usec per loop
tests/_fast_> python -m timeit "time.sleep(1.0/20000)"
10000 loops, best of 3: 107 usec per loop
tests/_fast_> python -m timeit "time.sleep(1.0/50000)"
10000 loops, best of 3: 76.9 usec per loop
tests/_fast_> python -m timeit "time.sleep(1.0/100000)"
10000 loops, best of 3: 66.6 usec per loop
tests/_fast_> python -m timeit "time.sleep(1.0/1000000)"
10000 loops, best of 3: 58 usec per loop
Если я беру ваш код (выкинув всякие step), то мои замеры показывают следующее:
Windows 7:
0.0009999275207519531
0.0010004043579101562
0.0010001659393310547
0.0009999275207519531
0.0009999275207519531
0.0010001659393310547
0.0009999275207519531
0.0010001659393310547
0.0009999275207519531
0.0010001659393310547
Linux:
9.29832458496e-05
7.20024108887e-05
7.20024108887e-05
7.10487365723e-05
7.39097595215e-05
6.41345977783e-05
6.31809234619e-05
6.41345977783e-05
6.41345977783e-05
6.31809234619e-05
Я тут почитал про реальное время... лучше 0.000125 точности не получишь на прерываниях таймера.
Самый точный способ - это скушать процессор циклом
a=0
for i in range(int(steps)):
start = time.time()
t = time.perf_counter() + 0.00001
while t > time.perf_counter():
pass
a+=time.time()- start
print(a/steps)
Но на вызов time.perf_counter() и time.time() теряется время и на моем компьютере получилось
0.0000110626220703125
вместо 0.00001, ошибка на ~0.000001 не сильно зависит от интервала.
Но в Вашем случае циклы без сна 0.001-0.002 что делает сон в 0.00001 не существенным.
Поищите другой способ задать частоту на выводе - средствами ардуины
from firmata import *
a = Arduino('COM13')
a.pin_mode(12, firmata.OUTPUT)
a.delay(2)
while True:
a.digital_write(12, firmata.HIGH)
a.delay(2)
a.digital_write(12, firmata.LOW)
a.delay(2)
Спасибо за поправку @eri