My entry to Nanorama 2020 [if I'm in time, doesn't matter if I'm not] is a very simple battery tester costing a few pounds (in addition to an Arduino NANO, of course). It isn't really finished, so I've called it a 'prototype'. As such, treat any results with a very large pinch of salt, though I'll run through a test of two batteries to show it working.
I decided that I would try and use parts I already had to hand and do it as cheaply as possible. I also decided to make it more of an experiment than a design, so the basic methods aren't necessarily very good and maybe couldn't be made to work well without much more work and better, more expensive components. Think of it as me having fun with some simple 'design hacking', rather than as a neat, tidy project to build.
The initial inspiration came from a circuit in a Linear Technology application note [1]. That circuit uses a specialised analogue switch IC to implement a synchronous demodulator [the modulation in question being to the current being drawn from the battery, which creates a changing voltage across the battery's internal resistance]. Initially, I thought I might be able to do something along similar lines with parts that I have here [with less accuracy, obviously], but, when I tried simulating it, discovered that the method didn't quite work. Whatever I tried, the contribution from the negative sense seemed to go the wrong way to correct for the inaccuracy that comes from the negative drive lead. That's probably just down to my lack of understanding of the original and my inability to do good analogue design.
So I changed course and, keeping the same method of modulating the current, experimented with clamping a capacitor [capacitive coupling with dc restoration] to get the voltage change due to the internal resistance of the battery. Unlike the original circuit, I don't need it to result in a stable, constant output to drive a meter as, with the NANO, I can take a fast, sampled measurement at the appropriate time and it doesn't matter if the capacitors start to drift off after.
The circuit divides into two halves, the forcing side and the sensing side, like this:
The forcing side is a constant-current load using what should now be a familiar circuit if you have been here for any length of time [quite a few people on element14 have done projects using it in a similar form]. I've included a means of changing the gain of the amplifier, under processor control, so that I can have either the set current or twice the set current running. Most of the time during the test it will operate at the normal discharge current (0.5A) but, for a short period of 10ms, once a minute, it will switch to x2 and run at 1A to enable it to do the resistance test.
The sensing side has two circuits. One to sense the terminal voltage of the battery and one to sense the internal resistance.
That circuit has some wrong values. R14 is 100k and R15 is 150k. Originally, I was thinking of having a range to suit a 9V battery, but ended up modifying it to work 0-2V for a 1.5V battery test. Adjusted with the preset, this gives 0-1000 on the A/D for 0-2000mV at the terminals [so a resolution of 2mV].
The top sensing circuit measures the terminal voltage at the 0.5A discharge current. That's simply a divider, with a capacitor to momentarily hold the value whilst the A/D reads it. The long time-constant of the resulting CR circuit (doesn't matter with a whole minute between readings, as long as I do this reading before stepping the current for the resistance test) nicely smooths the signal. The high value resistors don't load the battery significantly. When the reading comes to be done, transistor Q4 clamps the lower terminal of the capacitor to ground. That then gives a reading relative to ground. The capacitor is about a thousand times larger than the sampling capcitor of the A/D, so performing the conversion won't affect the reading.
The second sensing circuit reads the internal resistance. This will be a little less obvious than the other one, though it's quite simple if you understand how a capacitor behaves. Prior to the measurement, the current is stepped up to 1A and then back to 0.5A. It's the stepping back that will generate the change in voltage that I'm measuring. When the current goes down, the terminal voltage goes up because there's now less drop across the internal resistance. Both sides of the capacitor move by the same voltage step [because you can't, instantaneously, change the voltage across a capacitor]. To get ready for that, for most of the period when the current is at 1A, transistor Q5 connects the righthand end of the capacitor to half the voltage between ground and the negative end of the battery as seen by the sense wire. That voltage will actually be below ground, so effectively will subtract from the final reading a voltage that matches the contribution that comes from the negative drive wire that otherwise adds to the contribution from the internal resistance. The op amp then buffers the capacitor voltage so that it can be read by the A/D in the NANO. The gain is to match to the ADC working with an internal reference of 1.1V, so 0-1000mR neatly spans 0-1000 on the ADC.
The latter circuit doesn't work all that well. On paper it's fine, in the simulator it's not too bad, but in reality it's messy because of noise and probably the aspects of the particular capacitor I've used that the simulator isn't modelling.
Here is the NANO code that operates it.
/* Simple NANO Battery Tester Project 14 'Nanorama' May 2020 Version 0.2 17-May-2020 Specific to the NANO. A/D set up to use internal 1.1V reference. A0 voltage equivalent to rbat [scale: 0-1000 = 0-1000mR] A1 battery terminal voltage [scale: 0-1000 = 0-2V] D2 low: current x2, high: current x1 D3 low i=500mA, high i=50mA D4 rbat voltage clamp D5 terminal voltage clamp */ unsigned long oldTime, newTime; int rbat, vbat; int minuteTime; void setup() { Serial.begin(9600); DDRD = DDRD | 0x1C; // set D2, D3, D4, and D5 to outputs analogReference(INTERNAL); // set reference to 1.1V PORTD &= ~0x08; // set current to 500mA (for AA battery) oldTime = millis(); newTime = oldTime + 10000L; minuteTime = 0; analogRead(A1); // throwaway read } void loop() { if(millis() >= newTime) { oldTime = newTime; newTime = oldTime + 60000L; // measure terminal voltage PORTD |= 0x20; // set vbat clamp control pin to high (clamp) delayMicroseconds(20); vbat = analogRead(A1); PORTD &= ~0x20; // set vbat clamp control pin to low (float) delayMicroseconds(200); analogRead(A0); // throw away read // measure rbat PORTD |= 0x04; // set HI/LO current control pin to HI current (x2) delay(1); // wait for 10ms PORTD |= 0x10; // set rbat clamp control pin to high (clamp) delay(8); PORTD &= ~0x10; // set rbat clamp control pin to low (float) delay(1); PORTD &= ~0x04; // set HI/LO current control pin to LO current (x1) delay(8); rbat = analogRead(A0); // report values (minutes, internal resistance, terminal voltage) // comma separated Serial.print(minuteTime, DEC); Serial.print(", "); Serial.print(rbat, DEC); Serial.print(", "); Serial.print(vbat * 2, DEC); Serial.println(""); // prints carriage return minuteTime += 1; analogRead(A1); // throwaway conversion } }
It's all quite straightforward. I use the millis() function to do the minute timing. The code then reads the terminal voltage value, steps the current up and down, and finally reads the voltage that's equivalent to the internal resistance before sending them all back to the PC in comma-separated form. At the PC end I manually copy-pasted them from a PuTTY window into a spreadsheet for the graphing.
Here are pictures of the assembled prototype. It's a little untidy as it grew in the making, but that doesn't really matter for a prototype.
Now to see it in action. Here are the batteries I've got to work with:
The two Duracells are from a camera and are depleted to the point where the camera refused to work with them, the Energizers were the replacement cells so the two leftovers in the packet are fresh, and the Kodak branded batteries came from Poundland so were just 20p each. [I bought them specially - no expense spared when it comes to element14 projects! It will be interesting to see how they compare with the Energizers which were more than four times as expensive.]
Firstly, here is a test of one of the Duracell batteries. This had already been depleted to the point that a compact camera refused to use it any further.
The camera presumably rejected it based on the terminal voltage, but what surprised me was just how much energy there was left in the cell. At a discharge current of 0.5A, it ran for almost an hour before it was down to 0.9V. [I stopped at 0.9V because the constant-current load isn't very good below 850mV at the 2x current (1A) that it uses for the resistance sensing.
Here now are the results for a KODAK battery and an Energizer battery.
These were fresh batteries, so we see the curves from the start. How reliable the internal resistance curves are is an open question at the moment. I've rushed this to enter the competition and it's not an easy thing to test anyway. The changes in the curve look a bit odd in places, but they do go with points on the discharge curve where changes are happening. The discharge would be expected to result in a gradual rise in internal resistance, the initial self-heating a fall, so the start rising and falling again could be explained by the heating taking over from the initial discharge until such time as thermal equilibrium is reached and the resistance then starts going up again. But although the resistance curves are (possibly) indicative, don't assume the absolute values mean much at all.
Finally, here's the mandatory video
[1] Power Conversion, Measurement and Pulse Circuits. Jim Williams. Application Note 113, Linear Technology 2007.
Top Comments