Repository navigation
Hardware
What the device is made of, how it is wired, and which parts of that are verified rather than assumed. The authoritative detail lives in docs/HARDWARE_BOM.md and docs/HARDWARE_INTEGRATION.md; this page is the orientation and the warnings.
The Waveshare has two physically identical SH1.0 4-pin sockets, one UART and one I2C.
The UART block's rear label reads UART, GND, 3v3, TX, RX. The I2C block's pin order has
never been reported. If its power ordering differs, a board-to-board cable puts 3.3 V onto
a data line and something dies.
Check the label before connecting the receiver. This is the only step in the project that can destroy hardware, and it is still open as #9.
| Ref | Part | Why this one |
|---|---|---|
| H1 | Waveshare ESP32-S3-Touch-AMOLED-2.41-B | 600×450 AMOLED, touch, ESP32-S3R8 with 8 MB PSRAM and 16 MB flash, QMI8658 IMU, RTC, microSD, supplied case |
| H2 | SparkFun GPS-17285 — u-blox NEO-M9N, SMA, Qwiic | 25 Hz navigation rate on four constellations, 3.3 V logic, UART and I2C, UBX |
| H3 | Taoglas Magma X AA.170.301111 |
Covers all four constellations the M9N tracks, including BeiDou B1 at 1561 MHz, which common 1575–1610 MHz antennas miss |
| H4 | High-endurance microSD, 8–32 GB | Session traces and event logs, FAT32 |
| H6 | Fused 5 V vehicle USB supply | Never connect raw vehicle 12 V to the Waveshare board |
Confirmed from the board itself: chip revision v0.2, 16 MB flash, and the fitted card reports as SN32G, 30 GB, FAT.
The antenna band, not its gain, is what decides it. BeiDou B1 sits at 1561.098 MHz, below the 1575–1610 MHz window that most "GPS/GLONASS/Galileo" antennas cover. Fit one of those and BeiDou is quietly absent — the receiver still works, so nothing looks broken, while a quarter of the constellations silently stop contributing.
A newer u-blox part would be a downgrade. The M9N does 25 Hz on four constellations. The M10 manages 10 Hz on four, and 20 Hz only with three and a raised CPU clock. For lap timing, fix rate is the whole point, so the older generation is the right one.
| On GPIO47 (SDA) / GPIO48 (SCL) |
|---|
| Touch controller |
| QMI8658 IMU |
| RTC |
| IO expander (AMOLED enable, tearing effect, touch interrupt) |
GNSS receiver at 0x42, joining via Qwiic |
The receiver is the one participant on that bus with a deadline. At 25 Hz a fix is 40 ms and the receiver's buffer holds roughly 410 ms, so the margin is about ten missed polls — which is less comfortable than it sounds on a device whose UI task has starved before. Bus contention is a real design consideration, not a theoretical one.
Both of the breakout's connectors are Qwiic on the same bus, and its I2C jumper carries
the pull-ups.
| Function | Pins | Bus |
|---|---|---|
| AMOLED QSPI CS / CLK / D0–D3 | GPIO9 / 10 / 11–14 | SPI2_HOST |
| AMOLED reset | GPIO21 | |
| Touch reset | GPIO3 | |
| microSD CS / SCLK / MOSI / MISO | GPIO2 / 4 / 5 / 6 |
SPI3_HOST, SPI mode |
| UART socket | GPIO43 / 44 |
UART0 — also the default console
|
This is the constraint most likely to catch someone out.
GPIO43/44 is UART0, which is the firmware's primary console. The staged transport
plan in
ADR-005
moves GNSS to UART for vehicle use, because UART is pushed by DMA while I2C must be polled.
That puts the receiver on the same two pins the console speaks on.
If both are used at once, log output is transmitted into the receiver and the console driver owns the pin the receiver answers on. So the console has to move to USB Serial/JTAG before GNSS takes the UART socket.
Two practical consequences:
- Do not plan to use UART0 as a permanent diagnostic tap. It is wanted for the receiver. Boot logs are obtainable over USB instead — see below.
- The breakout's UART is plated through-holes only, so the UART stage needs soldering.
I2C is solderless, which is why bring-up uses it. Leave the breakout's
SPIsolder jumper open: closing it disables the UART on those lines.
The module's UART default is 38400 baud, 8N1, per the data sheet. The 115200 figure in SparkFun's hookup guide is their serial monitor, not the module.
make firmware-capture-boot captures a cold boot over the board's own USB-Serial-JTAG port
— the full log from the ROM banner to the application, with no extra hardware.
Two traps, both of which produce silence rather than an error:
- Opening the port and waiting captures nothing. Boot output is written and discarded before a host attaches, so the listener has to hold the port before the reset.
- Pulsing RTS alone boots the ROM download stub, which prints nothing. RTS is wired to EN (reset) and DTR to GPIO0 (boot select), and pyserial asserts both on open. Releasing RTS with GPIO0 still low starts the download stub. An empty capture then reads as "the output was discarded" when it means "the application never ran".
A genuine power cycle cannot be captured this way at all: the USB device is inside the
chip, so cutting power destroys the port the listener is holding. An RTS reset is a chip
reset (rst:0x15 USB_UART_CHIP_RESET) and the handle survives it. Only a separate USB-UART
adapter on the UART socket could see a post-power-cycle boot, since its own connection to
the host is independent of the target's power — and that socket is wanted for the receiver.
Background in #181.
TrackSessionTimer GPS bootstrap
imu: ready
sd-card: mounted
sd-card name=SN32G capacity=30424 MB fs-total=30409 MB free=30408 MB
settings: source=0 current-format=1, mode track-day
track catalog: built (26 discovered, 26 loaded, 0 rejected, cap 32)
gnss: transport attached over i2c
ready screen presented on the 600x450 panel
settings: source=0 means the stored configuration was read in its current format; a
non-zero value means it was migrated from an older one on that boot. The track counts depend
on what is on the card, and rejected or a truncation warning means definitions did not
make it into the catalog.
| State | |
|---|---|
| Display, touch, gesture UI | working on hardware |
| microSD, settings persistence, session lifecycle | working, survives power cycle |
| QMI8658 IMU, gyro-tracked attitude, G recording | working |
| Boot log capture over USB | working |
| GNSS receiver | never connected. The transport attaches and reports itself at boot, but no part of the chain has met a real receiver |
| RTC | present, not driven |
| Vehicle power path, enclosure, antenna mounting | not built |
The receiver and antenna are in hand. The Qwiic cables are not, and that single missing cable is what stands between the device and a lap time.
In order, because the first step is the irreversible one:
- Read the I2C socket's label and confirm its pin order before connecting anything (#9).
- Connect the receiver over Qwiic and check GPS Only mode: a satellite count that climbs, then a fix, outdoors.
- Confirm bus faults and a silent receiver are distinguishable on the Diagnostics GNSS page (#178).
- Starve the poll deliberately and watch the gap counter trip on the device. The host tests prove the logic; they do not prove the wiring (#18).
- Select Donington Park and confirm the timing engine arms (#139).
- Only then the UART stage, which needs soldering and the console moved first (ADR-005).