Connecting a Raspberry Pi to the time mesh

The M-HAT gives us a first working path from BLE time to a Pi clock. USB, wired PTP and a smaller ESP32 bridge give us several directions to explore next.

PToB over BLE feeds a Pi 5 through demonstrated M-HAT PPS, with NTP protocol checks and wired PTP testing distinguished. Dashed paths show proposed external PTP ingress and an ESP32-S31 bridge.
Concept diagram. BLE-to-Pi PPS transfer is measured; NTP loopback and Wi-Fi PTP egress have protocol checks. Wired endpoint timing, Linux USB/SOF and reverse PTP ingress remain future experiments.
In this post

A time mesh becomes more useful when it can join the clocks people already run. A workshop might have a Raspberry Pi serving NTP, a wired PTP network and sensors that need shared time without another cable. We want PToB to connect those environments, carrying time over BLE while keeping familiar tools at the network boundary.

Our first experiment uses a Raspberry Pi 5 with a repurposed Particle M-HAT. Its nRF52840 receives authenticated PToB timing, produces a hardware pulse per second, and passes that PPS through the HAT connector to Linux. Chrony disciplines the Pi system clock. NTP and PTP services give us the beginnings of a bridge to existing network clients.

The new seven-page paper records that first working path and its complete results. It also sets up the next question: can an ordinary USB cable make the Pi connection easier?

From a BLE clock to Linux PPS

The M-HAT generates its pulse with a hardware timer, so Linux does not have to schedule the edge. PPS reaches Pi GPIO16 through the existing connector; the kernel timestamps it and chrony follows its phase. Network NTP supplies coarse UTC second numbering. The current setup therefore combines a BLE-derived second boundary with a separate source for deciding which UTC second it is.

The HAT is running receiver firmware. It follows the mesh and emits pulses only while its source and timing map remain permitted. It cannot yet take an external PTP clock and become a mesh grandmaster. That direction needs its own bridge and source implementation.

After a 120-second settling period, our final fixed 600.026-second window retained all 600 expected PPS assertions, with one source cohort, no observed missing pulses and no service restarts. The complete GPIO timestamp population had:

  • 872 ns RMS phase relative to the disciplined Pi system clock.
  • 554 of 600 observations within ±1 µs.
  • 4.809 µs absolute P99, with a 7.017 µs maximum.

All tails remain in those figures. Chrony’s separately sampled tracking RMS estimate had a 72 ns median, while the HAT’s internal fit RMS had a 54 ns median. These describe different stages of the chain. GPIO phase includes interrupt capture and the clock servo’s own corrections; none of these measurements independently establishes UTC accuracy or electrical PPS accuracy.

For a first integration, ten continuous minutes is encouraging. The tails also tell us where the next experiments need to concentrate. Keeping the complete delivered path below one microsecond remains our goal.

How that compares with other PPS systems

PPS can give a Linux system excellent phase information, but the capture path matters. In chrony’s published examples, a serial-port PPS server reports a tracking RMS of about 489 ns while an independent reference finds the system clock roughly 20 µs off much of the time. Interrupt timestamping delays account for most of that example’s error.

The same documentation shows a different route: PPS captured directly by an Intel I210 network hardware clock, avoiding interrupt capture. Chrony tracks that reference to about 20 ns, with independent accuracy still requiring a better reference. Those are different machines and measurement arrangements, rather than a matched benchmark against our Pi.

The useful comparison is architectural. Our sub-microsecond GPIO RMS is promising for an initial system-time experiment, but a small servo estimate can coexist with bias and larger tails. Capturing an event in the clock that timestamps network packets can remove a crossing that a GPIO-to-system-clock route still has to traverse.

Watching the whole timing path

We built a read-only monitor so that a low RMS number does not have to stand in for the health of the complete gateway. It shows BLE admission, current PPS, chrony selection and NTP/PTP readiness separately, along with the source grandmaster and immediate radio parent.

Repository Pi timing monitor showing BLE admission, GPIO16 PPS, chrony selection and separate NTP/PTP readiness with illustrative example values.
The repository’s timing monitor, rendered with synthetic example data. The stages distinguish an admitted source, selected PPS and network-service readiness; Ethernet link absence remains visible. Open the image for full-size details.

