# A simpler digital battery monitoring system



## cmyk (Dec 11, 2014)

Hi all,

I've been working on a system to digitally monitor cell voltages for lithium EVs, and send those voltage readouts to some sort of controller so


the driver/owner knows about battery charge (and pack health)
the pack charger knows when to stop charging (HVC cutoff)
The closest existing system I've found is the CellLog 8, which can be had for around $2.25/cell, but can only send an alarm signal - LVC only IIRC.

Here's what I have come up with so far:








Each one of these circuits monitors four cells at once, plus three thermistor probes for pack temperature. An ATTiny44/84 reads these voltages, and sends them as serial data through one of 6 connections to a controller through an RJ45 cable. The RJ45 connector also controls the power for the monitors, so they don't have to be on all the time.

The lower three cell voltages are fed through voltage followers, which reduces the current drawn from individual cells to the nanoamp range (depends on the op-amp). The top cell cannot be read from a voltage follower (maximum voltage output from the LM324 is Vin - 1.5 or so), so a differential amplifier is used instead - note that current will go through the resistors, but since it is the pack voltage the batteries won't become unbalanced. Voltage dividers are used to bring the op-amp outputs to a safe level for the ATTiny to read - 1% tolerance is recommended, since the error multiplies with this configuration (up to 4% before calibration).

I've made a couple of prototype boards, and tested them with some Headway cells - they draw around 15mA when on and transmitting, and require some calibration (programming values into the ATTiny) to report accurate voltages, but they seem to work so far.

This design can be made for around $10/board - ~$2.50/cell, assuming PCBs can be printed for $3 each - and some components (LED, thermistor screw terminals, etc) may be omitted to make it cheaper to produce.

So, what do you guys think? I'd love to hear your comments and suggestions!


----------



## dcb (Dec 5, 2009)

those attinyx4s are fun, you can get a 24a for $0.50, like less than the op amp and use one per cell down to 1.8v (and has internal 1.1v voltage reference, so it can measure its own supply voltage). I've not seen an addressing scheme like that, first thought was to multiplex them so you can have 2^6 addresses, but usually the device has a unique address via flash or solder bridges, and the address is part of a data packet. You can also auto-assign addresses a few ways too, the one I'm (slowly) sorting out is basically using a token ring, and an address field in the data packet. Each node decrements the address field as it level shifts (no optos) the packet to the next node/battery and when it reaches zero, then that node is the target (plus some special commands for find the min/max volts/temp of the whole string in one pass).


----------



## cmyk (Dec 11, 2014)

dcb said:


> those attinyx4s are fun, you can get a 24a for $0.50, like less than the op amp and use one per cell down to 1.8v (and has internal 1.1v voltage reference, so it can measure its own supply voltage). I've not seen an addressing scheme like that, first thought was to multiplex them so you can have 2^6 addresses, but usually the device has a unique address via flash or solder bridges, and the address is part of a data packet. You can also auto-assign addresses a few ways too, the one I'm (slowly) sorting out is basically using a token ring, and an address field in the data packet. Each node decrements the address field as it level shifts (no optos) the packet to the next node/battery and when it reaches zero, then that node is the target (plus some special commands for find the min/max volts/temp of the whole string in one pass).


Interesting concept! Most of my component pricing comes from Mouser with 10+ quantities, so I might not have seen a cheap 'Tiny there (LM324's are only 34 cents!). If one microcontroller is used per cell, going with an ATTiny*5 would be better, since less pins are needed. However, I decided to go with monitoring 4 cells with one microcontroller for the following reasons:


Being able to monitor 4 cells with one board is cheaper than monitoring 4 cells with 4 boards. Even if the PCB space is shared between 4/6/8 cells so one board is used, 4 'Tiny45s are more expensive than one 'Tiny44.
If one cell falls below 1.8v (which shouldn't happen if the LVC works, but let's hypothesize here), the board would not be able to send voltage/temperature readouts, and if it has to "repeat" packets from other boards connected serially the string of monitors would be broken. Getting power from 4 cells isn't too bad because it allows at least one cell to fail before it stops working.
This design is set up so a jumper across an "address pin" (pairs 1-2, 3-4 etc. in JP5) allows the board to send data on one of six wires. This keeps the boards isolated from each other (in addition to the opto isolation) so they don't depend on each other's ATTiny for communication, but it's not a very efficient way to use the 8 wires in a Cat3/Cat5 cable.

