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 <noreply@anthropic.com>
This commit is contained in:
mikkeli
2026-10-09 19:18:16 +09:00
parent fe284ce540
commit 28e056dc4d
2 changed files with 70 additions and 20 deletions
+40 -13
View File
@@ -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>,<dpo>` 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).