0

How can I attain milisecond accuracy in repeating time cycle
Moderators: adafruit_support_bill, adafruit

Please be positive and constructive with your questions and comments.

How can I attain milisecond accuracy in repeating time cycle

by Probotics on Sat Sep 18, 2021 12:49 am

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?

Probotics
 
Posts: 3
Joined: Tue Apr 12, 2011 1:17 pm

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

by MarksBench on Sat Sep 18, 2021 1:45 am

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/raspberry-pi-pico-python-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.

MarksBench
 
Posts: 63
Joined: Tue Apr 20, 2021 5:40 pm

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

by westfw on Sat Sep 18, 2021 4:12 am

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...)

westfw
 
Posts: 1797
Joined: Fri Apr 27, 2007 1:01 pm
Location: SF Bay area

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

by Probotics on Sat Sep 18, 2021 5:19 pm

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.

Probotics
 
Posts: 3
Joined: Tue Apr 12, 2011 1:17 pm

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

by Probotics on Sun Sep 19, 2021 4:16 pm

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.

Probotics
 
Posts: 3
Joined: Tue Apr 12, 2011 1:17 pm

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

by adafruit_support_mike on Sun Sep 19, 2021 10:11 pm

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.

adafruit_support_mike
 
Posts: 63729
Joined: Thu Feb 11, 2010 2:51 pm

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

by tannewt on Mon Sep 20, 2021 5:14 pm

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

tannewt
 
Posts: 2629
Joined: Thu Oct 06, 2016 8:48 pm

Please be positive and constructive with your questions and comments.