How can I attain milisecond accuracy in repeating time cycle

CircuitPython on hardware including Adafruit's boards, and CircuitPython libraries using Blinka on host computers.

Moderators: adafruit_support_bill, adafruit

Please be positive and constructive with your questions and comments.
Locked
User avatar
Probotics
 
Posts: 7
Joined: Tue Apr 12, 2011 1:17 pm

How can I attain milisecond accuracy in repeating time cycle

Post by Probotics »

I am implementing a PID system that requires tying feedback readings to time at 1 - 10ms precision level.

time.monotonic() achieves this - for about 16 minutes at which point it starts losing decimal places (at least on a QTPY RP2040).

The problem is I need it to maintain precision over at least 3 hours. Resetting the board restarts monotonic time and resets the degradation - but interrupts operations and sends me back through a startup cycle when the processor comes back online. I really only need to know millisecond precision over the course of about a second (I mean I don't need to know something is happening 2 hours and 13 milliseconds after start but I do need to know something is happening 10 milliseconds (or 11 or 15) after the last measurement).

I've been running in loops on this for a while and I'm down crazy ideas like creating a PWM pulse out, wiring it to the neighboring port, and counting the processor's own pulses to tell time!

Any ideas? Am I missing something obvious?

User avatar
MarksBench
 
Posts: 69
Joined: Tue Apr 20, 2021 5:40 pm

Re: How can I attain milisecond accuracy in repeating time c

Post by MarksBench »

I think something like using the RP2040 onboard hardware timers to trigger an interrupt every x number of milliseconds might do the trick. You could use it to increment a counter that gets reset every time the event you're looking for occurs.
From https://datasheets.raspberrypi.org/pico ... on-sdk.pdf
The machine.Timer class, which uses RP2040’s hardware timer to trigger callbacks at regular intervals...
The example uses MicroPython - not sure if it will work in CircuitPython without interrupts.

User avatar
westfw
 
Posts: 2010
Joined: Fri Apr 27, 2007 1:01 pm

Re: How can I attain milisecond accuracy in repeating time c

Post by westfw »

QT Py has a hardware timer as well, AFAIK.
The difficulty seems to be in CircuitPython's choice of units for the time functions it provides.
AFAICT, you have a choice of a float value in seconds from time.monotonic(), but since the 32bit floats provided by CircuitPython are only good for 6-7 digits of precision, you lose millisecond granularity some time around 1000.001 - the 16minute number OP noticed.

There's clock_monotonic_ns(), which returns 32bit ints, but with nanosecond resolution that's going to overflow after about 4s (and I'm not sure what happens after that.)

And... that's where my knowledge of CircuitPython stops. For Arduino, I might suggest "bare metal" manipulation of one of the timers that the Arduino core doesn't use, but I don't know if that's possible in CP. (It seems likely that if it is possible, someone has done it already...)

User avatar
Probotics
 
Posts: 7
Joined: Tue Apr 12, 2011 1:17 pm

Re: How can I attain milisecond accuracy in repeating time c

Post by Probotics »

Thanks MarkBench, I'm looking at the doc you sent. I might have to bail on CircuitPython or figure out how you can reach out of it somehow to access functions that aren't implemented if that is even possible. The hardware is there but the software seems to be unable to use it.

Thanks also Westfw. monotonic_ns might also be an option if I give up on CircuitPython. It doesn't support long integers here and it errors out if I try to use monotonic_ns on the QTPY.

It definitely seems an odd thing not to be able to do. The hardware seems kind of accessed for several different functions but I haven't found a simple way to get to it from within CircuitPython. It is a common thing elsewhere - Arduino, RP, heck even 8-bit PIC chips out of the 2000s will do it.

I really did want to do this in CircuitPython as part of a move to more modern languages and technologies. Any solutions not contained in MarkBench's doc or that help me integrate it with CirPy would be welcome.

User avatar
Probotics
 
Posts: 7
Joined: Tue Apr 12, 2011 1:17 pm

Re: How can I attain milisecond accuracy in repeating time c

Post by Probotics »

Hey all, just posting for future folks who search with the same problem I had.

It turns out time.monotonic_ns() does indeed work on the QTPY RP2040 and I guess that means long integers are implemented.

A QTPY SAMD21, apparently feeling lonely, snuck into my collection of QTPY RP2040s. My old eyes missed it and I was operating on the assumption I was using a RP2040. Converting over to the proper board, monotonic_ns, and exiling my SAMD21 to another box is almost certain to solve my problem. Thank you to those who suggested solutions, I expect I would have gone on missing what happened for longer without the ideas.

User avatar
adafruit_support_mike
 
Posts: 67485
Joined: Thu Feb 11, 2010 2:51 pm

Re: How can I attain milisecond accuracy in repeating time c

Post by adafruit_support_mike »

Probotics wrote:It definitely seems an odd thing not to be able to do.
CiruitPython is designed for cross-platform support and ease of programming, but not for high performance. As a rule of thumb, interpreted code tends to be about 10x slower than a compiled binary because of all the work the interpreter does in the background.

User avatar
tannewt
 
Posts: 3315
Joined: Thu Oct 06, 2016 8:48 pm

Re: How can I attain milisecond accuracy in repeating time c

Post by tannewt »

CircuitPython 7.0.0 has `supervisor.ticks_ms()` which will wrap but maintain precision. `time.monotonic_ns` will use long ints so it may slow down a bit over time due to allocating the values.

https://circuitpython.readthedocs.io/en ... r.ticks_ms

Locked
Please be positive and constructive with your questions and comments.

Return to “Adafruit CircuitPython”