Mavlink Wall-Clock Sync

This guide walks through configuring the NanoPi to set its system clock from a MAVLink peer's SYSTEM_TIME messages. This is useful in systems where there is one device that all of the other device logs should be synced with.

The wall-clock source can be any MAVLink device that sends SYSTEM_TIME with a valid epoch timestamp — a flight controller with GPS, a companion computer with NTP, a dedicated time module, etc. The timesync module does not care where the peer gets its time from.

How It Works

Time source (GPS, NTP, etc.) → MAVLink peer → SYSTEM_TIME → SHM → chrony → Pi clock
  1. Some MAVLink device on the bus has an accurate wall clock (however it obtained it).

  2. That device sends SYSTEM_TIME messages containing time_unix_usec.

  3. The timesync module receives those messages and writes valid timestamps into an NTP shared memory segment.

  4. Chrony reads that segment as a reference clock and adjusts the Pi's system clock.

  5. All other Theseus sensors sync from the Pi via NTP automatically.

Prerequisites

  • The configured MAVLink peer must be sending SYSTEM_TIME with a valid epoch time_unix_usec (i.e., a real wall-clock time, not zero or boot-relative). Without valid timestamps, chrony falls back to whatever time source it had before.

  • If the peer is a flight controller using GPS as its time source, set BRD_RTC_TYPES=1 on the FCU (reboot required). Do not use 2 — it creates a circular time loop where the FCU trusts the Pi's clock, which is trying to trust the FCU's clock.

  • chrony.conf must include the SHM refclock line. This is included by default on mvps devices, but verify it is present:

refclock SHM 0 refid MAV precision 1e-3 delay 0.01 poll 1

Parameters

All parameters live in mav_timesync_params.yaml (file ID: components/timesync/mav_timesync_params). Four parameters control wall-clock sync:

Parameter
Type
Default
Description

mav_clock_input

bool

false

Master switch. When true, valid SYSTEM_TIME messages from the configured source are written into chrony's SHM segment. When false, no clock adjustment happens regardless of other settings.

system_clock_source_mode

string

timesync_peer

Determines which MAVLink peer provides the wall-clock time for chrony. timesync_peer reuses the normal TIMESYNC target. dedicated_peer uses the explicit sysid/compid below instead.

system_clock_source_sysid

int

42

MAVLink system ID of the dedicated wall-clock peer. Only used when system_clock_source_mode is dedicated_peer.

system_clock_source_compid

int

1

MAVLink component ID of the dedicated wall-clock peer. Only used when system_clock_source_mode is dedicated_peer.

When to use each mode

timesync_peer (default): The same MAVLink peer used for TIMESYNC round-trip offset estimation also provides SYSTEM_TIME for chrony. This is the simpler configuration and works whenever that peer has a valid wall clock.

dedicated_peer: A different MAVLink device provides the wall-clock time for chrony. Use this when:

  • The TIMESYNC peer does not have a reliable wall clock.

  • You want to source wall-clock time from a specific device on the MAVLink bus that is not the TIMESYNC target.

In dedicated peer mode, the TIMESYNC peer still handles boot-offset initialization and round-trip time measurement. Only the chrony wall-clock feed is redirected to the dedicated peer.

Configuration

Start by downloading the below python helper script:

The timesync_clock_source.py script wraps the Params API so you don't need to remember individual curl commands. It lives at scripts/device/timesync_clock_source.py in the repository.

Check current status:

Example output:

Enable wall-clock sync with the default TIMESYNC peer:

This sets mav_clock_input: true while leaving system_clock_source_mode: timesync_peer, so chrony gets its time from the same peer used for TIMESYNC.

Switch to a dedicated peer:

This sets system_clock_source_mode: dedicated_peer and configures the peer IDs. If mav_clock_input is already enabled, the dedicated peer will start feeding chrony on the next service restart.

Clear the dedicated peer (revert to TIMESYNC peer):

Disable wall-clock sync entirely:

Custom API URL (if the edge API is not at the default http://192.168.218.100:5050):

circle-exclamation

Verification

After restarting the service, verify that chrony is receiving time from the MAVLink source:

Look for a line with #* MAV — the * means chrony has selected it as the active source:

Verify the system clock is correct:

If chrony shows MAV but without the *, it means chrony sees the source but has not selected it yet (it may still be evaluating samples). Give it 30-60 seconds after the peer starts sending valid timestamps.

Troubleshooting

No MAV source in chronyc sources:

  • Check that mav_clock_input: true is set and the service was restarted.

  • Verify refclock SHM 0 refid MAV ... exists in /etc/chrony/chrony.conf.

MAV source present but not selected (#? instead of #*):

  • The peer may not have a valid wall clock yet. Check time_unix_usec in the SYSTEM_TIME messages — values near zero mean the peer does not have a time source.

  • Chrony may be preferring another source. Check chronyc sources -v for competing sources with better stratum.

system_time_invalid events in logs:

  • The configured source is sending SYSTEM_TIME with a time_unix_usec that is not a valid epoch timestamp (before Feb 2009). This means the peer does not yet have a valid wall clock. The events will stop once the peer starts sending valid time, and a system_time_recovered event will be emitted.

Dedicated peer configured but no clock feed:

  • Verify system_clock_source_mode is dedicated_peer, not timesync_peer. In timesync_peer mode the explicit sysid/compid values are ignored.

  • Verify the dedicated peer is on the MAVLink bus and sending SYSTEM_TIME at the expected sysid:compid.

Last updated