Another way to send data (as far as a wire budget goes) might be to use some sort of clock from the monitor controller - the clock signal "chooses" which boards should send data. Maybe clock pulse #1 goes to one set of boards (on the 6 wires), clock pulse #2 goes to the next set (which are on the same 6 wires), etc.


----------



## dcb (Dec 5, 2009)

There's a lot of ways to go about it of course. But most bulk PCB houses charge by the sheet for the most part, so you can have a pretty small pcb repeated more times or a larger one repeated less times (for the same cost). Also I was thinking that only one wire between nodes (ok, maybe 2 if ground loops are an unsolvable issue) per tiny pcb would be easiest, most foolproof, just one lead to cell+, one lead to cell-, and one lead to the next node/battery in the chain. Then an opto on the ends of the string.

Also I don't see a crystal, so you will need a clock line, or a robust comm protocol. Just FYI I have sorted out a 1 start bit, 1 databit protocol (which get assembled into larger packets) that seems to work without a crystal with the expected variations in internal oscillator timing, just to avoid the addition of a crystal+caps or a clock line (minimalist parts design=software problem). The code has room to spare on an attiny24 (and no prob adding a thermistor here or there as well), but I did have to resort to assembler for just the communication part.


----------



## cmyk (Dec 11, 2014)

Is this what you mean? I added an on/off line (green wires), so the monitor does not have to constantly draw power from the pack:









I guestimated resistor values, since a high signal cannot be more than around (Vcc+0.5) for the next monitor, but also must be higher than the threshold for a binary 1 (around 0.7*Vcc for 'Tinys) for various cell voltages.

This only uses one data wire, which is good, but a monitor at the "top" of the string would have to send its data through all the others - and if one pack/monitor fails (a cell reversal would shut off a monitor if there is diode protection, and destroy one if there isn't), packets would not be able to go all the way around. Of course, if the pack gets low enough to destroy a battery there are probably bigger things to worry about than a non-functional monitor (and maybe I'm worrying about this too much).

I initially chose ethernet cable because you can get high-quality, noise-resistant (if the twisted pairs are used) cable pretty cheaply, but I guess it would be unnecessary if you don't need more than two or three wires between each board.

As for a crystal - Having the ATTiny's send at 19200 baud worked pretty well for me through Cat5 wrapped around a DC motor, even though they still use the internal oscillator (I'll probably bump it down to 9600 baud for robustness). Were you able to get your protocol working on 1/4Mhz? I've set my ATTinys to 8Mhz right now, since I'm just testing stuff with Arduino's IDE and the software serial library requires that speed to function. I might move to AVR C/Assembly as well, since something like 9600 baud wouldn't need a clock rate that fast (which would eat up more power anyway).


----------



## dcb (Dec 5, 2009)

I don't have an on off (less wires=simpler=software problem), it goes to sleep after a minute of inactivity or with a broadcast command (turns off the voltage dividers and shuts down everything except what it needs to wake on another pulse). I've seen reference to a design that slept between each com event too, but microamps will take decades to drain an EV battery. Though I did bother to make sure it drew the same amount of power from each cell just to be nice. Which reminds me, that opamp setup is going to rely on lower cell readings to calculate the higher ones (oversampling?), and also the adc impedance should be no more than 10k I believe. 

Also level shifting (because of the protection diodes) does need a transistor, I'm trying to set up a constant current driver, that toggles between 5ma and 20ma currently, with complimentary detection. two wires and an opto would be much simpler hardware wise (though it does create timing problems or price problems, with an inexpensive opto and no xtal this setup would have to be painfully slow to still work reliably), but I'm not done trying to get it down to 1 yet 


