Bearing
Position, time, and heading for every module on the bus. A small GNSS node that tells the rest of your rig where it is and what time it is, even when the sky is the only network around.
What's Inside / Module
The GNSS Module
A standalone GNSS receiver that publishes position, speed, heading, altitude, and precise time onto the TrailCurrent CAN bus at 30 Hz, refreshed from the GNSS receiver ten times a second. Any other module on the bus can listen in.
Built around the Waveshare ESP32-S3 RS485 CAN board paired with a DFRobot Gravity multi–constellation GNSS receiver. GPS, BeiDou, and GLONASS out of the box. No custom PCB — just two boards joined by four soldered wires (I2C, power, ground) and a two–piece 3D printed case with a Deutsch connector for power and CAN, and an SMA connector for the active antenna.
At a Glance
What's inside the case and what comes out of the connectors.
Compute
Waveshare ESP32-S3 RS485 CAN board. Dual–core Xtensa LX7 running pure C on ESP-IDF 5.5, with an on-board CAN transceiver and USB-C for flashing. 8 MB flash with dual OTA partitions, so updates are safe and roll back on their own if something goes wrong.
GNSS Receiver
DFRobot Gravity GNSS module on I2C. GPS, BeiDou, and GLONASS with seven selectable constellation modes. Active antenna over SMA on the outside of the case, so you can mount the module where it's convenient and put the antenna where it can see the sky.
Vehicle Network
500 kbps CAN bus through the Waveshare board's on-board NXP TJA1051T transceiver and the ESP32-S3 TWAI peripheral, broken out to a Deutsch DTM 4-pin connector. Position, speed, heading, altitude, and timestamp publish at 30 Hz on the bus, refreshed from the GNSS receiver at 10 Hz. Power and bus share a single cable.
Bill of Materials
Everything you need to build one Bearing, top to bottom.
| Qty | Part | Description | Source |
|---|---|---|---|
| 1 | Waveshare ESP32-S3 RS485 CAN Board | ESP32-S3 dev board with on-board CAN transceiver (NXP TJA1051T), RS485 driver, USB-C, and a 7–36 V wide-input power rail. Off-the-shelf. | Waveshare |
| 1 | DFRobot Gravity GNSS Module | Multi-constellation GNSS receiver (GPS + BeiDou + GLONASS) with I2C interface. Wired to the ESP32-S3 board with four soldered leads: SDA, SCL, 3V3, and GND. | DFRobot |
| 1 | Waveshare GPS External Antenna | Active GPS patch antenna with integrated LNA, magnetic base, and a 3 m SMA lead. Mounts externally wherever the sky is clear; plugs straight into the SMA bulkhead on the case. | Waveshare |
| 1 | U.FL to SMA Bulkhead Pigtail | Short straight coax pigtail with a U.FL (IPEX) plug on one end and an SMA bulkhead jack on the other. The U.FL end clips directly onto the DFRobot GNSS module's on-board U.FL connector; the SMA end mounts through the short side of the case. Neither the GNSS module nor the Waveshare antenna ships with this — buy it separately. | Generic |
| 1 | Deutsch DTM04-4P Connector | 4-pin receptacle carrying 12 V power and the CAN H / CAN L pair. The TrailCurrent standard for vehicle bus interconnects. | TE Connectivity |
| 1 | Case Bottom | 3D printed. 110 × 91 × 22 mm overall, with four integrated mounting tabs. Openings on the short side for the Deutsch and SMA connectors. ABS or ASA recommended. | 3D printed (STL below) |
| 1 | Case Cover | 3D printed. 110 × 65 × 8.5 mm. Embossed TrailCurrent logo on the top face. Seats between the four mounting tabs of the bottom. ABS or ASA recommended. | 3D printed (STL below) |
| 4 | M2.5 × 5 mm Machine Screws | Secure the cover to the case bottom at the four corners. Stainless or zinc-plated steel. | Hardware store |
Technical Drawings
Orthographic views of the full assembly, straight out of the FreeCAD model.
Top View
Embossed logo on the cover, four M2.5 screws, and four mounting tabs at the corners.
Front View
The long side of the case. The SMA antenna jack pokes out of the short end on the left.
Connector Side
SMA antenna jack and Deutsch DTM 4-pin connector for power and CAN.
Blank Side
The opposite short end. No openings — this is usually the face you mount toward a bulkhead.
Overall dimensions: 114 × 91 × 30 mm. Source CAD lives in the CAD folder of the Bearing repo.
3D Printed Parts
Two pieces, ABS. A ready-to-slice .3mf project file with both plates and the full print profile lives in the CAD folder.
Case Bottom
The main body. Integrated bosses hold the Waveshare ESP32-S3 board and the DFRobot GNSS module side by side, openings on one short end frame the SMA and Deutsch connectors, and four mounting tabs at the corners let you bolt it wherever it needs to live.
- Dimensions: 110 × 91 × 22 mm
- Material: ABS (or ASA)
- Nozzle: 0.4 mm
- Layer height: 0.2 mm
- Walls: 6 perimeters
- Infill: 100% (zig–zag)
- Supports: Tree (auto), 30° threshold
- Nozzle temp: 270 °C (260 °C first layer)
- Bed temp: 90 °C
- File:
BodyCaseBottom.stl
Case Cover
The lid. A flat plate with the TrailCurrent logo embossed on the top face and four clearance holes for the cover screws. Seats inside the four mounting tabs of the bottom half. Print with the logo face up for the cleanest finish.
- Dimensions: 110 × 65 × 8.5 mm
- Material: ABS (or ASA)
- Nozzle: 0.4 mm
- Layer height: 0.2 mm
- Walls: 6 perimeters
- Infill: 100% (zig–zag)
- Supports: None (prints flat, logo face up)
- Nozzle temp: 270 °C (260 °C first layer)
- Bed temp: 90 °C
- File:
BodyCaseCover.stl
Hardware
Two off-the-shelf boards, four wires between them. No custom PCB, and the only soldering is the four wires from the main board to the GNSS module.
MCU Board
Waveshare ESP32-S3 RS485 CAN board. Dual–core Xtensa LX7 with integrated WiFi and Bluetooth, 8 MB flash, USB-C for flashing, and an on-board NXP TJA1051T CAN transceiver. 8 MB flash is split into two OTA partitions so updates land on the inactive half and the bootloader swaps them on reboot.
Power
12 V comes in over the Deutsch connector and lands on the Waveshare board's wide-input regulator (7–36 V range). The regulator feeds both the ESP32-S3 and the DFRobot GNSS module, so there's only one power path in the whole enclosure.
CAN Interface
The board's on-board CAN transceiver connects straight to the ESP32-S3 TWAI peripheral. 500 kbps, standard 11-bit identifiers, routed out through the Deutsch connector alongside the power pair. The RS485 side of the board is unused on Bearing.
GNSS Interface
The DFRobot Gravity GNSS module hangs off I2C with four hand-soldered wires from the ESP32-S3 board: SDA, SCL, 3V3, and GND. We recommend soldering rather than using header pins or terminal blocks — it's more reliable in a vehicle environment where everything is constantly vibrating. The active antenna connects through a straight U.FL-to-SMA bulkhead pigtail that clips directly onto the GNSS module's on-board U.FL connector, with the SMA end mounted through the case wall.
Assembly
Start to finish in under an hour, most of which is the print.
-
1
Print the case
Easiest path: open
TrailCurrentBearingCase.3mffrom the CAD folder in Bambu Studio (or Orca) and print both plates. ABS, 0.2 mm layers, 100% infill, 6 walls, tree supports on the bottom. If you're slicing from STL, match those settings; the cover prints flat with no supports. -
2
Flash the firmware
On the bench, plug the Waveshare ESP32-S3 RS485 CAN board into USB-C and flash the Bearing firmware straight from your browser using the TrailCurrent Flasher. After the first flash, all future updates happen over the air through the CAN bus trigger protocol.
-
3
Wire the GNSS module
Cut four short leads and solder them between the ESP32-S3 board and the DFRobot GNSS module: SDA, SCL, 3V3, and GND. We recommend soldering directly to both boards rather than using headers or terminal blocks — it's more reliable in a vibrating vehicle. Clip the U.FL end of the SMA bulkhead pigtail directly onto the GNSS module's on-board U.FL connector while you have it on the bench.
-
4
Drop it in the case
Set the Waveshare board and the DFRobot GNSS module into the bottom half of the case. The integrated bosses hold both boards in place.
-
5
Wire the connectors
Press the Deutsch DTM04-4P receptacle into its opening and wire it to the Waveshare board's power input and CAN H / CAN L terminal blocks. Press the SMA end of the pigtail into its opening next to the Deutsch connector and tighten its bulkhead nut.
-
6
Close the case
Drop the cover on between the four mounting tabs. Secure with four M2.5 × 5 mm screws at the corners. Snug, not cranked down; the plastic threads are gentle.
-
7
Plug it in
Mount the active antenna somewhere it can see the sky and plug the Deutsch connector into the TrailCurrent bus. Within a minute or two Bearing is publishing position, speed, heading, altitude, and timestamp at 30 Hz, with fresh GNSS fixes arriving ten times a second.
CAN Protocol
Four outbound messages, everything a downstream module needs to know where and when it is.
| ID | Name | DLC | Payload |
|---|---|---|---|
0x06 |
DateTime | 7 | UTC year, month, day, hour, minute, second from GNSS time. |
0x07 |
Sat / Speed / Course | 6 | Satellite count, ground speed (knots × 100), course (degrees × 10), and active constellation mode. |
0x08 |
Altitude | 4 | Altitude in meters × 100, 32-bit big–endian. |
0x09 |
Lat / Lon | 8 | Latitude and longitude as sign byte + 24-bit scaled value (degrees × 10000). |
Graceful Bus Behavior
A TX_ACTIVE / TX_PROBING state machine lets any module join or leave the bus without breaking the others. Three TX failures in a row drop Bearing into a 2-second probe; an ACK from any peer snaps it back to full 30 Hz output.
OTA Over CAN
Broadcast CAN ID 0x00 with Bearing's last three MAC
bytes and it joins WiFi, spins up an HTTP server, and accepts a
new firmware image. It writes to the inactive OTA slot and
reboots; if anything fails, it returns to normal operation.
mDNS Self–Discovery
When CAN ID 0x02 is broadcast, Bearing advertises
itself over mDNS as _trailcurrent._tcp with its type,
CAN ID, and firmware version. Headwaters scoops that up to
inventory every module on the bus automatically.
Build Your Own Bearing
Every file is in the repository: KiCAD sources, CAD, ESP-IDF firmware, and the CAN protocol spec. Fork it, build it, make it yours.