0

I wrote a system to exchange crc-checked struct data between an arduino nano and my python script. This is working pretty well but when i let the system run i get unexpected output on my python monitor (using pycharm)

print "Took ", (time.time() - timeout), " s" sometimes prints out Took 0.0 s. Usually it prints Took 0.0160000324249 s. Using win7-64bit professional.

From time doc : Return the time in seconds since the epoch as a floating point number. Note that even though the time is always returned as a floating point number, not all systems provide time with a better precision than 1 second.

I´m looking for something like millis() thats enough precision for my case

Code Python :

import serial
import time
import binascii
import struct
from ctypes import *    

arduino = serial.Serial()
def receive_struct2():
  start = 0x85
  detected_start = False
  arduino.baudrate = 57600
  arduino.timeout = 0
  arduino.port = 'COM8'
  try:
    arduino.open()
  except serial.SerialException, e:
    print e

  while True:
     if(arduino.inWaiting() >= 1 and detected_start == False):
        data = ord(arduino.read())
        if data == start:
          print "Detected begin"
          detected_start = True
        else: print chr(data),

     if arduino.inWaiting() >= 1 and detected_start == True:
       message_length = ord(arduino.read())
       #print "Got message length ", message_length
       timeout = time.time()
       while time.time() - timeout <= 0.3 and arduino.inWaiting() <  message_length-1:pass
       print "Took ", (time.time() - timeout), " s"
       ....
Marc Pole
  • 29
  • 7
  • unrelated: there should be a way to wait for I/O without a busy loop (`select()` analog on Windows) check aurdino API doc. A better way to implement a busy loop is to use a deadline: `deadline = timer() + 0.3; while timer() < deadline and ...`. Note: there are different useful timer definitions: system-wide vs. process-wide value, known-origin vs. only relative values are useful, count sleep time and/or time in child processes or not, etc. For example read [`time.monotonic()`, `time.perf_counter()`, `time.process_time()` definitions](https://docs.python.org/3/library/time.html#time.monotonic) – jfs Feb 07 '15 at 19:45

1 Answers1

1

Summary: Use timeit.default_timer() instead of time.time(), to measure a short duration.


16ms error for time.time() is not surprising on Windows.

Currently, Python uses GetSystemTimeAsFileTime() to implement time.time() on Windows that has the resolution (precision) of 0.1ms (instead of ftime()'s 1ms) and the accuracy is between 0.5 ms and 15 ms (you could change it system-wide using NtSetTimerResolution()). See Python bug: Use GetSystemTimeAsFileTime() to get a resolution of 100 ns on Windows and another SO question: How does python's time.time() method work?

A better alternative to measure short time intervals on Windows is to use time.clock() that is implemented using QueryPerformanceCounter() on Windows. For portability, you could use timeit.default_timer that is assigned to time.clock() on Windows, time.time() on other systems, and it is time.perf_counter() since Python3.3. See Python - time.clock() vs. time.time() - accuracy?

Community
  • 1
  • 1
jfs
  • 399,953
  • 195
  • 994
  • 1,670