0

I want to run some physical devices in a time dependent manner, my program needs to synchronize with an external process, so accuracy is important. The code I need to run is quite simple, but I will have to wait in between, my first approach would be:

import serial
import time
device = serial.Serial('COM3')

while True:
   device.write(command)
   time.sleep(30)

However I want one loop to take 30 seconds excluding the code executing, the best way I can think of would be something like:

start = time.time()
cycle = 1
while True:
   device.write(command)
   while start + cycle*30 < time.time():
      sleep(0.5) 

But this doesn't feel like a great way to do this. Is there a better way?

Thijs
  • 1
  • Does this answer your question? [In Python, how can I put a thread to sleep until a specific time?](https://stackoverflow.com/questions/2031111/in-python-how-can-i-put-a-thread-to-sleep-until-a-specific-time) – Joooeey Jun 15 '22 at 11:36
  • I think you mean "_take 30 seconds **including** the code executing_". At least, your second code example seem to suggest so. – wovano Jun 15 '22 at 18:08

2 Answers2

0

You have to use threading. I think you want to run command while writing to device without affecting synchronization. To do so , the only solution is run two tasks parallelly, How to do it? By threading.

import time
import threading

command = "command"
 
#First Method
def write_to_device(command):
    while True:
        device.write(command)
        time.sleep(30)
 
#Second Method
def do_something():
    While True:
        pass
        # Do something
 
     
t1 = threading.Thread(target=write_to_device, args=(command,))
t2 = threading.Thread(target=do_something)
 
#Started the threads
t1.start()
t2.start()
 
#Joined the threads
t1.join()
t2.join()
Kavindu Ravishka
  • 711
  • 4
  • 11
  • I think this can be a very helpful tool if I want to run other things in between. But it doesn't necessarily solve the timing issue (device.write(command)) should be very quick, but I don't trust all the equipment involved to be quick enough. – Thijs Jun 15 '22 at 11:52
  • There won't be any problem if the interval is 30 seconds. I think you are passing this info via a port. Then there won't be a problem. Ports have a cache to store it until it is read. And most of the devices wait until something come to read if there is nothing to read when it is ready. I assume you are trying to write into arduino or node mcu. No problem with timing. It will solve them by itself. – Kavindu Ravishka Jun 15 '22 at 11:57
0

The easiest solution is to calculate the time until the start of the next interval, and sleep for that amount of time. See the following code for a demonstration:

import random
import time

INTERVAL_TIME = 5.0

def some_operation():
    print('Starting some operation at ' + time.strftime('%H:%M:%S'))
    time.sleep(3.0 * random.random())
    print('Finished the operation.')

next_time = time.time()
while True:
    next_time += INTERVAL_TIME
    some_operation()
    time.sleep(next_time - time.time())

Note that if the operation could take longer than the interval period, you'll have to decide how you want to deal with it. Sleeping for a negative amount of time is not possible and will result in an exception. However, you could choose to start the next operation immediately (and hopefully catch up time), or skip the operation and start at the next interval.

wovano
  • 4,543
  • 5
  • 22
  • 49