LexYeow
Posts: 2
Joined: Tue Dec 29, 2020 7:03 am

How to have accurate time.sleep()

Tue Dec 29, 2020 7:15 am

Hi guys, currently trying out the timelapse project. However, the sleep() function isn't exactly accurate. When I want to take a picture every 5 seconds, sleep(5), the time taken to snap a picture would always be much longer than 5 seconds. Anyone knows how to have accurate timing?

pcmanbob
Posts: 11391
Joined: Fri May 31, 2013 9:28 pm
Location: Mansfield UK

Re: How to have accurate time.sleep()

Tue Dec 29, 2020 10:35 am

Hi.

As Linux is not a real time OS you can never guarantee that timing will be accurate,

but you could try using code like this to replace your time sleep.

Code: Select all

import time

now = time.time()
start = now
end = now + 5

while now < end:
    now = time.time()
    
print ("time up ", now - start)    

I guess it depends on how accurate you need the 5 second delay to be.

Edit...

Also have you allow for the time it takes to actually take the picture in your timing calculations, if you want exactly 5 seconds between pictures.

Code: Select all

take picture - timer 
 1 second ---- 4 sec 
 over all 5 seconds 
 
some thing like this

Code: Select all

import time

while true:

    now = time.time()
    start = now
    end = now + 5

    print ("take picture")
    # replace line above with code to take picture
    while now < end:
        now = time.time()
        
    print ("time up ", now - start)    
    
includes the time it take to actually take the picture in the overall timings.
Last edited by pcmanbob on Tue Dec 29, 2020 11:05 am, edited 2 times in total.
We want information… information… information........................no information no help
The use of crystal balls & mind reading are not supported

User avatar
jahboater
Posts: 7199
Joined: Wed Feb 04, 2015 6:38 pm
Location: Wonderful West Dorset

Re: How to have accurate time.sleep()

Tue Dec 29, 2020 10:43 am

LexYeow wrote:
Tue Dec 29, 2020 7:15 am
Hi guys, currently trying out the timelapse project. However, the sleep() function isn't exactly accurate. When I want to take a picture every 5 seconds, sleep(5), the time taken to snap a picture would always be much longer than 5 seconds. Anyone knows how to have accurate timing?
You have not said what language you are using.

As above, you wont get precise timings with an OS like Linux but it should be fairly close (within milliseconds or better).

Try nanosleep() in C.
See "man nanosleep" for details.

User avatar
davidcoton
Posts: 6368
Joined: Mon Sep 01, 2014 2:37 pm
Location: Cambridge, UK

Re: How to have accurate time.sleep()

Tue Dec 29, 2020 10:50 am

"sleep" (or "nanosleep") will add a delay from the end of one process to the start of the next.
If you need accurate timing start to start, use pcmanbob's technique.
If that isn't close enough, you'll probably need to use a real time kernel, but don't ask me how.
Location: 345th cell on the right of the 210th row of L2 cache

LTolledo
Posts: 5563
Joined: Sat Mar 17, 2018 7:29 am
Location: Anime Heartland

Re: How to have accurate time.sleep()

Tue Dec 29, 2020 11:02 am

if you need accurate timing....use a microcontroller...not a microcomputer....
"Don't come to me with 'issues' for I don't know how to deal with those
Come to me with 'problems' and I'll help you find solutions"

Some people be like:
"Help me! Am drowning! But dont you dare touch me nor come near me!"

User avatar
jahboater
Posts: 7199
Joined: Wed Feb 04, 2015 6:38 pm
Location: Wonderful West Dorset

Re: How to have accurate time.sleep()

Tue Dec 29, 2020 11:51 am

davidcoton wrote:
Tue Dec 29, 2020 10:50 am
If you need accurate timing start to start, use pcmanbob's technique.
Using the loop will just run the CPU core flat out doing nothing, and of course since it still relies on getting the time will have a similar overheads. At least use a decent clock such as "clock_gettime(CLOCK_MONOTONIC)"
davidcoton wrote:
Tue Dec 29, 2020 10:50 am
"sleep" (or "nanosleep") will add a delay from the end of one process to the start of the next.
Any sleep system call has an overhead of course.
Measurement is a wonderful thing, for nanosleep() on a Pi4, I get:

Code: Select all

$ ./try
5 secs is 5000141106 nanosec
5 secs is 5000138320 nanosec
5 secs is 5000137329 nanosec
5 secs is 5000133192 nanosec
5 secs is 5000130459 nanosec
5 secs is 5000140250 nanosec
that is, the overhead is around 130 to 140 micro seconds - about 0.002%
Which may be good enough and presumably is better than the OP's quoted "much longer than 5 seconds"

It may also be that the OP's long timings are nothing to do with the sleep and may be in some other part of the code.

You could likely improve on 0.002% by using a micro-controller, but is it worth it?

PiGraham
Posts: 4789
Joined: Fri Jun 07, 2013 12:37 pm
Location: Waterlooville

Re: How to have accurate time.sleep()

Tue Dec 29, 2020 12:36 pm

For timelapse with raspistill have you read the docs?
https://www.raspberrypi.org/documentati ... melapse.md

Or in Python, using picamera:
https://picamera.readthedocs.io/en/rele ... -sequences

User avatar
rpiMike
Posts: 1739
Joined: Fri Aug 10, 2012 12:38 pm
Location: Cumbria, UK

Re: How to have accurate time.sleep()

Tue Dec 29, 2020 1:23 pm