re 1/4 mhz, the first instruction sets it to 4mhz, seemed like the best compromise between com performance and low voltage operation and KISS. Throughput is comparable to 14.4kbps n81 between cells. Bitwise it is more like 80kbps but there's a lot of start/stop bits to keep things in sync (plus majority voting on start bit and data bit). Each cell loads the whole token packet before retransmitting (and possibly modifying first), number of nodes is only limited by how big you make the address field. Also a few CRC bits in there too.

Last I looked it was 24 bit token packet, 8 address bits, 10 value bits, 3 command bits, 3 parity. FF is broadcast address with its own command bit definitions (i.e. go to sleep, or report error to controller)


----------



## dougingraham (Jul 26, 2011)

Just a couple of comments.

Use a P-FET for Q1 so you can measure the top cell voltage with less error.

Use an external reference for the ADC because the internal one is plus or minus 10% which can give rather large errors between devices and is not too stable over temp. An example of how much this matters is one module could be low by 10% and the next could be high by 10%. If the cells are perfectly balanced and both at 3.3 volts the monitor in one case could read this as 2.97 volts and the next cell over could be read as 3.63 volts. With LiFe type cells your device could report an overcharge condition and a dead cell when nothing at all is wrong. Typically they are not going to be this bad and you should individually calibrate them even if you use an external reference. While not as good as a separate reference and if the chip allows it you could use a precision voltage regulator and use VCC as the A/D reference.

Assuming you leave them turned off when not measuring anything the pack imbalance caused by the measurements will be in groups of four cells and should be minimal but over many years this adds up.

Best Wishes!


----------



## dcb (Dec 5, 2009)

If relying on the internal voltage reference you do need to calibrate it, and the temperature sensor to a lesser degree. And you have to compensate for differences in vcc if running off the cell voltage. There are a bajillion graphs in the tiny24a datasheet but you can (and people do) eliminate external components that way. the 8mhz internal oscillator should be calibrated at the same time, presumably on the same test fixture. 

Conceptually it is easiest to stick the calibration factors in the chips e-prom, but you will save more space (leaving out the eprom code at runtime) if the chip is reflashed with them as constants in progmem (can be automated trivially). If it were a $1000 charger, then eprom, but a sub $2 space limited bms node, flash.

Edit: if you need to store something like a map, then the eprom might make sense (though it is slower access), but simple scaling/offsets it won't. There's lots of ways to get there, but even accuracy can be a "software" problem (i.e. calibration/oversampling).


----------



## cmyk (Dec 11, 2014)

dougingraham said:


> Use an external reference for the ADC because the internal one is plus or minus 10% which can give rather large errors between devices and is not too stable over temp. An example of how much this matters is one module could be low by 10% and the next could be high by 10%. If the cells are perfectly balanced and both at 3.3 volts the monitor in one case could read this as 2.97 volts and the next cell over could be read as 3.63 volts. With LiFe type cells your device could report an overcharge condition and a dead cell when nothing at all is wrong. Typically they are not going to be this bad and you should individually calibrate them even if you use an external reference. While not as good as a separate reference and if the chip allows it you could use a precision voltage regulator and use VCC as the A/D reference.


The LM4041C component (on pin 6 in the schematic) is a precision voltage reference - 1.225V +/- 0.1%. Of course, if this isn't readily available a zener diode could be used instead (a 3.3v 1N4728A had about 0.6% error with a 30 degree change in testing).

I'm not sure if individual calibration of each input pin is necessary - The ATTiny datasheet states that ADC pins go through a multiplexer to a single ADC. If the ADC is slightly off, that change will affect all inputs. Using an external reference is still good though, since its value will change (and can be compensated for) with differences in temperature.

The pack unbalancing is indeed a factor; manual balancing may have to be done every few years to keep this to a minimum (but at least the monitor will show which one needs extra charging/discharging!).



dcb said:


