Comments on Dealing with multiple CAN terminations in a master-slave-BMS setup
Parent
Dealing with multiple CAN terminations in a master-slave-BMS setup
I’m running into a CAN bus termination issue in one of my designs and wanted to get some opinions on the best way to handle it.
Setup
I have a master controller made up of two PCBs connected in a piggyback fashion. Each board has its own MCU and CAN transceiver, and both currently have 120 Ω termination resistors. These two boards talk to each other over CAN.
The same CAN lines also go out of the master to connect to a battery BMS, and sometimes a slave controller.
Here’s what gets added to the bus depending on configuration:
-
Battery A (Li-ion) - has its own BMS with a built-in 120 Ω terminator.
-
Battery B (NiMH) - doesn’t have CAN or any termination.
-
Slave board - basically the same hardware as the master, but with only one MCU and CAN transceiver, and it also has a 120 Ω terminator.
So depending on what’s connected, I end up with more than two terminations on the same CAN bus, which is not desirable.
What I’m thinking
-
The master logic board will always keep its termination enabled.
-
The piggyback board by default will have it's termination disconnected and on power up will detect (through a GPIO line) if a slave is connected:
-
If slave is connected, the piggyback board turns its termination OFF.
-
If no slave, it connects the termination, so that the master+piggyback still form the two ends.
-
I will remove the CAN termination resistor from the battery BMS even though it’s physically at the far end (around 12 inches away). Should I be doing it ?
Bus details
-
CAN baud rate: 500 kbps, 11 bit, Classic CAN 2.0
-
Frame size: about 12 bytes
-
Total bus length: roughly 12 inches
Questions
-
Is it acceptable to skip the termination on the battery side even though it’s technically the far end (~12 in)?
-
I came across an application note that uses an optocoupler to control termination. Has anyone here tried that approach, or is there a cleaner way to do MCU-controlled termination? Link CAN Selectable Termination Application note
The noticed the photorelay part has a max turn-on/turn-off time of 5ms. Which is slow compared to analog switches but I don't have to keep changing the termination when the communication is happening only needs to check once on power up and set appropriate can termination.
- Last one, where should I put the control circuit? On the Piggyback PCB or Logic board PCB ? The CAN bus is going out from the Logic board PCB and PiggbyBack and Logic board are connected with B2B connectors inside an enclosure.
Appreciate any thoughts or examples from people who’ve handled similar setups especially where you have modular boards and removable CAN nodes.
Post
Your bus length is so short that you can consider the battery connection a stub. As long as there is 60Ω between CANH and CANL and the cable to the battery is not ridiculously long (many meters), it will work just fine.
If you add a third termination you end up with (1/120 + 1/120 + 1/120 = 1/Rtot) 40Ω, which isn't recommended, but in practice that will very likely work too (I do this all the time by mistake on all manner of CAN hardware and have yet to see it fail or causing error frames).
You usually just get problems when there is one or several missing terminators and you get >120Ω.
I came across an application note that uses an optocoupler to control termination.
It needs to be fast enough to switch on before CAN communication goes live and accumulates too many errors. If you are using something like a generic Cortex M then it boots out of power-on very fast. On the other hand if you have lots of overhead like RTOS, or in case you run on some low frequency = low power oscillator, then it won't.
CAN error frames are always expected during the boot-up stage because not all nodes will start in sync, someone has to be the first one and not getting anyone to talk with. That first node will send an error frame and then keep trying. If its error counter passes 127 then it will go error passive and depending on how you deal with errors that could be a problem. 128 more errors and it goes bus off.
So the critical time is: bit rate * bits * 128.
- 500kbps = (1/500*10^3) = 2μs per bit
- Assume worse case = no payload and 11 bit id, around 46 overhead bits in a CAN frame (+/- some stuffing).
- 2μs x 46 = 92μs
- 92μs x 128 = 11.78ms
Meaning that if the optocoupler has 5ms toggle time, the MCU then has 11.78 - 5 = 6.78 ms to come out of power-on reset, initialize everything and send out a CAN frame. That can either be an eternity or far too quick, depending on which MCU you've got, how you clock it and how much boot-up code there is.
I've encountered problems with this in real life when someone attempted to do with this with an even slower relay, which therefore brought down the whole bus sporadically, depending on how the relay contact bouncing ended up.
What's recommended instead of an optocoupler is an analog switch IC. And if you need galvanic isolation (doesn't sound like you do in this specific case) then add that on the line controlling the analog switch. Preferably with an inductive "digital isolator" rather than an optocoupler, since they are faster.
where should I put the control circuit?
Usually you do not want to control termination through the MCU, because normally the MCU will not have a clue of what hardware configuration that is present.
The plain and simple way is instead to add something like a terminal block connector to the board and if you put a wire between pin 1 and 2 on it, then a SMD 120Ω resistor on-board is connected between CANH and CANL, otherwise it just sits floating connected to just one of them. If you pick a terminal block with a removable cable connector part, then you can just move that cable part around between boards depending on where the termination needs to be.
The advantage of this is no soldering, so all boards are the same and even the end user can be taught to do it.

0 comment threads