Hi all, this is my first post here – hope it’s useful to someone.
Disclaimer: This is a DIY project for people who know what they are doing. Working with a vehicle CAN bus carries real risks – you can cause malfunctions or damage. Do this at your own risk.
Goal
The idea is to dynamically limit the Orion XS maximum charging current based on engine RPM read from the vehicle CAN bus. This allows the charger to back off when the engine is idling and ramp up only when the alternator is actually producing enough power.
The test vehicle is a Mercedes Sprinter 907.
Hardware
-
Victron Cerbo GX (Venus OS Large)
-
Victron Orion XS – connected to Cerbo via VE.Direct cable
-
Teltonika ECAN02 CAN bus adapter – used as a passive tap on the vehicle CAN network
Why the ECAN02 (or similar isolated adapter)
Older Cerbo GX units do not have galvanically isolated CAN. Connecting directly to the vehicle CAN network without isolation risks injecting noise or unintended frames into a safety-critical bus. The ECAN02 provides galvanic isolation and acts as a passive listener – it does not transmit onto the vehicle bus.
Wiring
Vehicle side – under the driver’s seat (Sprinter 907)
The Sprinter 907 CAN bus is accessible under the driver’s seat. The relevant wires are:
-
Brown – CAN_L
-
Brown/Red – CAN_H
Connect the ECAN02 accordingly. Power the ECAN02 from the same source as the Cerbo GX – this is important for a stable common ground reference.
Alternative power source worth considering: If you are using an Orion XS, you already have a shared ground between the vehicle and the hotel electrical system. In that case, you could power the ECAN02 from terminal 15 (ignition-switched +12V), which is available under the driver’s seat on the Sprinter. This way the adapter only starts transmitting to the Cerbo after the ignition is on, which is a cleaner behaviour. That said, I haven’t verified this approach yet – it needs testing.
Cerbo GX side – VE.Can port
Connect the ECAN02 output to the Cerbo VE.Can RJ45 port. Pin assignment:
-
Pin 7 – CAN_H
-
Pin 8 – CAN_L
Software setup
This assumes you are already running Venus OS Large with Node-RED. Install the SocketCAN palette in Node-RED via Manage palette:
node-red-contrib-socketcan
Note: in this library the node names are counterintuitive – socketcan-out is for receiving frames (has an output), and socketcan-in is for sending frames (has an input). Keep this in mind when building your flow.
3. CAN bus speed
The Sprinter 907 CAN bus runs at 250 kbps, which is also the default speed of the Cerbo GX VE.Can port – so no configuration change is needed on the Cerbo side.
I tested this with nothing else connected to the VE.Can port. I’m not yet sure what happens when the Cerbo is flooded with vehicle CAN frames while other VE.Can devices (like the Orion XS) are also present on the same bus – this needs more testing.
Node-RED flow
The flow reads Engine RPM from the vehicle CAN, decodes it, maps it to a current limit percentage, and sends that to the Orion XS via the Cerbo.
Flow structure
socketcan-out → function (decode + map) → [further control logic]
Function node – decode and map RPM to percent
This example uses the following DBC signal definition from the Sprinter 907:
BO_ 177 Engine_Data: 8 Vector__XXX
SG_ Engine_RPM : 24|16@1+ (1,0) [0|8000] "rpm" Vector__XXX
Signal is 16-bit unsigned little-endian, starting at bit 24 (byte 3), CAN ID 0xB1 (177 decimal).
// Filter by CAN ID
if (msg.payload.canid !== 0xB1) return null;
const data = msg.payload.data;
// Decode Engine_RPM: bit 24, 16-bit, little-endian unsigned
const rpm = (data[4] << 8) | data[3];
// Map RPM to charging current limit (percent of max)
let percent = 0;
if (rpm >= 2000) {
percent = 100;
} else if (rpm >= 1500) {
percent = 60;
} else if (rpm >= 1200) {
percent = 40;
} else if (rpm >= 800) {
percent = 20;
} else {
percent = 0; // idle or engine off – stop charging
}
msg.payload = { rpm, percent };
return msg;
The RPM thresholds and percentages are a starting point – adjust them to your alternator’s actual output curve.
Current status
This has been tested on a live Sprinter 907 with the exact setup described above – CAN parsing, RPM decoding and percentage mapping all work correctly in Node-RED on Venus OS Large with the ECAN02 connected to VE.Can.
The Orion XS control side (actually sending the current limit from Node-RED to the Orion XS) I have not been able to test as I don’t have an Orion XS available. If you have one in your installation and manage to get this working end-to-end, please share your results in the comments.
Going further – combining RPM with battery voltage
You can extend the logic by also reading the vehicle battery voltage. On the Sprinter 907:
BO_ 290 Battery: 8 Vector__XXX
SG_ Battery_Voltage : 0|8@1+ (0.1,0) [0|25.5] "V" Vector__XXX
Signal is 8-bit unsigned, starting at bit 0 (byte 0), scale 0.1V, CAN ID 0x122 (290 decimal).
if (msg.payload.canid === 0x122) {
const voltage = msg.payload.data[0] * 0.1;
flow.set('battVoltage', voltage);
return null;
}
A voltage above ~14V typically means the smart alternator is actively charging – which on some vehicles also indicates regenerative braking or a high-load generation phase. In that situation you could override the RPM-based limit and go straight to 100%:
const battVoltage = flow.get('battVoltage') || 0;
if (battVoltage > 14.0) {
percent = 100; // alternator fully active, safe to draw maximum
}
This is just one example of how combining multiple CAN signals gives you a more intelligent charging strategy than RPM alone. Whether this logic makes sense for your specific vehicle and alternator depends on your setup – treat it as a starting point.
If you try this on your installation, please share your results in the comments.