> If relying on the internal voltage reference you do need to calibrate it, and the temperature sensor to a lesser degree. And you have to compensate for differences in vcc if running off the cell voltage. There are a bajillion graphs in the tiny24a datasheet but you can (and people do) eliminate external components that way. the 8mhz internal oscillator should be calibrated at the same time, presumably on the same test fixture.


From the datasheet, I don't see the temperature sensor's accuracy improving much beyond 10% (page 144), and it will change as the chip heats up during operation. I have, however, heard of ways to use the internal reference to measure Vcc (by fiddling with registers to get it to an analog input instead of using it as an ADC reference), but I admit not spending enough time looking into it.

Oscillator calibration might not be as necessary if lower speeds are used; ideally the slowest one (hopefully 1Mhz) since that would also eat up less power.

One advantage of storing calibration data in EEPROM is that you can change/update it later, possibly with an instruction from the BMS controller. This doesn't require reprogramming the ATTiny, but would need two-way communication between a monitor and its controller. Also, being able to add calibration values from the controller (instead of pulling each 'tiny from the monitors) would be helpful if the 4 cell with op-amp design is used - error before calibration is 4% for cell #3, so this would be required in some fashion.


----------



## dcb (Dec 5, 2009)

cmyk said:


> From the datasheet, I don't see the temperature sensor's accuracy improving much beyond 10% (page 144), and it will change as the chip heats up during operation.


It is a question of calibration and software compensation really. This is a scaling and offset approach: http://21stdigitalhome.blogspot.com/2014/10/trinket-attiny85-internal-temperature.html an implementation of AVR122 (within 1 degree C).

The datasheet refers to using multiple temperature values as well (and vcc), but I don't expect anyone to put each chip in the fridge prior to production (not at <$2 apiece). The effect of temperature is small on voltage readings so it isn't critical, but a test/programming fixture with a 1.8v to 5v cc calibration is easy enough. And spot check a few in the fridge (and/or the oven).

occ cal isn't at all critical if com is working.

I guess it depends how you define simpler  adding components/connections or coding the most out of the chip. There is something simpler about a smaller circuit that is repeated for each cell (as the software is a one-time cost basically).


----------



## cmyk (Dec 11, 2014)

Yeah, I should probably have named this thread "A robust digital battery monitoring system"... Having op amps, voltage dividers and external references aren't as simple as a single ATTiny with some connectors.

That said, ATTiny's in sleep mode don't draw as much power as I thought they did - assuming they draw 150 uA in sleep (a high estimate - ADC off, one pin interrupt), they would discharge a 100AH battery by 10% per year. I might modify the circuit so the 'tiny controls the transistor/P-FET (to shut the op-amp/dividers off), and use the "input" opto for messaging from the controller.

I'm still favoring a multi-cell solution - Even with some overhead for resistors, one '24/44 plus an op-amp ($1.15 + $0.34 for 10+ quantities) is cheaper than four $.50 25/45/13 chips (though the cheapest ATTiny13 I could find in 10+ quantities was $0.83).


----------



## dcb (Dec 5, 2009)

Yah there is definately cost potential with multiple cells per board, and I've a few unknowns yet, and with price changes driving me to a tiny88, that is a lot of unused pins. one cpu/cell made more sense with the 24, but the 88 has twi built in and 10 adc channels for less than $0.70 (and a stable vcc when connected to a short stack). I'll have to rethink the sensibility of the 1 cpu/battery approach, though measuring voltages in a stack with one cpu has its own challenges, but they are pretty well known. 

Still not sure on network topology though, since "token ring" style allows for automatic addressing (plus only "need" 1 opto per board, and scanning for a max/min value is easy), and twi you will have to set some jumpers or "hardcode" the address. But it is a lot more cost effective to add 1 crystal for every 10 cells, than 1 for every cell. Probably looking at less than $1 per cell with quasi-distributed @ 10 cells per (or 9 and a thermistor), now if only the tiny had uart (AVR274?) 

Also have to think about minimizing regulator consumption in sleep mode (not worried about a few mA when driving or charging).


