Solectria E10 Lithium-Ion Upgrade
July 14th 2015, I won an auction for a used 2013 Nissan Leaf battery pack. The pack was pulled from a wrecked Leaf. $2959.33 including shipping.
The Nissan
Leaf battery pack is made of 192 Lithium-Ion (LiMnO2) cells, in a 96s2p configuration.
Each cell is 32.5Ah @ 3.75V nominal, (3.2V - 4.2V). Four cells per module in a
2s2p configuration.
And with 48 modules in the pack, this results in a 65Ah @
360V.
Since my Solectria
E10 runs at 144V nominal, I can't use the battery pack as is...
So I am going to reconfigure the pack: 2 parallel stacks of 20 modules in
series, 40s4p configuration.
Resulting in 130Ah @ 150V nominal (With 8 modules left over to be used in other
projects).
This
should get me a 60ish mile range... However, this leaves room in the battery
boxes for potentially another 2 Leaf battery packs, for a total range of 180ish
miles.
And this will still be about 200 pounds lighter than my current lead acid gel
cell pack.
I plan on reusing the almost everything in the battery pack, including the contactors, current sense, temperature sensors and most importantly the Battery Management System (BMS).
When I reconfigure the pack for my truck, I will only have 20 balancing chips... This will cause the BMS microcontroller to get really unhappy... Since it will fault out on the missing chips.
So I plan on figuring out how the BMS microcontroller talks to the balancing chips, so I can insert my microcontroller and use all the existing BMS hardware.
Kind of like a brain transplant.
A more elegant solution would be to read out the flash and decompile the BMS microcontroller, then modify the firmware such that it has 20 balancing chips... But I am not sure what, if any protections they have against this. Reverse engineering the serial protocol seems easier to me then reverse engineering byte code assembly.
The
majority of the time on this project will be spent on reverse engineering the
BMS, specifically how the microcontroller commands and reads the 24 balancer
chips.
So it can be reconfigured for 2
parallel stacks of 20 modules in series.
July 27th 2015, The battery pack arrived via heavy freight. I cleaned out the "motor cycle" parking spot in the garage, and the pack found its new home... on top of a few furniture dollies for easy maneuvering:
There was a little bit of damage visible on the exterior. The main power connector and part of the outer casing got crunched in the wreck.
Overview and Plan for the Nissan Leaf Battery Pack:
August 1st 2015, Since I
did not know the state of the pack, I wanted to turn on the internal contactors
to measure the total pack voltage...
Reverse engineering the connector pinout on a 2013 Nissan Leaf battery pack:
Using an ohm meter I was able to track down which pins went to the coils of the
contactors, the pre-charge relay and the CAN termination resistor. The
battery pack was missing the main disconnect... So I made one out of a 5 amp
fuse and some meter leads. They fit perfectly into the holes. With
the volt meter on the output connector, I applied 12V to both the high side and
low side contactors... They "thunked" and the meter showed 385.0V
Turning on the pre-charge and negative contactors to measure the pack voltage:
Using
a spare DMOC Adapter I wrote some code
so it could talk over CAN (Controller Area Network) bus to the BMS (Battery Management
System) in the Leaf pack. Getting the DMOC Adapter to talk to the Nissan Leaf battery
pack and sniffing the CAN packets:
August 9th 2015, Decoded some of the packets, and reading back all the individual cell voltages: January 30th 2016. Finally got some free time to work on the
battery pack... After sitting for 6 months I checked that I could still communicate with the pack: During this time the battery had self discharged to around
4.004V per cell. Removal of the 6 bolts around the safety disconnect:
However, the user manual I had did not match the connector type and pinout on
the pack.
Using this data I was able to reverse engineer the pinout of the connector.
With 96 cells in series, this results in 4.010V per cell. Almost fully charged!
Removal of the 10 bolts around the perimeter of the battery pack:
Using a modified scraping blade (I removed the bend in it, so it was long enough) and an oscillating tool to cut through the gasket sealing the cover on the battery pack:
After about 30ish minutes the cover came off. Assorted pictures of the battery pack:
I
particularly like the last picture of the warning sticker: "DO NOT ATTEMPT
TO DISASSEMBLE OR REPAIR".
Inside the 2013 Nissan leaf battery pack: The next day, I took out the Battery Management System (BMS)...
And then opened it up.
Overview of the battery management system:
Soldering wires on the TX (Pin 25) and RX (Pin 26) lines on the
microcontroller...
So I could sniff the serial (19.2k baud, 8 bit, no parity, 1
stop bit) communications between the micro and the balancer chips:
Recording serial communications between the microcontroller and balancing chips... Attempting to decode the protocol: February 6th 2016, I determined that the last byte in the packet
is the check sum, or as it turned out a cyclic
redundancy check (CRC8, polynomial 0x85). These are
the reverse engineering steps I took to determine the polynomial: February 7th 2016, I had acquired another BMS...
The balancer chips are different too: The pinouts are identical between the two and thus, they should
work... except for the pesky connector keying... Soldered another set of wires on the TX (Pin 25) and RX (Pin 26) lines on the
microcontroller... and placed the older BMS into the battery pack.
Testing the older BMS on the battery pack: Unfortunately the older BMS uses a different serial protocol
than the 2013 BMS.
2013 BMS serial stream:
Older BMS serial stream:
February 13-14th 2016, Since the battery cells voltages are stable
and don't change much... Time lapse video of the Lithium-Ion battery cell simulator being built: When I purchased the older BMS it also came with a wiring
harness. Lithium-Ion battery cell simulator hooked up to the BMS,
battery pack, and DMOC Adapter. Overview of Lithium-Ion battery cell simulator, and how it is connected to the Nissan Leaf battery pack: February 20-21st 2016, Had some trouble using the UART on the
DMOC Adapter to read the serial data... Ended up having to use an interrupt,
and two one shot timers to get it to work: Then wrote some code to send the serial data over WiFi to the browser for decoding: February 27-29th 2016, Using the battery cell simulator, I was
able to change the voltages on cells 93, 94, 95, and 96 on balancer chip
24. Note: Both packets above encode the same cell voltage data. Byte 14 in the packet toggles between 0x40 and 0x80, using this
as a flag I printed every other packet. Focusing on the the data in the 0x80 packet, I could see the
bytes changing as I changed the voltages on each of the simulated cells. First I slowly turned up the voltage on cell 93, until the value
read over the CAN bus pegged at 4.545V. I then turned cells 94, 95 and 96 all to
4.545V. I then turned cell 93 slowly down watching which byte 6 count
down until 3.408V, where it wrapped from 0x00 back to 0xFF, and byte 7 went from
0xFD to 0xFC. This puzzled me until I realized that it is a signed value. This made the data in the 0x40 packet make sense, since it
became positive at this time. Decoding of packets between the balance ICs and the microcontroller: March 10th 2016, Sniffing more data. Bytes 11 and 12 contain a "fifth cell" voltage data. This appears to measure the balancer chips internal linear regulator. The linear regulator takes the combined 4 cell stack voltages down to 4.12-ish volts to power its self. The reference voltage is packed 11 bit, 2's complement signed, but is only ever positive, thus full scale is 1023 = 4.545V. This is different from the individual cells... but it does not appear that the reference voltage is sampled
differentially. So this might be correct. March 12-14th 2016, I modified the battery cell simulator, (and
schematic) adding a header so I could open and short the "cell" with a
jumper.
Using the perturb and observe method, I gained some more info: Byte 16 remaining 6 bits and byte 15 make up a 14 bit time
stamp. Byte 3 upper 2 bits also encode chip status... I have seen 0xF2 become 0xFA if the cell voltages get too low, such that it has problems powering its self.
I also updated the serial decoder page with this new info, and
also laid out the for better read ability.
The most interesting thing is that the LEAF BMS balances all the time. Because the BMS is always balancing, I was able to turn up a few
cells and see what happened:
With cells 93 and 94 set higher than the rest of the pack
(4.124V), and cells 95 and 96 set to the same as the rest of the pack (4.0ish
volts). Removing the jumper on cell 93 causes it to drop to 0 volts,
resulting in a cell 93 under volt flag:
Removing the jumper on cell 94 also causes a cell 94 under volt
flag:
With the jumpers back in, turning cell 93 up to 4.515V causes a
cell 93 over volt flag, and a converter fault:
Most importantly I was able to see the balance shunt
enable/disable control packet: There are a few other control packets that I don't know what they do yet...
Since eventually I will replace the microcontroller in the BMS with my own, I
need to know the CRC check or the balancer chips will ignore my serial
communications.
But unfortunately
it was an earlier model with different connectors, which where keyed differently.
Note the gray and black connectors on the 2013 BMS, and the all white connectors
on the older BMS:
"D15120" on the 2013 BMS
"D15110" on the older BMS
But keys can be changed... or in this case removed:
0x55,0x1A,0xD2,0x4F,0xBF,0x46,0x35
0x55,0x5B,0x12,0xA8
0x55,0x5B,0x12,0xA8
0x55,0x5B,0x12,0xA8
0x55,0x5B,0x12,0xA8
0x55,0xC1,0xF2,0x00,0x00,0x85,0x15,0x56,0x98,0x61,0xA5,0xD3,0x21,0x80,0xC3,0x4B,0x99
0x55,0x42,0xF2,0x00,0x00,0x84,0x11,0x46,0x58,0x61,0xA0,0xCB,0x21,0x80,0xC4,0x4B,0x6D
0x55,0x03,0xF2,0x00,0x00,0x85,0x11,0x46,0x98,0x61,0xA5,0xC3,0x21,0x80,0xC6,0x4B,0x59
0x55,0xC4,0xF2,0x00,0x00,0x85,0x15,0x56,0x98,0x61,0xA5,0xB3,0x21,0x80,0xC9,0x4B,0x7B
0x55,0x85,0xF2,0x00,0x00,0x86,0x15,0x56,0xD8,0x61,0xA0,0xDB,0x21,0x80,0xCB,0x4B,0x57
0x55,0x06,0xF2,0x00,0x00,0x84,0x11,0x46,0x98,0x61,0x9A,0x0B,0x22,0x80,0xCC,0x4B,0x05
0x55,0x47,0xF2,0x00,0x00,0x85,0x15,0x56,0xD8,0x61,0xB0,0xB3,0x21,0x80,0xCF,0x4B,0x34
0x55,0x08,0xF2,0x00,0x00,0x86,0x15,0x56,0xD8,0x61,0xA8,0xF3,0x21,0x80,0xD0,0x4B,0x8D
0x55,0x49,0xF2,0x00,0x00,0x85,0x15,0x46,0x98,0x61,0xA2,0xB3,0x21,0x80,0xD3,0x4B,0x23
0x55,0xCA,0xF2,0x00,0x00,0x82,0x19,0x66,0xD8,0x61,0xAD,0xBB,0x21,0x80,0xD5,0x4B,0xE4
0x55,0x8B,0xF2,0x00,0x00,0x85,0x11,0x46,0x98,0x61,0xA1,0xBB,0x21,0x80,0xD7,0x4B,0x1A
0x55,0x4C,0xF2,0x00,0x00,0x85,0x11,0x46,0x98,0x61,0xA5,0xC3,0x21,0x80,0xD8,0x4B,0x83
0x55,0x0D,0xF2,0x00,0x00,0x85,0x15,0x56,0x98,0x61,0xAD,0xDB,0x21,0x80,0xDB,0x4B,0xE4
0x55,0x8E,0xF2,0x00,0x00,0x86,0x15,0x56,0xD8,0x61,0xB0,0xC3,0x21,0x80,0xDC,0x4B,0x94
0x55,0xCF,0xF2,0x00,0x00,0x85,0x15,0x46,0x98,0x61,0xA8,0xB3,0x21,0x80,0xDF,0x4B,0x5A
0x55,0x50,0xF2,0x00,0x00,0x85,0x15,0x46,0x98,0x61,0xA8,0xB3,0x21,0x80,0xE1,0x4B,0x3D
0x55,0x11,0xF2,0x00,0x00,0x85,0x11,0x46,0x98,0x61,0xAD,0xAB,0x21,0x80,0xE2,0x4B,0xBE
0x55,0x92,0xF2,0x00,0x00,0x85,0x15,0x46,0x98,0x61,0xAA,0xBB,0x21,0x80,0xE5,0x4B,0x07
0x55,0xD3,0xF2,0x00,0x00,0x86,0x15,0x56,0xD8,0x61,0xAC,0xBB,0x21,0x80,0xE7,0x4B,0x7E
0x55,0x14,0xF2,0x00,0x00,0x85,0x15,0x46,0x98,0x61,0xA0,0xEB,0x21,0x80,0xE9,0x4B,0xE1
0x55,0x55,0xF2,0x00,0x00,0x85,0x15,0x46,0x98,0x61,0xAE,0xA3,0x21,0x80,0xEA,0x4B,0xF7
0x55,0xD6,0xF2,0x00,0x00,0x85,0x15,0x46,0x98,0x61,0xAC,0xEB,0x21,0x80,0xED,0x4B,0x03
0x55,0x97,0xF2,0x00,0x00,0x85,0x15,0x46,0x98,0x61,0xAC,0x9B,0x21,0x80,0xEE,0x4B,0x3B
0x55,0xD8,0xF2,0x00,0x00,0x85,0x15,0x46,0x98,0x61,0xA8,0x83,0x21,0x80,0xF1,0x4B,0xF5
0x55,0x99,0x60,0xF5,0x8B
0x55,0x99,0x20,0xF5,0x16
0x55,0x39,0x55,0x05
0x55,0x5B,0x72,0x6D
0x55,0x99,0xA0,0xF5,0xA9
0x55,0x99,0x21,0xF0,0x9F
0x55,0x5B,0x52,0x2E
0x55,0x99,0x21,0xF0,0x9F
0x55,0x99,0x21,0xF0,0x9F
0x55,0x5B,0x4A,0x7E
0x55,0x1A,0xD8,0x6F,0x3F,0x44,0x1A
0x55,0x5B,0x02,0xA2
0x55,0x5B,0x02,0xA2
0x55,0x61,0xF2,0x00,0x00,0x69,0xA7,0x9D,0xB6,0xDA,0x6B
0x55,0xE2,0xF2,0x00,0x00,0x6A,0xAB,0xAD,0x36,0xDB,0x54
0x55,0xA3,0xF2,0x00,0x00,0x69,0xA7,0x9D,0xB6,0xDA,0x29
0x55,0x64,0xF2,0x00,0x00,0x6A,0xAB,0xAD,0xF6,0xDA,0x13
0x55,0x25,0xF2,0x00,0x00,0x69,0xA7,0x8D,0xB6,0xDA,0xB7
0x55,0xA6,0xF2,0x00,0x00,0x69,0xA7,0x9D,0xB6,0xDA,0x26
0x55,0xE7,0xF2,0x00,0x00,0x68,0xA3,0x8D,0x76,0xDA,0x3A
0x55,0xA8,0xF2,0x00,0x00,0x6C,0xB3,0xBD,0x76,0xDB,0x34
0x55,0xE9,0xF2,0x00,0x00,0x69,0xA7,0x9D,0xB6,0xDA,0xE2
0x55,0x6A,0xF2,0x00,0x00,0x64,0xA7,0x8D,0x76,0xDA,0xB7
0x55,0x2B,0xF2,0x00,0x00,0x69,0xA7,0x8D,0xB6,0xDA,0xB1
0x55,0xEC,0xF2,0x00,0x00,0x6B,0xAB,0xAD,0xF6,0xDA,0x89
0x55,0xAD,0xF2,0x00,0x00,0x69,0xA7,0x9D,0xB6,0xDA,0x1F
0x55,0x2E,0xF2,0x00,0x00,0x69,0xA7,0x9D,0xB6,0xDA,0x9E
0x55,0x6F,0xF2,0x00,0x00,0x68,0xA3,0x7D,0x76,0xDA,0xC2
0x55,0xF0,0xF2,0x00,0x00,0x69,0xAB,0x9D,0xB6,0xDA,0xD7
0x55,0xB1,0xF2,0x00,0x00,0x69,0xA3,0x8D,0xB6,0xDA,0x2F
0x55,0x32,0xF2,0x00,0x00,0x6A,0xAB,0xAD,0x36,0xDB,0x05
0x55,0x73,0xF2,0x00,0x00,0x69,0xA7,0x9D,0xB6,0xDA,0x59
0x55,0xB4,0xF2,0x00,0x00,0x69,0xA7,0x9D,0xB6,0xDA,0x18
0x55,0xF5,0xF2,0x00,0x00,0x6A,0xAB,0x9D,0xF6,0xDA,0x91
0x55,0x76,0xF2,0x00,0x00,0x69,0xA7,0x9D,0xB6,0xDA,0x56
0x55,0x37,0xF2,0x00,0x00,0x69,0xA7,0x9D,0xB6,0xDA,0x95
0x55,0x78,0xF2,0x00,0x00,0x6A,0xAB,0x9D,0xB6,0xDA,0x4F
0x55,0x99,0x40,0x0A,0x1C
0x55,0x5B,0x04,0xA0
0x55,0x61,0xD4,0x1F,0x21,0x00,0x00,0x80,0x00,0x00,0x09
0x55,0x39,0x00,0xC6
0x55,0x99,0x80,0x0A,0xDB
0x55,0x99,0x01,0x00,0x65
0x55,0x99,0x01,0x00,0x65
0x55,0x99,0x01,0x00,0x65
0x55,0x99,0x01,0x00,0x65
0x55,0x5B,0x02,0xA2
I did not have enough data to figure out how the serial data encoded the
voltage of the cells.
So I built a Lithium-Ion battery cell simulator (2.0V - 4.6V adjustable power
supply):
Modifying this spare harness, I was able to substitute cells 93, 94, 95 and 96
with the voltages from the 4 adjustable power supplies.
These cells where chosen because they are at the lowest voltage potential of the pack
(one side of cell 96 is ground).
Using this info I was able to correlate the values in read over the CAN bus to
the values I was reading over the serial bus.
0x55,0xD8,0xF2,0x00,0x00,0x85,0x15,0x46,0x98,0x61,0xA8,0x83,0x21,0x80,0xF1,0x4B,0xF5
0x55,0xD8,0xF2,0x00,0x00,0x85,0x16,0x4A,0xA8,0xA1,0xA8,0x85,0x11,0x40,0xF1,0x97,0xA2
This resulted in the same cell voltage, but encoded in two different serial
packets.
I was reading all 0xFF in bytes 6,7,8, 9 and 10 which store the cell voltage data.
I continued to turn cell 93 slowly down watching which byte 6 count down until
2.270V, where it wrapped from 0x00 back to 0xFF, and byte 7 went from 0xFC to
0xFF.
The balancing chips must contain a fully differential front end.
The 0x80 samples are + - and 0x40 samples are - + with respect to the cell.
It looks like the Microcontroller alternates between the two and takes the average between the samples to remove any front end bias
(leakage current).
The remaining bits in Byte 12 and byte 13 might contain a battery "health" type value or "balanced" value (still working on this, might be missing a bit or 2), The value seems to act like a bell curve with respect to the 4 cell stack voltage.
If the cell voltages are above 4.2V, the value is low.
If the cell voltages are in the 3.2V - 4.2V, the value is higher.
If the cell voltages are lower than 3.2V, the value is low.
Bytes 13 and 14 contain a "sixth cell" voltage data. This appears to measure the balancer chips internal ground connection. Typically returns 0... but every once in a while there is a 1 bit change. Still not sure, but I think it is 11 bit, 2's complement signed, like the reference voltage measurement.
Byte 16 upper 2 bits normally counts 0, 1, 2, 3, 0, 1, etc... but, when the , but not sure what they mean.
Bytes 4 and 5 are also cell status:
Byte 5 upper nibble is cell under volt status.
Byte 5 lower nibble is cell over volt status.
Byte 4 upper nibble is cell fault status.
Byte 4 lower nibble is cell shunt status.
Once cells are out of range, (not sure of the %) the balance shunts start tuning
on.
Each shunt is a 430 ohm resistor, (1206 size, marked "431" at the
bottom of this pic), so under 10mA of balance current.
Cells 93 and 94 balance shunts are on:
0x55 0x99 0xXX 0xFY 0xZZ
Such that:
0xXX = 0x21 - 0x38 = chip address
0xFY = lower nibble is which shunt should be enabled.
0xZZ = CRC8 check sum.
I warmed up the three temperature sensors
and spoofed the current sense with a clip leaded potentiometer, but it had no
effect on the control packets.
The remaining control packets look like they toggle between two values, these are probably what tells the converters to sample differentially.
I am working on a final ICD (Interface Control Document), that I will publish here with all the findings and notes (and update it as I learn more).
Video
showing adjusting cell voltages to cause balance shunts to turn on/off, under
volt flags on/off, over volt flags on/off, and measuring the balance current:
March 19-31st 2016, Using the continuity check on my volt meter, I was able to map out the functions of all 100 pins on the BMS microcontroller.
Next I designed a schematic which maps
all the functions from the PD70F3236 microcontroller to my dsPIC33EV256GM106
microcontroller.
Including some extra inputs and outputs, that are not populated on the BMS (I
can populate the missing parts, if I need more I/O).
Then I designed a circuit board that will get soldered in place of the 100 pin
TQFP PD70F3236 microcontroller.
This PCB takes care of the mapping from the 100 pin footprint to the 64 pin QFN dsPIC33EV256GM106
microcontroller.
The white connector hanging off the side of the board is the programming / debugging connector for the ICD3 "hockey puck".
Video overview of the board, and an 0402 resistor sitting on a penny for a sense of scale:
April 1st 2016, I unsoldered the PD70F3236 microcontroller using the de-soldering station at work, (during my lunch hour).
Video of the de-soldering process, (I kept turning up the heat until the microcontroller came off):
After I removed microcontroller, I sent the files off to the board house.
More EV Projects