The history view keeps receiver fit, chrony estimates and raw GPIO phase distinct. It preserves gaps and source changes and exports the selected window as CSV. The screenshots here demonstrate the monitoring interface; the measured population is in the paper.

Repository timing history interface with separate clock-offset, RMS, GPIO PPS and receiver-frequency charts using synthetic observations.
Offset and RMS history with illustrative synthetic observations, copied unchanged from the repository. Each chart names the part of the timing chain it observes. These plotted values are not the ten-minute experiment.

The actual post-run checks obtained valid NTP replies on Pi loopback and matched PTP Sync/Follow_Up traffic leaving Wi-Fi. Wired Ethernet was disconnected throughout the measurement. We have demonstrated the Pi integration and checked protocol operation; remote NTP/PTP timing still needs a peer and an independent reference.

The next experiment uses USB, without the HAT

Our macOS USB work starts from a hardware event rather than the arrival time of a serial message. The receiver captures USB start-of-frame events against its timer. The host matches frame identity to its own clock, then uses the receiver’s source map to translate that event into shared time. A late response can still describe an earlier captured event.

We want to try that architecture on Linux using a T096 receiver connected directly to the Pi over USB, with the M-HAT removed from the timing path. If it works well, sharing mesh time with a Pi could become a cable-and-software job, with no repurposed HAT or GPIO PPS connection.

The Linux host association is the experiment. Apple’s frame/Mach APIs do not simply transfer to a Pi, and USB completion time does not identify the original frame boundary. Our plan is to:

  1. Establish device-to-host frame association in shadow mode, without steering the system clock. Retain ambiguous frames, resets, warmup and expired-source intervals.
  2. Compare fixed windows with the GPIO baseline, including bias, RMS, P99, maximum error, missing observations and behavior under load. Test direct ports, hubs and reconnects separately.
  3. Introduce a chrony feed only after validating the mapping, then measure against an independent physical reference. Chrony remains the sole system-clock owner.

USB could bypass GPIO interrupt capture and offer more observations. Whether its host-clock association improves the complete Pi result is still open.

Crossing the Pi Ethernet clock

PTP Ethernet brings another clock into the chain: the NIC’s PTP hardware clock, or PHC. In our prepared forward path, chrony owns the system clock, a separate process transfers system time into the PHC, and PTP serves from there. The forthcoming wired tests need to measure that transfer and what an Ethernet peer actually receives, including link loss and recovery.

We also want the reverse direction: external PTP → Pi → PToB → BLE devices. That would let an existing wired timing network extend into places where running Ethernet is inconvenient. The PHC would follow external PTP, then a USB bridge or a suitable HAT/timer connection would associate it with the radio clock.

The tested Pi PHC exposes no external timestamp inputs or periodic-output pins. Ethernet packet timestamp support alone does not provide that physical bridge. A HAT approach needs suitable timing I/O and a measured clock association; USB needs the Linux SOF work above. Both need explicit source provenance, UTC/TAI handling and withdrawal when their reference disappears. A gateway must also avoid feeding its own exported time back into its source network.

Could an ESP32-S31 make a smaller bridge?

The ESP32-S31 is an appealing future target for us because it combines BLE with a gigabit Ethernet MAC. Espressif now lists it as available, and its datasheet documents IEEE 1588 support and transmit/receive frame timestamps. Gigabit operation requires an external PHY and suitable board design.

That gives us concrete PTP support to investigate. We still need to establish how the Ethernet clock connects to a precisely captured BLE event, what the driver exposes, and how both behave under concurrent traffic. Our existing ESP32-S3 timing implementation and results do not automatically carry across to the S31.

If those pieces work, an S31 board could offer a cheaper, smaller Ethernet-to-BLE bridge than a Pi plus HAT. Total board cost and timing performance remain to be established. An NTP mesh extension is another useful target without first meeting the PTP precision goal: it could receive mesh time and serve local clients, or potentially operate standalone with a GPS receiver supplying PPS and UTC second labels. Source-loss behavior, holdover and delivered NTP error would still need testing.

The M-HAT has given us a practical first route into Linux. USB may make that route easier to deploy; Ethernet clock work may connect existing PTP installations; a smaller MCU may bring the bridge to more places. We want a flexible time mesh that can use whichever connection fits an installation, carrying its source and measured limits along with the time.