----------



## dcb (Dec 5, 2009)

note: appendex A describes many of the issues with measuring a stack of batteries
http://cds.linear.com/docs/en/application-note/an112f.pdf

here is an spi example using $10 chips (for 6 cells) from ti and a target board.

http://www.ti.com/lit/an/slaa478/slaa478.pdf


----------



## PStechPaul (May 1, 2012)

I've been trying to come up with an ideal design for a BMS, and it seems that having an individual circuit for each cell is best. Some ideas I have considered:

1. The circuits could be connected with fiber optic cables with an LED and photosensor on each unit.

2. Once all units have been connected, they can self-assign addresses by sending a command along the string and increment from the one above it.

3. Measuring battery voltage might best be accomplished by using the internal reference and the ability to read the supply voltage (or use it as reference).

4. The processor can shut down to extreme low power and wake up on an interrupt or upon a watchdog timer reset.

5. Visible indication via LEDs can be done with low power by using short pulses (50 mSec) separated by much longer times (5 sec) to use 1/100 power. 

6. You can format the voltage data to show the voltage from 2.5V to 3.5V using 8 bits for a resolution of 1/256 or about 0.004 volts.

7. It may be possible to transmit this data using PWM rather than RS232 code. The closer the voltage is to the low point 2.5V the shorter the pulse and the lower the power needed to transmit. This will in effect provide a small amount of cell balancing.

8. I plan to add some cell balancing (shunting) so that a simple constant current charger can be used. It could be done using PWM and a resistor, or possibly using an inductor to save power.

As for PCBs, I have used www.pcbcart.com, and for a 1" x 2.5" board, panelized with scoring so they can be separated, the price per board is well under $1 each in quantity of 100, and half that is set-up charge, so next order will be $0.50 each or less.


----------



## dcb (Dec 5, 2009)

the multi-op amp approach can work, cmyk has addressed the quiescence issue to a degree (I might opt for a sugarcube relay to put them to sleep and a low power regulator to the cpu), though the one's I've seen have the op-amp inputs + and - connected to the cell + and - (through some large value resistors), i.e. use them for differential (and get ones with large enough voltage rating). They have some opamps with an enable line too. But it does seem to introduce a tiny bit of imbalance, which sorta mandates a balance circuit (=cost and heat/space considerations)


----------



## dcb (Dec 5, 2009)

I took a stab at a 8 cell unity gain diff (2 quad), the 10k resistors are kinda arbitrary here, don't want too high or low r (they could be bigger for less drain probably). 8 cells seems to be about the inexpensive price limit where you can get 4 channel op amps that can handle 8 cells of lithium voltage (and a cpu with 8 adc).

The outputs are spot on, well suited for a 5v reference adc(the voltage at the unconnected end of the 10ks). Though surely calibration is in order in production.

but you can see more is drawn from the lower cells than the upper ones, but price per cell it is going to be next to impossible to beat if you don't get too fancy.

(ltspice attached as txt)


----------



## cmyk (Dec 11, 2014)

Yeah, the current drain difference is why I went with a voltage follower/divider design. Besides the microcontroller draw, the only other drain is through the resistors for the top cell's op amp (which has the voltage of all four cells, and should discharge them evenly).

Another communication idea might be a hybrid topology (between "ring" and "bus", more like an incomplete ring):

A controller could send requests to a monitor, which would pass it down to the board with the correct address (this is the ring part). When a monitor needs to send information back (once it receives a request), it sends a response on a very high address (255 or 1023) to the next board _and_ on a shared bus (opto isolated). The controller can listen on the bus wire, and when it sees its address (255/1023/etc), it knows the response is for the packet that was sent. This way, the ring does not have to be terminated and the end of a long string of packs does not have to be routed all the way back to the controller. A break in BMS communications doesn't mean the whole pack is unmonitored, just the monitors downstream of the problem.

