We all use rechargeable batteries in wide variety of electronic devices and you noticed that your set of batteries lasts shorter than while the batteries were new. It's an inevitable fate of all of the rechargeable batteries. That "feature" depends on many factors and some of them which shortens the battery life cycle are: high or low temperature (while charging and in use), high discharge current, corrosion on battery terminals, number of charge-discharge cycles, build quality and so on. Now, we want to know exactly how much of the rated capacity there is left in our batteries. A while ago, when Arduino or some other free and/or open source development platforms were unavailable, building such a device was not that simple. But now, we can build one in a half an hour or so...
Step 1: A Little Theory First!
I used Arduino Uno/Nano R3 and this is my second project I've built with it. I just started to play with Arduino a month ago and my head is swarming with ideas, but most of them were already realized by someone else in some form using Arduino or other MCU platforms. And the battery capacity tester solutions I found were good, but most of them were not that precise in the final results. So, I took one project I bumped into with my first Google search - John Terry's Battery tester project and built it myself. I used it then to analyze the technique he used to measure the parameters needed during the discharge cycle. He measured the voltage across the battery under test and calculated the discharge current. His code calculated the mAh based on that current and the voltage is measured each second for the whole discharge cycle (until the battery voltage drops to 0.9V). The result produced this way is an approximate value because the discharge current depends directly on the voltage of the battery and it's internal resistance (which also changes while discharging). Battery discharge current curve is not linear at all. That was not precise enough for me, so I decided to make a little modification of the circuit and add a current sensing resistor (current shunt). I've seen projects which use it too, but they measure the current by calculating the voltage drop on the MOSFET transistor channel, but the resistance of those MOSFET channels, when saturated, can be very low (as low as 0.01 ohms). The voltage drop measured over such low resistance is going to be very low too, and because of that, the current calculated this way would not be precise because of the AREF analogue reference voltage used. The current sensing resistor I added was 0.22 ohms (I had it on hand at that moment) and it gave me enough precision for current measurement (15mA per one A/D converter digit).
Step 2: How It Actually Works.
MOSFET transistor used: NTD40N03R, 45A, 25V, N-channel
Main discharge resistor: 2.4Ohm, because of the Ohm's law --> current=voltage/resistance --> 0.5A or 500mA.
Note: I know that the ideal value for the main and the shunt resistors would be 1.2Ohm each, but I had these available in the parts bin.
The circuit works like this: It waits for the battery voltage at the A0 input to appear and then it checks the voltage to determine if the battery is suitable for this circuit and not discharged completely already (0.8V < Vbat < 1.7V). If we insert a Li-Ion battery in this circuit and start discharging it would damage the circuit and, possibly, the Arduino itself. This circuit can take NiMH, NiCD, Alkaline, Zinc-Carbon and any other that falls within the nominal voltage boundaries stated above. After the voltage detection lets the discharge cycle to begin, the Arduino turns on the MOSFET transistor by turning high (5V) the D8 output and effectively saturating the MOSFET and turning it's N-channel into a very low resistance path for the current. The initial current for an fully charged NiMH battery is around 500mA and it drops to around 400mA near the end of the discharge cycle. The battery voltage and current shunt resistor voltage drop values are then taken each second and the code calculates the mAh value (ShuntVoltage/0.22 ohms * 1 second) and adds it to the mAh accumulator variable. One more value is calculated at the same time and that is Wh, another capacity value, a true battery capacity because it takes the battery voltage into account and it represents the total amount of power that a battery can provide over a period of time. It's calculated by multiplying the mAh value by the measured voltage and that Wh value is added to the Wh accumulator variable as well. Next, the code checks if the battery voltage is 0.9 volts or less and if it is, then it increments a variable for low battery counter by 1, so that the discharge cycle stops if there were 10 low voltage measurements in the last 20 seconds.
If the battery voltage is still over 0.9V low threshold, then the code repeats the measurement in 1 second. But if the battery dropped to or below 0.9V, then the cycle stops and the measured capacity is displayed on the LCD screen in both mAh and Wh. The average discharge cycle can take from 1 hour for a lower capacity battery to over 2 hours or more for larger capacity cells. I know that this can be a long time to wait, but the discharge current is chosen to be around 500mA because it is the safe value for most of the battery types.
Step 3: The Schematic and the Code for Arduino
Here you will find the schematic (JPEG and TinyCAD file) and the code to upload to your Arduino Uno/Nano or compatible.
I hope I helped anyone who wish to use this circuit or to learn something from it.
I will be answering as much questions as I can as well as accepting any suggestions that you may have for me.
P.S. I made a little tweak to the delays used in the loop just to make sure that loop repeats at exactly one second intervals (measured error +-15 microseconds maximum).
Edit: I made a couple of corrections to the code:
- Changed the formula for current calculation because it was wrong,
- Changed the Wh parameter to display in mWh, because it makes more sense to use mWh for such "small" cells.