Jeff’s Ideas for Python on Hardware in 2020 – Time & Timekeeping #CircuitPython2020


Hi!  I’m Jeff Epler, AKA @jepler.  Python has long had a special place in my heart, because it is the computer language that makes me feel like I can accomplish anything I dream up.

When it comes to CircuitPython I’m new and have a lot to learn, but one thing I have seen is that it’s important to go in depth on an idea and make sure that the code in the core is ready to support a wide range of uses.  When we do this, we can find and fix problems before a new user having her first experience with CircuitPython has trouble.

One direction I’d like to dive deep is timekeeping.  If that sounds interesting to you, read on…

Timekeeping and Time Measurement

I’m a bit of a time nut, so I’d like to enable CircuitPython to keep better time.  It won’t necessarily be my focus in 2020, but it’s a set of thoughts to fall back on if I’m ever idle.  What would it take to make projects like these possible in CircuitPython?

  •  GPS Disciplined Oscillator
  •  Frequency Counter accurate to 1 ppm (6 digits)
  •  WWVB Receiver
  •  World Clock

Enhance the time module

In CircuitPython today, timekeeping depends on the “SysTick”, and requires attention from the CPU every millisecond or a tick can be lost.  This happens regularly during certain tasks, like updating large numbers of neopixels. We should modify most of the routines in the time module to use a built in RTC counter instead of the SysTick counter, on all ports where this is possible.  This would probably still count time at around 1ms granularity, but would no longer risk losing time even while doing tasks that fully occupy the CPU for more than 1ms at a time.  This may also enable calibration of a board’s timing crystal, to reduce the number of seconds per day gained or lost while the device is running. Except optionally adding a calibration value in, this would be transparent to users of CircuitPython.

Enhance the frequencyio module

A GPS Disciplined Oscillator (GPSDO) is a clock signal (often 1MHz or 10MHz) that is regulated very precisely using the GPS time as a reference.  A Frequency Counter is a device to measure the frequency of a signal.

A key sub-problem of these tasks is to continuously count the relative rates of two input signals in the background, while continuing to do Python tasks in the foreground.   Right now, frequencyio only supports counting frequency in the foreground.

Enhance the pulseio module

WWVB is a radio signal that can be received almost everywhere in North America.  Its signal can tell you the current time, once per minute. If you have a self-setting wall clock in your home, it’s probably using this kind of signal.

For a WWVB Receiver, you need to continuously receive a low bandwidth (1 symbol per second) signal in the background while the foreground Python code decodes the signal received in a previous minute and does other tasks such as updating a clock display.  Right now, pulseio only supports recording pulses in the foreground.

Enhance timezone handling

For a World Clock, you need the ability to work with standard “tzinfo” files, to convert among local time, UTC time, and other world time zones.  This might be as simple as porting the python package dateutil to circuitpython, or it might end up requiring new code designed just for CircuitPython.  In the end, you would be able to convert times between UTC and various local times.

[Image Credit: Mike Steele via Flickr, cropped for presentation]

Adafruit publishes a wide range of writing and video content, including interviews and reporting on the maker market and the wider technology world. Our standards page is intended as a guide to best practices that Adafruit uses, as well as an outline of the ethical standards Adafruit aspires to. While Adafruit is not an independent journalistic institution, Adafruit strives to be a fair, informative, and positive voice within the community – check it out here:

Join Adafruit on Mastodon

Adafruit is on Mastodon, join in!

Stop breadboarding and soldering – start making immediately! Adafruit’s Circuit Playground is jam-packed with LEDs, sensors, buttons, alligator clip pads and more. Build projects with Circuit Playground in a few minutes with the drag-and-drop MakeCode programming site, learn computer science using the CS Discoveries class on, jump into CircuitPython to learn Python and hardware together, TinyGO, or even use the Arduino IDE. Circuit Playground Express is the newest and best Circuit Playground board, with support for CircuitPython, MakeCode, and Arduino. It has a powerful processor, 10 NeoPixels, mini speaker, InfraRed receive and transmit, two buttons, a switch, 14 alligator clip pads, and lots of sensors: capacitive touch, IR proximity, temperature, light, motion and sound. A whole wide world of electronics and coding is waiting for you, and it fits in the palm of your hand.

Have an amazing project to share? The Electronics Show and Tell is every Wednesday at 7pm ET! To join, head over to YouTube and check out the show’s live chat – we’ll post the link there.

Join us every Wednesday night at 8pm ET for Ask an Engineer!

Join over 36,000+ makers on Adafruit’s Discord channels and be part of the community!

CircuitPython – The easiest way to program microcontrollers –

Maker Business — “Packaging” chips in the US

Wearables — Enclosures help fight body humidity in costumes

Electronics — Transformers: More than meets the eye!

Python for Microcontrollers — Python on Microcontrollers Newsletter: Silicon Labs introduces CircuitPython support, and more! #CircuitPython #Python #micropython @ThePSF @Raspberry_Pi

Adafruit IoT Monthly — Guardian Robot, Weather-wise Umbrella Stand, and more!

Microsoft MakeCode — MakeCode Thank You!

EYE on NPI — Maxim’s Himalaya uSLIC Step-Down Power Module #EyeOnNPI @maximintegrated @digikey

New Products – Adafruit Industries – Makers, hackers, artists, designers and engineers! — #NewProds 7/19/23 Feat. Adafruit Matrix Portal S3 CircuitPython Powered Internet Display!

Get the only spam-free daily newsletter about wearables, running a "maker business", electronic tips and more! Subscribe at !


  1. To do all of these timing things:
    1) Set up a timer running at the full clock speed, which interrupts every time it overflows. The ISR (Interrupt Service Routine) increments an overflow counter.
    2) Set up external and/or internal inputs to trigger the timer capture and execute an interrupt. The ISR in this case reads and stores the capture register, the overflow counter, and the input source; and then releases the counter register for the next input.
    3) An interface presents the (capture, overflow, input) tuples to user code. Current (counter, overflow) tuples can also be obtained so you know what ‘now’ is.

    With this general facility, all of your desires (except for timezone support) can be met:

    If you record the Pulses times from the WWVB (or better yet the PPS from a GPS), then you know what time it is relative to the second (and also have an increasingly refined knowledge of how fast the system clock is running);

    If you record the times of each input pulse you can compare the times of the zeroth and nth pulse to get a frequency. (It helps if your ISR in #2 can be set to record only the every nth pulse of a specific input, or you can use a prescalar counter on that input.). If the number of clock cycles between the pulses is >1e6 (and the jitter is low enough) you have PPM frequency measurement, even at low frequencies over short accumulation times.

    I started implementing this for the SAMDx1 chips in the ‘pulse time’ branch at
    but so far I haven’t managed to get the counter to actually count.
    At 48 MHz counter speed, a lot of moderately-high-precision applications are possible.

    See my issue//feature request at

  2. Thanks David! This looks like a great start. I haven’t understood the samd timers in depth yet, that’s for sure. How can we help you move this PR along? (Discussing it on GitHub or discord is probably better than here)

Sorry, the comment form is closed at this time.