Depending on the number of cells/boards, communication speed may be faster too. Instead of having to traverse each node in the monitoring system for every request/response (_n_), the time between sending a request and getting a response would be an average of _n/2_ (n=monitors, assuming the requests are evenly distributed).

This design would need two optos per board, one for the data input and one for the bus. The output to the next board does not have to be isolated, since that is done by the opto on the next one.

As an aside: It looks like there are many ways to design a BMS, with different constraints:


Cost
Simplicity (ATmega16HVB, TI's chips)
Accuracy
Robustness (bad cells/bad connections)
Cell balance (identical current draw, can be mitigated with shunting)
There isn't any one design that can satisfy all of these points. I guess it depends on each builder/designer's priorities


----------



## dcb (Dec 5, 2009)

cmyk said:


> Yeah, the current drain difference is why I went with a voltage follower/divider design.


Ah, thanks for reiterating that (kinda new to op-amps, i.e. as of this morning). That seems like a clever way to balance the load better (though still leaves cumulative error problems). FYI, I ran the ltspice simulation with 1M resistors (and 10k to ground impedence on the outputs) and the difference between top and bottom was less than 100uA, which if it holds up on a less expensive chip in the real world then is probably not worth worrying about too much. (4.22535mA vs 4.30341mA).


----------



## cmyk (Dec 11, 2014)

Alright - with all your help and suggestions, I've updated my design:









Some important changes:


Bidirectional Communication, via a hybrid ring/bus topology (Post #17)! This allows the monitoring controller to individually ask for values, and to set calibration values for each cell without any reprogramming. I tested this with some LTV826 optoisolators up to 14.4kbps, though it may be able to communicate even faster. Breaks in the communication chain may also be reported (with the controller watching for where packets stop being transmitted - all packets to the next monitor are also transmitted to the BMS controller).
Resistor value changes (dcb's post #6), so the ADC won't have to wait too long to get an accurate reading - power consumption isn't affected too much.
The op-amp power is now controlled by the ATTiny, while the microcontroller is set to stay on. Sleep modes available won't take up too much power, but the LM324 sucks up 1.6mA no matter what, so it will have to be shut off when not in use. This also means that the debug LED had to go away, since the 84/44 is out of pins.
A safety diode (D1) has been added, so the ATTiny won't be blasted with 7+ volts if the third cell sense wire becomes unplugged.
Different connectors for communication between boards. Since the jack doesn't need to use all 8 connectors any more, other pin headers may be used besides RJ45 (and those connections have been modified so the boards won't break when a crossover cable is used).
I'm kind of debating on the transistor switch (to a PFET, as suggested in doughingraham's post). Something like a J175 wouldn't have any voltage drop, but is also twice the price of a PNP transistor - and while a BJT has some voltage drop across the emitter/collector, this may be able to be compensated with calibration.


----------



## PStechPaul (May 1, 2012)

I have a thread going in HSM about using six LiFePO4 cells in an electric drill, and some ideas for a BMS are being discussed. For a pack of this size (19.2V), I may try using a DG408 multiplexer to take readings of as many as eight cells with just a single ADC. Thus the cell to be tested would be connected to a voltage divider (100k/10k) just long enough to take the sample, and otherwise there would be virtually no current flow from the cells except for the microcontroller power. So blocks of six (or eight) cells could be monitored by a single PIC (or Arduino), and then communication can be performed among multiple blocks. Eight cells would be 25.6V nominal which is well within the range of the multiplexer.

I have also decided that the individual cell shunts can be implemented with an opto-isolator, a PNP BJT (MJE170), and a resistor of perhaps 4.7 ohms to handle charge current up to 500 mA and about 2 watts. I'm thinking I'll use a white LED across the resistor to indicate shunting.

Another idea that was brought up is a programmable shunt voltage reference like a TL431 set to the cell maximum of about 3.4V. It is easy to make a shunt regulator with higher current capacity by using a 2.5V reference, op-amp, and an NPN transistor.

Your circuit looks OK, but as my design evolves, I am finding various ways to improve performance and decrease cost. Good luck.


----------

