A Battery Management System (BMS) includes functionality to sense important battery pack parameters including cell voltages, battery current, cell temperatures, etc. If any of these are out of a pre-defined range, the pack can be disconnected from its load or charger, or other appropriate action can be taken. In a previous project LTC6804 BMS I discussed my BMS design, which is based on the Linear Technology LTC6804 Multicell Battery Monitor chip and an Arduino microcontroller. This project extends the BMS project by adding battery pack balancing.
Battery packs are built up from individual cells in a parallel and/or series configurations. For example, an 8p12s pack would be constructed using 12 series-connected sets of 8 parallel-connected cells. There would be a total of 96 cells in the pack. For best performance all 96 cells should have closely matched properties, however, there will always be some variation among cells. For example, some cells may have lower capacity than other cells. As the pack is charged, the lower capacity cells will reach their maximum safe voltage before the rest of the pack. The BMS will detect this high voltage and cut off further charging. The result will be that much of the pack is not fully charged when the BMS cuts off charging due to the higher voltage of the weakest cell. A similar dynamic can happen during discharge, when higher capacity cells cannot discharge completely because the BMS disconnects the load when the weakest battery reaches its low voltage limit. The pack is therefore only as good as its weakest batteries, like a chain being only as strong as its weakest link.
One solution to this problem is to use a balance board. While there are many strategies to balance the pack, the simplest 'passive' balance boards are designed to bleed off some of the charge of the highest voltage cells when the pack is nearing full charge. While some energy is wasted, the pack can as a whole can store more energy. Bleeding is done by dissipating some power through a resistor/switch combination controlled by a microcontroller. This page describes a passive balancing system compatible with the LTC6804 Arduino-controlled BMS from a previous project.
Page 62 of the LTC6804 datasheet discusses cell balancing. There are two options: 1) using the internal N-channel MOSFETS to bleed current from the high cells, or 2) using the internal MOSFETS to control external switches that carry the bleed current. I use the second option because I can design my own bleed circuit to handle higher current than could be done using the internal switches.
The internal MOSFETS are available through pins S1-S12 while the cells themselves are accessed using pins C0-C12. The image to the right shows one of the 12 identical bleed circuits. When Q1 is turned on, current will flow from C1 to ground through R5, dissipating some of the charge in cell 1. I selected a 6 Ohm, 1 Watt resister, which should be able to handle several milliamps of bleed current. There is an LED added so the user can see which cells are balancing at any given time.
The pins S1-S12 are controlled by the CFGR4 and the first 4 bits of the CFGR5 register groups (see pages 51 and 53 of the LTC6804 datasheet). These register groups are set in the Arduino code (discussed below) in the function balance_cfg.
The schematic for the BMS balance board was designed using Eagle CAD. It is fairly straightforward. There is one bleed circuit for each battery pack series segment. The switches are controlled by signals from the LTC6804 through the JP2 header. The bleed current flows from the battery pack through header JP1. Note that the bleed current flows to the next lower battery pack segment, so for example, C9 bleeds into C8, etc. The Arduino Uno shield symbol is placed on the schematic for the PCB layout described in Step 3.
The layout is mostly determined by the design of the main BMS system discussed in LTC6804 BMS. The headers JP1 and JP2 have to match up with the matching headers on the BMS. The Mosfets, bleed resistors and LEDs are arranged in a logical way on the Arduino Uno shield.Gerber files were created using Eagle CAD and the PCBs were sent out to Sierra Circuits for fabrication. Send me a message if you would like to get a PCB, I may still have some left.
Balance board PCBs were soldered by hand using a Weller WESD51 temperature controlled soldering station with an ETB ET series 0.093 "screwdriver" tip and 0.3mm solder. Although smaller tips may seem better for intricate work, they do not retain heat and actually make the job more difficult. Use a flux pen to clean the PCB pads before soldering. 0.3 mm solder works well for hand soldering SMD parts. The temperature was set at about 790 deg F. Place a bit of solder on one pad and then place the part with a tweezers or x-acto knife and tack down that pad. The remaining pad can then be soldered without the part moving. Make sure not to over-heat the part or the PCB pads. Because most of the components are fairly large by SMD standards, the PCB is fairly easy to assemble.
The Arduino code for the BMS is available by clicking the image to the right. Several required libraries for interacting with the LTC6804 are specified in the header. These can be found on the Linear Technology website here. Download and extract LTSketchbook.zip to find the listed libraries. The code poles the LTC6804 every 5 seconds and reads the battery cell voltages, pack temperature sensors and total current. If any values are out of the pre-defined safe range, the arduino opens a relay to disconnect the battery pack. The code writes cell voltages both to the Serial monitor and to an Xbee wireless mesh network. The battery pack can be monitored remotely using the Xbee interface. Here I will draw your attention to the section that controls cell balancing. As mentioned above, S1-S12 are controlled by the CFGR4 and the first 4 bits of the CFGR5 register groups on the LTC6804 (see pages 51 and 53 of the LTC6804 datasheet). The loop function of the Arduino code detects the highest voltage battery pack segment and places its number in the variable cellMax_i. If the voltage of cellMax_i is greater than the CELL_BALANCE_THRESHOLD_V, the code will call the function balance_cfg(), passing the number of the high segment, cellMax_i. The function balance_cfg sets the values of the appropriate LTC6804 register. A call to LTC6804_wrcfg then writes these values to the IC, turning on the S pin associated with cellMax_i.