Skybrush TIMESYNC and the MA-RTK-AIR-626: tracing a missing GPS week
A customer flying a Skybrush light-show fleet sent us a puzzle in October: every drone carrying an MA-RTK-AIR-626 RTK module had a perfect RTK FIXED solution and passed its pre-arm checks, yet Skybrush Live flagged each one with a yellow TIMESYNC warning. The cause turned out to be one missing number. The 626 never sends the GPS week, and ArduPilot's u-blox driver has no other place to find it. This is the story of how we traced it, why no setting could fix it, and how we changed the firmware and tested the change before it went near a show. The step-by-step fix and the firmware downloads for 20 flight controllers are in the MA-RTK-AIR-626 Skybrush guide.
The symptom: everything looked right except the clock
A drone show is a time problem as much as a positioning problem. Every drone flies its own pre-computed trajectory, and the fleet stays in formation only if every drone starts the show clock at the same instant. Skybrush takes that clock from GPS time, and Skybrush Live warns with TIMESYNC when a drone cannot provide it.
On this fleet nothing else looked wrong. The 626 drones had a 3D fix, then RTK FIXED from the base station. Positions in Mission Planner were correct. Pre-arm checks passed, because they look at position quality, not at the date. What was missing was the time itself: no valid GPS date, and no real UTC timestamps in the logs.
That pattern, a good fix with no time, is what pointed us away from antennas, wiring and RTK corrections and toward the GPS driver.
Tracing it: GPS time is two numbers
GPS receivers do not count time as a calendar date. They count the week number since 6 January 1980 and the time of week ("iTOW"), in milliseconds, since the start of that week. A flight controller needs both to know the absolute time.
The 626 is built on a Unicore UM626N receiver, but it speaks a u-blox-compatible subset of UBX, u-blox's binary protocol, so ArduPilot drives it with its u-blox driver. Reading that driver, libraries/AP_GPS/AP_GPS_UBLOX.cpp, settled it:
- When a NAV-PVT message arrives ("position, velocity, time"), the driver stores the position, velocity and fix, and takes the time of week from it. It does not read the UTC date and time that NAV-PVT also carries.
- The week number is set in only two places: the handlers for NAV-SOL and NAV-TIMEGPS.
A genuine u-blox receiver sends one of those two messages alongside NAV-PVT. The 626 sends only NAV-PVT. So the week was never set and stayed at 0. ArduPilot treats week 0 as "no GPS time": the system clock is never set from GPS, and the SYSTEM_TIME message the ground station receives carries a Unix time of 0. Skybrush saw a drone with no usable GPS time and raised TIMESYNC.
Why no parameter or module update could fix it
Before touching firmware, we ruled out the cheaper fixes.
- Turning on GPS auto-configuration.
GPS_AUTO_CONFIGmust stay 0 on the 626. The module ships pre-configured, and letting ArduPilot send its u-blox configuration commands risks overwriting that. More to the point, auto-configuration only asks the receiver for messages; it cannot make a receiver send messages it does not implement. - Changing the GPS type or protocol.
GPS1_TYPEset to auto or u-blox both end up in the same driver, with the same two week handlers. - Updating or reconfiguring the 626. We checked with the manufacturer: the UBX output is fixed in the receiver module's own firmware. There is no setting or update that adds NAV-TIMEGPS or NAV-SOL.
That left the flight controller. The information we needed was already arriving, inside every NAV-PVT message, in the UTC date and time fields the driver was ignoring.
Designing the fix
The change is a few dozen lines in the u-blox driver, and three rules shaped it.
1. Fill in the missing number; do not replace the precise one
It is tempting to take the whole time from the UTC date and be done. We did not, for two reasons. ArduPilot represents GPS time as week plus milliseconds of week, and everything downstream (logging, time sync, the system clock) uses that pair. And the time of week is the precise part: the receiver reports it in milliseconds, tied to the measurement epoch. So the receiver's iTOW stays exactly as it was, and the date is used only to answer one question: which week is it?
2. Round against the receiver's time of week
Converting a UTC date to GPS time means adding the leap seconds between them, 18 since 2017, and ArduPilot has that number compiled in. If a receiver's leap-second count differs, or its date lags its time of week by a second, the obvious calculation breaks at exactly the wrong moment: just after the weekly rollover, when the date still lands in the old week while iTOW has already restarted from zero. The drone's clock would then be wrong by a whole week.
So the driver subtracts the receiver's own time of week from the date-derived GPS time, which should land exactly on the start of a week, and rounds to the nearest week:
week = round((unix_seconds + leap_seconds − 315964800 − iTOW_seconds) / 604800)
Here 315964800 is the GPS epoch, 6 January 1980, in Unix seconds, and 604800 is the number of seconds in a week. An error of a few seconds, or of anything less than 3.5 days, rounds to the correct week.
3. Act only until the receiver supplies a week, and only on valid dates
The date-derived week is a fallback, not a replacement:
- It is used only while the receiver has never sent a week. The moment a NAV-SOL or NAV-TIMEGPS arrives, the driver goes back to the receiver's own week, exactly as in the official firmware. A genuine u-blox module behaves as before.
- It is used only when NAV-PVT flags both its date and time as valid, and the date passes a sanity check (year 2020–2099, plausible month and day). Before the receiver has a valid date, nothing changes.
- It is recomputed on every NAV-PVT message, so the week ticks over correctly at the weekly rollover, mid-flight if need be.
- When it first takes effect, the flight controller prints one line,
u-blox 1: GPS week 2441 from NAV-PVT date, so an operator can confirm the fix is active from Mission Planner's Messages tab.
The whole change costs about 300 bytes of flash and touches only AP_GPS_UBLOX.cpp and its header. The published patch is short enough to review in a few minutes.
Testing it before it went near a show
Show drones fly over crowds, so we tested in layers, from arithmetic to hardware.
The formula, 1,305 cases. An independent Python test reproduces the driver's integer arithmetic, including the 32-bit wrap-around and the 16-bit week, and compares every result with an independently computed true GPS week. It covers ordinary instants from 2020 to 2099; every second from 5 s before to 5 s after seven separate week rollovers between 2020 and 2037 (each at UTC Saturday 23:59:42); receivers whose leap-second count is 16 to 20 s, that is up to ±2 s away from ArduPilot's 18; and sub-second offsets of 0, 500 and 999 ms. All 1,305 cases pass.
Is it in the binary? Each build is checked for the from NAV-PVT date message string. The unpatched build does not contain it.
SITL, with a negative control. ArduPilot's software-in-the-loop simulator normally emulates a full u-blox receiver. For the test only, we changed the simulated receiver to behave like the 626: send nothing but NAV-PVT, with a valid UTC date. Then we ran the same scenario twice:
| Patched driver | Unpatched driver | |
|---|---|---|
| GPS fix | 3D | 3D |
| Week message | u-blox 1: GPS week 2440 from NAV-PVT date, matching an independent calculation | none |
Unix time in SYSTEM_TIME | valid, within 1 s of the simulator's clock, no drift | 0, no GPS time |
The unpatched run reproduced the customer's symptom exactly, which is what made the patched run meaningful. The simulator change was reverted afterwards and is not in the firmware.
On a real fleet. The customer flashed the MicoAir743v2 build on their show drones, a mix of MicoAir H743 V2 and H743 V2 AIO 45A flight controllers. With a GPS fix, the drones reported a valid GPS week and correct UTC time, and the TIMESYNC warning cleared in Skybrush Live.
The detour: one board, two names
The hardware test nearly stalled for a reason that had nothing to do with GPS.
The customer's fleet had two kinds of flight controller: a standalone H743 V2 and the H743 V2 AIO 45A, an all-in-one board with a built-in 4-in-1 ESC. ArduPilot has a target called MicoAir743-AIO, so we built that one for the AIO drones as well. Mission Planner refused it: board ID mismatch.
The bootloader was right. The H743 V2 AIO 45A runs the same ArduPilot target as the standalone H743 V2, MicoAir743v2, board ID 1179. MicoAir743-AIO (board ID 1176) is for the older H743 AIO 35A. We had guessed from the product name, and the parameter files could not have told us otherwise, because two boards on the same target produce the same parameters. One file, MicoAir743v2, covers both kinds of drone in that fleet.
What we changed after that:
- We ask for the board line, not the product name. The line Mission Planner prints at connect, such as
MicoAir743v2 0031002A 33335110 35353936, names the target exactly. The guide now starts with finding it. - We do not rely on the bootloader to catch mistakes. It caught this one, but several targets share a board ID (
Pixhawk1,CubeBlackandfmuv3all use 9, for example), and a wrong file for those installs without complaint. The guide lists the shared IDs. - The AIO manual spells it out. The H743 AIO user manual explains how to tell the 45A and 35A boards apart and which firmware each takes.
What we published
- MA-RTK-AIR-626 for Drone Light Shows — Fix the Skybrush TIMESYNC Warning: who needs it, how to install and verify it, how to roll back, and the alternatives that need no custom firmware.
- Skybrush 4.6 firmware for 20 flight controllers, built from the unmodified Skybrush
CMCopter-4.6source (ArduCopter V4.6.3) plus this one change. TheMicoAir743v2build is confirmed on a show fleet; the others are build-verified: they compile, fit in flash and contain the fix, but we have not flown them. Test fly every drone before a show. - The complete source: the patch, the build script and the build record, under the same GPLv3 license as ArduPilot and Skybrush. The firmware is not affiliated with or endorsed by the Skybrush or ArduPilot projects.
What we would tell other integrators
- "u-blox compatible" describes a protocol, not a message set. A receiver can speak valid UBX and still leave out messages a driver depends on. When you qualify a new module, list the messages it actually sends.
- Check the time, not just the fix. A drone can have RTK FIXED and no idea what day it is. Look at the GPS week in the log (
GWkin theGPSmessage) or the Unix time inSYSTEM_TIME. Anything that time-stamps, synchronizes or schedules depends on it. - Keep negative controls. The unpatched SITL run that failed in the same way as the field was the strongest evidence that the patched run tested the right thing.
- Identify boards from what the firmware reports. Product names and parameter files can mislead; the board line at connect cannot.
If you fly the 626 in a show fleet, start with the guide and firmware downloads. For the hardware itself, the MA-RTK Series User Manual covers the 626's specifications and wiring, and the RTK Setup Guide shows how one base station serves the whole fleet.
Where to buy
- MA-RTK-AIR-626, budget RTK for swarms and light shows
- MicoAir H743 V2 flight controller and H743 V2 AIO 45A, both on the
MicoAir743v2build confirmed in a show fleet
For a fleet of 10 or more, email info@robofusion.net for volume pricing.
Written and maintained by the Robofusion engineering team.