This means we can mix and match CMUs from different battery packs with a common BMS controller, without needing to worry about their original ID values.
Big thanks to Tom for publishing his original reversed CMU CAN protocol and also coulomb and others on the iMIEV forum for partly reversing CMU renumbering on iMIEV (seems very similar).
The CMU control connector is a JST 08CPT-B-2A plug and the matching socket. Pins:
- AN0I - input link on daisy chain. Mitsubishi's name for this pin is terrible, so I'm going to call it "AN-IN".
- AN0O - output link on daisy chain. I'm going to call this "AN-OUT"
Mitsubishi numbers the CMUs 1,2,3,4,5,7,8,9,10,11 (ten modules, CMU6 is skipped). This corresponds to the second hex digit in the CAN status messages sent by each CMU: 0x6XY where digit "X" is the ID.
The signalling is basically TTL serial at 12V. The AN-IN input pin is pulled up to 12V inside the CMU, and the AN-OUT outputs are open drain so need a pullup on the input.
(On the bench I think you can probably read the output from AN-OUT without level shifting by pulling up to a lower voltage like 3.3V and directly connecting this to an input, but I haven't tested that.)
The CMUs don't do anything at all unless they have 12V on their power pins, and are connected to a battery (or something that looks like a battery) on the other side.
To trigger renumbering, the AN-IN pin expects to see a 5 byte serial packet. Serial settings are unusual: 1200bps, Even parity, 1.5 stop bits.
The packet is made up of:
- 00 - Single zero byte
- 00 00 00 - Three data bytes. If the first ID is to be CMU1, this can be all zeroes.
- 00 - Single checksum byte, sum of the previous bytes.
The three data bytes reserve two bits for each available CMU ID, with these values:
- b00 - Not allocated yet
- b01- Old ID kept
- b10 - New ID set
- b11 - Error in input packet
00 00 00 00 00
The packet output from CMU1 if it didn't change ID:
00 01 00 00 01
The packet output from CMU1 if it did just change ID:
00 02 00 00 02
Here's a scope capture showing a CMU doing this operation:
(AN-IN is CH1, AN-OUT is CH2)
If you renumber a full pack (10 modules) and no IDs change, then the output packet at the end is:
00 55 55 05 af
Skipping of CMU6 seems to be automatic, there are no bits that map to CMU6. Similarly, it seems like you can't go past CMU11 - if you try to trigger a higher CMU number then it sets the error bit values (b11) in that spot and does not change ID.
I've added renumbering support to my Python host program that monitors CMUs using python-can (outlander_cmu_ui.py):
(Dodgy voltages are showing because I have the CMU connected to some poorly wired supercaps, not a real battery pack.)
You could easily port the renumbering support to a microcontroller or something instead.
Breadboard wiring was pretty simple:
(The second FET is only to avoid inverting the UART signal when plugging in a 3.3V USB/serial adapter.)
Although in reality it got a bit messy:
It seems to be necessary to also send CAN ID 0x3c3 periodically in order for renumbering to work, although this might be due to my test setup (the CMU decides my dodgy fake cell voltages are out of range and goes into some kind of failure mode!) This is why I ended up integrating it into the same UI that sends/receives CAN messages. There is a simpler file cmu_renumbering.py in the repo linked above that can be run as a command line program but in my testing it didn't always work - I think because of needing to synchronise with sending CAN messages..
The ID is stored in "IC60" which a SOIC-8 SPI EEPROM, markings S25 A02 DAVDGY (I think).
Sorry for blurry photo. MCU (IC200) is also visible in top left, I think it's a Renesas R5F2123AJFP.
Not sure which manufacturer the EEPROM is from, but it looks to be compatible with the 25AA series from Microchip (but probably not from them).
There are useful labelled test points for the EEPROM SPI bus: CLK, BUSY for CS, TXD and RXD for MISO and MOSI. Also a nearby test point for the MCU reset line (RST). I didn't have much luck driving the EEPROM pins in-circuit, but was able to connect a logic analyzer and see the firmware's operations. Have pushed some of the captures to here.
When renumbering, the CMU seems to write to the first 6 bytes in the EEPROM only. The byte values I've captured are:
ID 2 - fd fc fe fd db 0a
ID 3 - fc fc fd fd 23 38
ID 4 - fb fc fc fd 0b 6a
ID 5 - fa fc fb fd 93 3f
ID 10 (really 11 because 6 is skipped) - f4 fc f5 fd 63 32
Looks like ID is encoded as (0xFF-ID) and (0xFF-ID+1) in bytes 1 & 3, with a checksum or CRC in bytes 4 & 5 - but I haven't looked into this more closely.
I was disappointed not to be able to set more than 10 IDs, I was hoping the CMUs could be used in >80S packs. If we're lucky then the pack limitations (no CMU6, no IDs above CMU11) are encoded in the EEPROM and not in the firmware, so they can be overridden. The firmware does read quite a bit more data from the EEPROM after each reset, so there's a chance.
Hope this is all useful for someone else. If you find a mistake or get different results from your CMUs, please share the info!