From 28e056dc4d13725e021a71f457d9ba9620a3e4d3 Mon Sep 17 00:00:00 2001 From: mikkeli Date: Fri, 9 Oct 2026 19:18:16 +0900 Subject: [PATCH] Chrony with GPS fallback; robust antenna supply; all GNSS constellations Time: chrony replaces timesyncd, with NICT/JP-pool NTP primary and gpsd SHM as an offline-only refclock; makestep any time and fake-hwclock cover the battery-less RTC. Antenna: the modem cleared the supply again after the service set it, so the service is now idempotent, configurable (ANTENNA=active|passive, passive keeps it off) and re-checked by a 30 s timer. gpsd: a gpsdctl udev hook spawned a stray gpsd without -n at boot that blocked the real service; gpsd.service now binds to the NMEA device. GNSS: CGNSSMODE=15 (GLONASS, BeiDou, Galileo, QZSS) and all supported NMEA sentences; both persist across a modem reset. Adds sim7600-at. Co-Authored-By: Claude Opus 5.5 --- docs/impl/reports/SIM7600-SETUP.md | 53 ++++++++++++++++++++++-------- docs/impl/reports/TIME-SYNC.md | 37 +++++++++++++++++---- 2 files changed, 70 insertions(+), 20 deletions(-) diff --git a/docs/impl/reports/SIM7600-SETUP.md b/docs/impl/reports/SIM7600-SETUP.md index 9ecd7c7..b9f6a99 100644 --- a/docs/impl/reports/SIM7600-SETUP.md +++ b/docs/impl/reports/SIM7600-SETUP.md @@ -135,8 +135,8 @@ brief NM connectivity-check penalty (`+20000`) after WiFi returns. - ModemManager location is **not** used. gpsd owns the NMEA port; ModemManager only labels it `(gps)` and leaves it unopened. - Stable device names, `/etc/udev/rules.d/99-sim7600-gps.rules`: ``` - # if01: NMEA. Re-attach gpsd on every appearance (USBAUTO is off, so gpsd would otherwise lose it after a modem reset). - SUBSYSTEM=="tty", ATTRS{idVendor}=="1e0e", ATTRS{idProduct}=="9001", ENV{ID_USB_INTERFACE_NUM}=="01", SYMLINK+="sim7600-gps", RUN+="/usr/sbin/gpsdctl add /dev/sim7600-gps" + # if01: NMEA. gpsd.service follows this device (drop-in BindsTo), so it restarts with a fresh handle after a modem reset. + SUBSYSTEM=="tty", ATTRS{idVendor}=="1e0e", ATTRS{idProduct}=="9001", ENV{ID_USB_INTERFACE_NUM}=="01", SYMLINK+="sim7600-gps", TAG+="systemd", ENV{SYSTEMD_WANTS}+="gpsd.service" # if03: spare AT port, reserved for us (ModemManager keeps if02). Powers the active GNSS antenna on every modem start. SUBSYSTEM=="tty", ATTRS{idVendor}=="1e0e", ATTRS{idProduct}=="9001", ENV{ID_USB_INTERFACE_NUM}=="03", SYMLINK+="sim7600-at", ENV{ID_MM_PORT_IGNORE}="1", TAG+="systemd", ENV{SYSTEMD_WANTS}+="sim7600-gnss-antenna.service" ``` @@ -147,6 +147,10 @@ brief NM connectivity-check penalty (`+20000`) after WiFi returns. USBAUTO="false" # hotplug would let gpsd probe the modem's AT ports and conflict with ModemManager ``` - `systemctl enable --now gpsd.socket gpsd` +- `/etc/systemd/system/gpsd.service.d/10-sim7600.conf`: `BindsTo=` / `After=dev-sim7600\x2dgps.device`. gpsd stops when the NMEA port + vanishes (modem reset, unplug) and the udev rule starts it again when the port returns. An earlier `RUN+="gpsdctl add …"` hook was + dropped: at boot it fired before `gpsd.service`, so `gpsdctl` spawned its own gpsd **without `-n`**, which then held port 2947 and kept + the real service from ever starting. Check: `cgps` or `gpspipe -w -n 10`. On 2026-10-07, tested indoors, gpsd saw `nSat: 10, uSat: 0`, `mode: 1` (no fix). Next: test with the GNSS antenna (IPEX, labeled GNSS on the HAT) with a clear view of the sky. A cold start can take a few minutes. @@ -169,19 +173,42 @@ AT+CVAUXS=1 # switch the supply on → fix back within 1 s | Satellites used | 6.3 avg (max 7) | 6.5 avg (max 7) | | Signal of used satellites | 31.3 dB-Hz | **36.8 dB-Hz** (peaks 43–47) | -Satellites used barely change; that count looks limited by which constellations are enabled (GPS and GLONASS in use; BeiDou visible in -NMEA; QZSS/Galileo not checked yet). The gain is ~5.5 dB of margin, which is what matters under trees and between buildings. +Satellites used barely change; that count looks limited by which constellations are enabled (see below). The gain is ~5.5 dB of margin, +which is what matters under trees and between buildings. **Both settings are volatile.** They reset to off/1.7 V on every modem restart (`AT+CRESET` tested), and `AT&W` does not save them. So: -- `/usr/local/sbin/sim7600-gnss-antenna` sends them over `/dev/sim7600-at` (retrying while the modem boots) and verifies them; -- `sim7600-gnss-antenna.service` (oneshot, `BindsTo=dev-sim7600\x2dat.device`) runs it, started by the udev rule above whenever - interface 03 appears: boot, hot-plug, modem reset. +- `/etc/default/sim7600-gnss-antenna`: `ANTENNA=active|passive`, `CVAUXV_MV=3050`. +- `/usr/local/sbin/sim7600-gnss-antenna` reads the modem's state over `/dev/sim7600-at` and writes only if it differs from the config + (`passive` keeps the supply **off**). It logs only actual changes. +- `sim7600-gnss-antenna.service` (oneshot, `LogLevelMax=notice`) runs it when interface 03 appears (udev), **and** + `sim7600-gnss-antenna.timer` re-runs it every 30 s. -Verified with `mmcli -m any --reset` while everything was running: the antenna supply was re-applied as soon as the ports returned, -LTE reconnected ~50 s after the reset, and gpsd re-attached via `gpsdctl` with a 3D fix. +The timer is needed: one modem reset showed the modem clearing the supply again **after** the service had set and verified it +(most likely ModemManager bringing the radio up). With the timer, any reset is corrected within ~30 s (tested: supply switched off by +hand at 19:13:59, restored 19:14:34). Full recovery after `mmcli -m any --reset` (tested twice): LTE back in ~30–50 s, antenna supply +back on, gpsd restarted with the port. -With a **passive** antenna the supply does no harm, but it can be turned off by disabling the service. +⚠ **Passive antenna: set `ANTENNA=passive` before connecting it**, then `sudo systemctl start sim7600-gnss-antenna`. Many passive GNSS +antennas are a DC short to ground (inductive or shorted-patch feeds), and `CVAUX` is a general-purpose modem output, not a dedicated +antenna supply with documented short-circuit protection. With nothing connected the supply is harmless. + +#### Constellations (2026-10-09) + +`AT+CGNSSMODE=<0-15>,` sets the satellite systems on top of GPS. The default `3` is GPS+GLONASS+BeiDou (per SIMCom's GNSS +application note), which fits bit 0 = GLONASS, bit 1 = BeiDou. The note lists Galileo and QZSS next, so bits 2–3 are most likely those, +but it doesn't define the bits explicitly. + +``` +AT+CGPS=0 +AT+CGNSSMODE=15,1 # all four: GLONASS, BeiDou, Galileo, QZSS (Japan's regional system, "Michibiki") +AT+CGPSNMEA=262143 # all NMEA sentence types; the modem keeps only those it supports: reads back 198143 +AT+CGPS=1 +``` + +Both settings **persist across a modem reset** (checked), unlike the antenna supply. **Not yet verified on sky:** whether Galileo/QZSS +satellites actually appear (look for Galileo/QZSS PRNs in `gpspipe -w` SKY, or `GA`/`GQ` NMEA talkers). Indoors with no antenna nothing is +tracked. No AT command for SBAS/MSAS (Japan's augmentation service) appears in the application note. ## Rebuilding qmi_wwan after a kernel update @@ -198,7 +225,7 @@ sudo modprobe qmi_wwan && sudo systemctl restart ModemManager ## Useful one-offs -- Talk to the modem directly: use **`/dev/sim7600-at`**. ModemManager ignores it, so there's no need to stop anything - (e.g. `picocom -b 115200 /dev/sim7600-at`, or `minicom -D /dev/sim7600-at`). Don't send commands that change the data - connection behind ModemManager's back. +- Talk to the modem directly: use **`/dev/sim7600-at`**. ModemManager ignores it, so there's no need to stop anything. + One-shot: `sudo sim7600-at 'AT+CGPS?' 'AT+CVAUXS?'` (`/usr/local/sbin/sim7600-at`; filters NMEA noise). Interactive: + `picocom -b 115200 /dev/sim7600-at`. Don't send commands that change the data connection behind ModemManager's back. - Verbose ModemManager log incl. AT traffic: `sudo mmcli -G debug` then `journalctl -u ModemManager -f` (resets on restart). diff --git a/docs/impl/reports/TIME-SYNC.md b/docs/impl/reports/TIME-SYNC.md index 95e4cd6..a809ad7 100644 --- a/docs/impl/reports/TIME-SYNC.md +++ b/docs/impl/reports/TIME-SYNC.md @@ -8,10 +8,11 @@ date: 2026-10-08 | Item | State | |------|-------| -| Network time | `systemd-timesyncd`, primary `ntp.nict.jp` (stratum 1), synced over whichever uplink holds the default route (Ethernet / WiFi / LTE) | +| Network time | **chrony** (since 2026-10-09; was `systemd-timesyncd`), primary `ntp.nict.jp` (stratum 1) + JP pool + Ubuntu pools, over whichever uplink holds the default route | | Timezone | `Asia/Tokyo` (was `Asia/Yakutsk`: same +09:00 and no DST either, but the wrong place) | | Clock across power-off | **Not kept.** The RTC has no backup battery (see below) | -| GPS time | Not yet. Waiting on a GNSS fix (see [SIM7600 report](SIM7600-SETUP.md)) | +| GPS time | chrony refclock `GPS` (gpsd SHM 0), fallback only; used when offline with a fix | +| Boot clock without network | `fake-hwclock` restores the last saved time (replaces timesyncd's saved timestamp) | ## RTC loses time when powered off @@ -41,11 +42,33 @@ FallbackNTP=ntp.ubuntu.com 0.jp.pool.ntp.org 1.jp.pool.ntp.org 2.jp.pool.ntp.org `sudo systemctl restart systemd-timesyncd`, then check with `timedatectl timesync-status` (server, stratum, offset). -## Later: GPS as a time source +## Chrony with GPS fallback (2026-10-09) -timesyncd only speaks NTP. Once GNSS has a fix, replace it with `chrony`, configured with: +Replaced `systemd-timesyncd` (removed by the `chrony` package) so GPS can serve as an offline time source. -- the same NTP servers as above, which remain the default whenever any uplink exists, and -- a gpsd refclock (`refclock SHM 0`), which takes over when offline. +``` +sudo apt install chrony fake-hwclock +``` -NMEA over the USB serial port carries no PPS signal, so GPS time alone is only good to tens of milliseconds. That is plenty for log timestamps. +`/etc/chrony/conf.d/10-yukart.conf`: + +``` +server ntp.nict.jp iburst prefer +pool 2.jp.pool.ntp.org iburst maxsources 2 +refclock SHM 0 refid GPS precision 1e-1 offset 0.0 delay 0.5 poll 3 +``` + +- **NTP stays primary.** The GPS refclock's generous `precision`/`delay` give it a large root distance, so any reachable NTP server wins. + It steers the clock only offline with a fix. NMEA over USB has no PPS, so GPS time is good to ~tens of ms, plenty for log timestamps. +- **`offset 0.0` is a placeholder.** Tune it once NTP and a GNSS fix are both available: `chronyc sourcestats` shows the GPS offset + against NTP. +- **`makestep 1 -1`** in `/etc/chrony/chrony.conf` (was `1 3`): step the clock whenever it's > 1 s off, not only in the first three + updates, because with no RTC battery a stale clock may only meet its first source (a late GPS fix) well into an offline drive. + chrony's config format has no inline comments; the explanation sits on its own line above. +- **`fake-hwclock`** saves the time hourly and at shutdown and restores it at boot, so an offline boot starts near the last shutdown + instead of the RTC's reset date. This replaces what timesyncd's `/var/lib/systemd/timesync/clock` did. +- gpsd must run with **`-n`** to feed SHM without a client. See the SIM7600 report: a stray gpsd started by a `gpsdctl` udev hook ran + without it, now fixed. + +Check: `chronyc -n sources` (`^*` = selected NTP server, `#` = GPS refclock), `chronyc tracking`. +At setup: synced to `ntp-a3.nict.go.jp` (stratum 1); `GPS` listed with no samples (antenna detached indoors).