Solstice
Every watt in, every amp out. Solstice bridges a Victron MPPT solar controller and SmartShunt onto the CAN bus so the rest of your rig knows exactly what the sun is doing and exactly where the battery stands, in real time.
What's Inside / Module
The Solar & Battery Gateway
One small black box in your rig that listens to Victron and speaks CAN. Solar harvest on one side, battery state of charge on the other, and a single module reporting all of it to Headwaters at 30 Hz.
Built around the Waveshare ESP32-S3 RS485 CAN board. One UART runs VE.Direct to a Victron MPPT charge controller (with bidirectional HEX SET for load control). A second UART reads VE.Direct from a SmartShunt in parallel. The firmware parses both TEXT streams and republishes the values on the TrailCurrent CAN bus at 500 kbps. WiFi credentials and OTA updates travel in over the bus; no local config needed.
At a Glance
One module. Two Victron talkers. The whole energy picture on the bus.
Solar In
Reads VE.Direct TEXT from a Victron MPPT charge controller
at 19200 baud: panel voltage, panel current, solar
watts, battery voltage, charge state, and error codes.
Republishes as CAN message 0x2C (solar basics)
and 0x2D (solar current) every 33 ms.
Battery In
A second UART reads VE.Direct TEXT from a Victron
SmartShunt in parallel: battery voltage, current, state of
charge, wattage, and time–to–go. Published as
CAN messages 0x23 (voltage, current, SOC) and
0x24 (watts, TTG). This replaces the retired
Ampline module.
Load Control Out
Listens for CAN message 0x2E from Headwaters
and writes a VE.Direct HEX SET to the MPPT's load-output
register. Turn the Victron load relay on, off, or back to
its default schedule from anywhere on the bus, your phone,
or the PWA dashboard.
Bill of Materials
Everything you need to build one Solstice, top to bottom.
| Qty | Part | Description | Source |
|---|---|---|---|
| 1 | Waveshare ESP32-S3-RS485-CAN | ESP32-S3 industrial board with on-board CAN transceiver and RS485, wide 6–36 V DC input, screw-terminal I/O, and a 2×10 IDC ribbon header that carries both VE.Direct UART pairs to the MPPT and SmartShunt. Datasheet. | Waveshare |
| 2 | Deutsch DTM04-4P Connector | Sealed 4-pin receptacles, one on each short end of the case. One carries 12 V power and the TrailCurrent CAN pair (CAN-H, CAN-L). The other lands the two Victron VE.Direct serial pairs on a single ribbon cable run. Solid grey TPA with orange wedge lock and silver-plated contact pins. | TE Connectivity |
| 1 | Victron MPPT Charge Controller | Any Victron SmartSolar MPPT with a VE.Direct port. Solstice talks to the TEXT protocol at 19200 baud and issues HEX SET to the load-output register (0xEDAB) when the bus requests a load state change. |
Victron Energy |
| 1 | Victron SmartShunt | Any Victron shunt with a VE.Direct port that meets your setup's amperage requirements, wired across the battery bank for state of charge, voltage, current, wattage, and time–to–go. Solstice reads the shunt's VE.Direct TEXT output RX-only. | Victron Energy |
| 1 | 2×10 IDC Ribbon Cable | Generic 20-position IDC ribbon cable, 2.0 mm pitch, sized to match the Waveshare board's 2×10 GPIO pin header. One end crimps onto the Waveshare header; the other end breaks out to the two VE.Direct pigtails going to the MPPT and shunt. See solstice-ribbon-cable.svg for the wire-to-GPIO mapping. | Hardware store |
| 1 | Case Bottom | 3D printed. 90 × 110 × 23 mm (including mounting tabs). Integrated standoffs for the Waveshare board, two DTM connector ports on opposite short ends, and four mounting tabs at the corners. Black ABS. | 3D printed (STL below) |
| 1 | Case Cover | 3D printed. 65 × 110 × 7.5 mm. Embossed TrailCurrent logo on the top face, "TC" and "VE" call-outs on opposite corners, and four clearance holes for the cover screws. Black ABS. | 3D printed (STL below) |
| 2 | M2.5 × 4 mm Machine Screws (board mount) | Secure the Waveshare board to its two integrated standoffs inside the case bottom. Black pan-head to match the case. | Hardware store |
| 4 | M2.5 × 6 mm Machine Screws (cover) | Close the cover onto the case bottom at the four corners. Black pan-head. | Hardware store |
Technical Drawings
Orthographic views of the full assembly, straight out of the FreeCAD model.
Top View
Embossed TrailCurrent logo centered on the cover, "TC" and "VE" call-outs on opposite corners, and four cover screws at the corners. Four mounting tabs flare out from the body; the two DTM connectors peek out of the short ends.
Front (Connector End)
Looking straight at the Deutsch DTM04-4P receptacle. Four silver-plated pins in a grey TPA housing with the orange secondary lock visible on the wire-entry side. This is where 12 V power and the CAN pair land.
Right Side
The long profile. Cover seam runs along the top, mounting tabs flare at the corners, and the DTM connectors protrude slightly past the short ends for cable clearance.
Left Side
Mirror of the right side. The case is symmetric end-to-end, so Solstice drops into the rig the same way no matter which short end points where.
Overall dimensions: 90 × 115 × 27.5 mm (includes mounting tabs and the DTM connector protrusions). Cover area on its own is 65 × 110 mm. Source CAD lives in the CAD folder of the Solstice repo.
3D Printed Parts
Two pieces, black ABS, single filament. A ready-to-print project lives on Makerworld, and the raw .3mf and STL files are in the CAD folder of the repo.
Case Bottom
The main body. Integrated standoffs hold the Waveshare board, two DTM04-4P openings on opposite short ends, and four mounting tabs at the corners for the install. Prints with the open top facing up so the walls grow straight off the build plate.
- Dimensions: 90 × 110 × 23 mm (with tabs)
- Material: Black ABS
- Nozzle: 0.4 mm
- Layer height: 0.2 mm
- Walls: 2 perimeters
- Infill: 15% grid
- Orientation: Open side up (standoffs point at the nozzle)
- Supports: Tree (auto), enabled
- Nozzle temp: 270 °C
- Bed temp: 90 °C
- File:
BodyTrailCurrentSolsticeEnclosureBottomV4.stl
Case Cover
The lid. Embossed TrailCurrent logo centered on the top face, "TC" and "VE" call-outs on opposite corners, and four clearance holes for the cover screws. Prints flat with the logo face up so the embossed detail comes off the nozzle cleanly.
- Dimensions: 65 × 110 × 7.5 mm
- Material: Black ABS
- Nozzle: 0.4 mm
- Layer height: 0.2 mm
- Walls: 2 perimeters
- Infill: 15% grid
- Orientation: Logo face up
- Supports: Tree (auto), enabled
- Nozzle temp: 270 °C
- Bed temp: 90 °C
- File:
BodyTrailCurrentSolsticeEnclosureCoverV1.stl
Assembly
Drop the Waveshare board in, land the two DTM4 connectors, run the ribbon cable, close the cover.
-
1
Print the case
Open
TrailCurrentSolsticeEnclosure.3mffrom the CAD folder in Bambu Studio (or Orca). Black ABS, 0.2 mm layers, 15% grid infill, 2 walls, tree supports on the bottom. The cover prints flat with no supports needed. -
2
Flash the Waveshare board
On the bench, clone the Solstice repo, source the ESP-IDF 5.5 environment, run
idf.py set-target esp32s3andidf.py build flash monitor. First boot, the board sits quiet waiting for WiFi credentials over CAN from Headwaters. -
3
Mount the Waveshare board
Lower the ESP32-S3-RS485-CAN board into the case bottom so its terminal blocks line up with the interior mounting standoffs. Drive two M2.5 × 4 mm black pan-head screws through the board into the standoffs. Snug, not cranked down; the printed threads are gentle.
-
4
Press in the DTM connectors
Two Deutsch DTM04-4P receptacles, one on each short end. Press each through its opening from outside and retain with the case-provided lip. One connector lands 12 V / GND / CAN-H / CAN-L to the Waveshare screw terminal. The other feeds the two VE.Direct serial pairs into the case so the ribbon cable can carry them across to the Waveshare GPIO header.
-
5
Route the ribbon cable
Plug the 2×10 IDC ribbon onto the Waveshare board's GPIO header. The other end breaks out into two VE.Direct pigtails: one to the Victron MPPT (GPIO 3 / GPIO 14 for TX / RX), one to the shunt (GPIO 4 for RX-only). See solstice-ribbon-cable.svg for the exact pin mapping.
-
6
Close the case
Drop the cover on with the logo facing up and the "TC" / "VE" call-outs oriented toward the right short end. Secure with four M2.5 × 6 mm black pan-head screws at the corners.
-
7
Hook it up
Mate the DTM cables in the rig: 12 V and the CAN pair to the vehicle bus, and the VE.Direct pigtails to the MPPT and SmartShunt VE.Direct ports. Power up and watch Solstice start publishing CAN IDs
0x23,0x24,0x2C, and0x2Dto Headwaters.
CAN Bus Protocol
Seven message IDs at 500 kbps. Every 33 ms, or on demand.
| CAN ID | Direction | Contents |
|---|---|---|
0x23 |
TX (every 33 ms) | Shunt basic data 1: battery voltage, battery current, state of charge. |
0x24 |
TX (every 33 ms) | Shunt basic data 2: battery wattage and time-to-go. |
0x2C |
TX (every 33 ms) | Solar basics: panel voltage, solar watts, battery voltage, solar status. |
0x2D |
TX (every 33 ms) | Solar current: sign byte plus magnitude. |
0x2E |
RX | Load control: 0x00=OFF, 0x01=ON, 0x04=Default. Triggers a VE.Direct HEX SET on the MPPT's load register. |
0x00 |
RX | OTA trigger. Matches the last 3 bytes of the device WiFi MAC; wakes Solstice to join WiFi and expose an HTTP OTA endpoint for 3 minutes. |
0x04 |
TX (boot once) | Firmware version report. Last 3 bytes of MAC + semver major/minor/patch. Headwaters uses this to track the running build. |
Full wiring diagram lives in DOCS/solstice-pinout.svg on GitHub.
Build Your Own Solstice
Every file is in the repository: KiCAD-compatible pinout docs, ESP-IDF firmware, FreeCAD enclosure, and the Makerworld print profile. Fork it, build it, make it yours.