2026-06-12

Making devices talk: working with CAN bus
Almost every project on this site has CAN somewhere in it. It is the robust, two-wire bus that vehicles and industrial gear have used for decades — a BMS, a charger, a motor controller and a dashboard can all sit on the same pair of wires and take turns speaking.
The catch is that CAN defines how messages travel, not what they mean. Two devices can share a bus and still be talking past each other: different message IDs, different scaling, different assumptions. That last mile is where most of the work lives.
What a gateway does
A CAN gateway reads one device's messages and re-frames them into what the other device expects. In practice that means:
- Translating protocols — for example an EMUS BMS into the frames a Tesla drive unit, a set of gauges or a Victron system understands.
- Filtering and isolating — keeping two buses cleanly separated while still passing through the messages that matter.
- Matching bit rates — bridging segments running at different CAN speeds (125, 250, 500 or 1000 kbit/s).
How it is built
I design the hardware as well as the firmware — STM32-based boards with the CAN transceivers, power and connectors laid out to survive an automotive or marine environment. The firmware is embedded C, with two independent CAN channels so each side keeps its own timing and bus load. Each build is a small, well-defined translation table rather than a general-purpose router — which keeps the behaviour predictable and easy to reason about.
To avoid rewriting the same low-level code on every board, I maintain STM32_CAN, a small open-source library for talking CAN on STM32 microcontrollers. It wraps the peripheral setup, message filtering and send/receive handling behind a simple interface, and it is the foundation most of my gateways and nodes are built on.
Debugging a live bus
Most of the real work is not writing frames but figuring out what the other device actually says. For that I live in SavvyCAN, an open-source CAN analyser — capturing traffic, replaying frames and reverse-engineering unknown message formats. I have contributed improvements and bug fixes back to the project, and maintain a Qt 6 build of my fork that I use day to day. Being comfortable inside the tool — and in its source — makes decoding an undocumented protocol much quicker.
Where it fits
Anywhere two pieces of equipment should be able to cooperate but don't quite speak the same language — EV conversions, marine systems, battery and charging setups. When a protocol is not in the standard list, it is usually just a matter of adding the mapping.
See the CAN Gateway for one example of this in hardware.