Another option that can take a picture approx every 5 seconds excluding time taken for picture.

Code: Select all

import time

nextPic = time.time()+5

while True:
    if time.time()>nextPic:
        nextPic += 5
        print('take picture (must take less than 5 seconds)')
        
    time.sleep(0.001)

twostage
Posts: 125
Joined: Sun May 07, 2017 6:31 pm
Location: Northumberland

Re: How to have accurate time.sleep()

Tue Dec 29, 2020 4:54 pm

I think it is just a matter of compensating for the time taken for the picture to take in the sleep. Assuming the picture taking can be buried in a while loop :-

Code: Select all

snaptime = time.time()
while True:
	snaptime = snaptime + 5# desired time is 5 seconds since the last time through or wait 5 seconds if it is first time through
	sleeptime = snaptime - time.time()# work out how long to sleep until the next camera snap
	if sleeptime >  0: # haven't missed the slot
		time.sleep(sleeptime)
		# take the picture and do some other stuff if needed
	else:
		#ooops took to long taking the last picture so just skip to the next one
 

PiGraham
Posts: 4789
Joined: Fri Jun 07, 2013 12:37 pm
Location: Waterlooville

Re: How to have accurate time.sleep()

Wed Dec 30, 2020 11:21 am

Out of curiosity I did a quick test of raspistill -tl time-lapse option

Code: Select all

 $ raspistill -tl 5000 -t 30000 -o image%04d.jpg
with these results:

Code: Select all

-rw-r--r-- 1 pi pi 2699301 2020-12-30 10:53:09.378878731 +0000 image0000.jpg
-rw-r--r-- 1 pi pi 2697500 2020-12-30 10:53:14.441429941 +0000 image0001.jpg
-rw-r--r-- 1 pi pi 2722885 2020-12-30 10:53:19.423913342 +0000 image0002.jpg
-rw-r--r-- 1 pi pi 2721842 2020-12-30 10:53:24.416378444 +0000 image0003.jpg
-rw-r--r-- 1 pi pi 2626125 2020-12-30 10:53:29.408823637 +0000 image0004.jpg
-rw-r--r-- 1 pi pi 2642521 2020-12-30 10:53:34.401251811 +0000 image0005.jpg
-rw-r--r-- 1 pi pi 2627651 2020-12-30 10:53:39.393665469 +0000 image0006.jpg
-rw-r--r-- 1 pi pi 2631567 2020-12-30 10:53:44.396071564 +0000 image0007.jpg

Intervals:
5.06
4.98
4.99
4.99
4.99
4.99
5.00

Seems pretty good to me.
Last edited by PiGraham on Wed Dec 30, 2020 8:41 pm, edited 1 time in total.

User avatar
davidcoton
Posts: 6368
Joined: Mon Sep 01, 2014 2:37 pm
Location: Cambridge, UK

Re: How to have accurate time.sleep()

Wed Dec 30, 2020 4:43 pm

PiGraham wrote:
Wed Dec 30, 2020 11:21 am
Out of curiosity I did a qhick test of raspistill -tl timeplase option
Very curious quick spelling lapses there! :lol:
Location: 345th cell on the right of the 210th row of L2 cache

User avatar
paddyg
Posts: 2615
Joined: Sat Jan 28, 2012 11:57 am
Location: UK

Re: How to have accurate time.sleep()

Sat Jan 02, 2021 11:51 pm

This has cropped up on this forum a few times. @rpiMike's answer is a good way to do it. You can modify it to give you accuracy of only a few micro seconds and it won't 'accumulate errors'. i.e.

Code: Select all

MARGIN = 0.00001 #10us
DELAY = 5.0
num = 1
start_time = time.time()
next_pic = start_time + DELAY
while True:
    tm = time.time()
    if (tm + MARGIN) > next_pic:
        num += 1 # integer counter
        next_pic = start_time + num * DELAY
        print('take picture at {:.6f}'.format(tm))
    time.sleep((next_pic - tm) * 0.9) # sleep for 90% of the remaining time
Last edited by paddyg on Sun Jan 03, 2021 10:32 am, edited 1 time in total.
also https://groups.google.com/forum/?hl=en-GB&fromgroups=#!forum/pi3d

PiGraham
Posts: 4789
Joined: Fri Jun 07, 2013 12:37 pm
Location: Waterlooville

Re: How to have accurate time.sleep()

Sun Jan 03, 2021 9:57 am

paddyg wrote:
Sat Jan 02, 2021 11:51 pm
... it won't 'accumulate errors'.
That's a good point. It may be important to distribute images on a realtime schedule. You can store the start time and calculate the target time for each capture as start_time_date + interval * i++. Rather than just using the time of the previous capture plus interval. That way if some captures take a different time to complete it doesn't affect the timing of subsequent images.

User avatar
paddyg
Posts: 2615
Joined: Sat Jan 28, 2012 11:57 am
Location: UK

Re: How to have accurate time.sleep()

Sun Jan 03, 2021 10:25 am

@PiGraham, yes you are absolutely right, and that was actually the conclusion from the previous thread (now you remind me!). Python converts the + 5 to a float value and then you get cumulative float approximation errors. I will edit above - might as well make it as correct as possible. For most purposes I don't suppose it matters really but someone might find these posts when looking for something that did require an accurate sleep.
also https://groups.google.com/forum/?hl=en-GB&fromgroups=#!forum/pi3d

Return to “Python”