GPS-disciplined clock timekeeper sync application
  • C 78.3%
  • CMake 16.4%
  • Python 5.3%
Find a file
Repository files (latest commit first)
Filename Latest commit message Latest commit date
2026-08-04 23:21:59 -07:00
.gitignore Initial commit of GPS-Disciplined DS3231 RTC application with I2C safety checks 2026-08-04 21:21:57 -07:00
CMakeLists.txt Restore Conan package dependency resolution and remove duplicated local driver sources 2026-08-04 23:17:58 -07:00
conanfile.txt Initial commit of GPS-Disciplined DS3231 RTC application with I2C safety checks 2026-08-04 21:21:57 -07:00
LICENSE.txt Update copyright email in LICENSE.txt 2026-08-04 23:21:59 -07:00
main.c Restore final combined application using GP0/GP1 UART0 without GPS software standby 2026-08-04 23:08:05 -07:00
pico_sdk_import.cmake Initial commit of GPS-Disciplined DS3231 RTC application with I2C safety checks 2026-08-04 21:21:57 -07:00
read_serial.py Configure application for UART1 (GP8/GP9) at 9600 baud and direct library compilation 2026-08-04 22:48:46 -07:00
README.md Add standalone deployment, drift, and resync guide to README 2026-08-04 23:16:27 -07:00

GPS-Disciplined DS3231 RTC (GPSD-RTC)

This project implements a GPS-Disciplined Real-Time Clock system for the Raspberry Pi Pico 2 (RP2350). It leverages a high-precision, temperature-compensated DS3231 I2C RTC for continuous timekeeping and uses an ATGM336H GPS+BDS Receiver to automatically establish and maintain atomic-clock accuracy on boot.


⚡ The Synergy (Design Philosophy)

  • The Problem:
    • Real-Time Clock (RTC) modules are extremely low power and maintain accurate time for years on a coin cell battery, but they suffer from minor drift and require a manual configuration process initially to set the correct time.
    • GPS/GNSS receivers obtain absolute UTC time from atomic clock satellites, but they are highly power-hungry (~47mA continuous) and take time to acquire satellite locks.
  • The Solution:
    1. Boot Sync: On startup, the Pico 2 boots up and initializes the DS3231 RTC.
    2. GNSS Lock: It starts up the ATGM336H GPS module, boosts communication to 115200 baud, and sets update rates to 10Hz to acquire a satellite position/time fix as quickly as possible.
    3. RTC Discipline: Once a valid fix is acquired, the Pico 2 extracts the satellite UTC date and time, converts it, programs the DS3231's internal registers, and clears the oscillator stop flag.
    4. Pico Interrupt Disable: Once synchronized, the Pico 2 disables its internal UART RX interrupts to stop processing serial data and reduce CPU overhead. Crucially, the GPS module itself is left active and transmitting, bypassing problematic hardware-level standby configurations.
    5. RTC Timekeeping: The Pico 2 drops into a low-overhead loop, reading and printing sub-second accurate time and temperature directly from the DS3231 RTC, keeping the GNSS module inactive.

Warning

DO NOT SEND SOFTWARE STANDBY COMMANDS TO THE GPS MODULE! An earlier iteration of this project attempted to send $PCAS03,0,0,0,0,0,0,0,0,0,0,0,0 to silence the ATGM336H's serial stream. This configuration is saved to the module's flash/backup SRAM and persists across power cycles, causing the GPS module to boot up completely silent (holding TX at a constant 3.3V high) despite blinking its PPS LED. If a module gets locked into this silent standby state, it must be rescued using the recovery sequence (sending $PCAS03,1,1,1,1,1,1,1,1,1,1,1,1 and $PCAS04,1 at both 9600 and 115200 baud). To avoid this, the current design leaves the GPS module outputting continuously and only disables UART RX interrupts on the Pico side.


🔌 Hardware Wiring Guide

1. DS3231 RTC Connections (I2C0)

  • SDA: Connect to GP4 (Pico Physical Pin 6)
  • SCL: Connect to GP5 (Pico Physical Pin 7)
  • VCC: Connect to 3V3 OUT (Pico Physical Pin 36)
  • GND: Connect to any GND pin (e.g., Pico Pin 8)

2. ATGM336H GNSS Connections (UART0)

  • TXD: Connect to GP1 (RX) (Pico Physical Pin 2)
  • RXD: Connect to GP0 (TX) (Pico Physical Pin 1)
  • PPS: Connect to GP2 (Pico Physical Pin 4)
  • VCC: Connect to 3V3 OUT (Pico Physical Pin 36)
  • GND: Connect to any GND pin (e.g., Pico Pin 3)

🛠️ Build and Compile Instructions

1. Install Conan Dependencies

Before building, run the Conan package manager to pull the standalone source-only drivers (lf-atgm336h and lf-ds3231):

conan install . --output-folder=build --build=missing

2. Configure and Compile

Generate the build system using CMake targeting the Pico 2 (RP2350) board, and compile the firmware:

cd build
cmake -DPICO_BOARD=pico2 ..
make -j$(nproc)

This will produce gps_disciplined_rtc.uf2 in the build/ directory, which can be loaded directly onto your Pico 2 in BOOTSEL mode:

picotool load -x -f gps_disciplined_rtc.uf2

⏱️ Practical Considerations: Standalone Deployment & Drift

1. Why keep the GPS attached?

If the DS3231 keeps time on its own backup battery, why use a GPS at all?

  • Sub-Microsecond PPS Discipline: When GPS is active, the Pico can use the hardware Pulse-Per-Second (PPS) signal to discipline the system clock to stratum-1 accuracy (< 1µs jitter).
  • Set-and-Forget Maintenance: The GPS automatically resolves leap seconds, initial setup configuration, battery failure recovery, and crystal age drift.

2. How long does the RTC keep "good" time?

The DS3231 uses a Temperature-Compensated Crystal Oscillator (TCXO) rated for ±2 ppm accuracy (0^\circ\text{C} to +40^\circ\text{C}):

  • In practice: ±2 ppm translates to roughly ±0.17 seconds of drift per day, or about ±5 seconds per month (~1 minute per year).
  • For sub-second logging precision: The RTC keeps "good time" (under 1 second of drift) for about 5 to 6 days.
  • For human-scale timekeeping: The RTC keeps "good time" (under 1 minute of drift) for an entire year without resyncing.

3. Periodic Resync (Standalone Detached Deployment)

Yes, you can absolutely use this system for periodic resyncs! If your deployment target is indoors, underground, or inside a Faraday-shielded enclosure where GPS signals cannot reach:

  1. Power on the Pico 2 + DS3231 + GPS assembly near a window or outdoors.
  2. Wait for the module to lock, discipline/synchronize the DS3231 register time, and print [SYNC SUCCESS].
  3. Disconnect power, detach the GPS module entirely, and move the Pico 2 + DS3231 to its final indoor location.
  4. The DS3231's backup coin cell battery (CR2032) will keep the synchronized register time alive during transit, and it will run standalone on the internal pull-up fallback mode.
  5. Tune-ups: Periodically (e.g., once a month or once a year, depending on your accuracy requirements), reconnect the GPS module or bring the unit back to a window to run a resync "tune-up."