Pages: [1] 2   Go Down
Author Topic: Smart battery discharger/tester  (Read 5192 times)
0 Members and 1 Guest are viewing this topic.
0
Offline Offline
Sr. Member
****
Karma: 17
Posts: 389
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hi,

Some (most) of us are P*R**L*X renegades  smiley-wink
During this Dark Age, I built a battery discharger using a 12V lamp as resistive load. This was the good old time when an Analog Input had to be emulated through an RC circuit...
The purpose of such a device is to evaluate the actual capability of a AA (R6) battery, in term of mAh
This smart version is based on an electronic load, with fixed/adjustable discharge current.

Here it is:

Smart battery discharger/tester diagram


The NPN transistor acts as a variable resistor
Current is sensed through a shunt resistor; the corresponding voltage is fed back to the inverting input of an OpAmp configured as a comparator. The non inverting input is set at a reference voltage value through an adjustable voltage divider.
In an effort to have both input at the  same level, the OpAmp will output the adequate signal which is fed to the NPN transistor base
To avoid full depletion of the battery, a relay disconnects the battery below 500mV. This sub miniature relay is directly driven by the Arduino
I used TIP41C and LM324, but any GP OpAmp and NPN transistor will fit the bill; just make sure that the max allowable collector current is over 2 Amps.
Volts and Amps are acquired through AI0 and AI1, mAh are computed by integrating Amp over time


Breaboard implementation

Caution: This device is designed to convert electric power to HEAT  :o
The power dissipation can be calculated, or simulated in LTSpice
according to datasheet, the TIP41C transistor can dissipate up to 65W. Don't take the info for granted; this value assumes that collector temperature remains at 25°C which is unrealistic.
For more than a couple of Watts, install a suitable radiator on the component.
To avoid destroying the component it is advisable to limit max power within the code


LTSpice simulation       X axis = potentiometer wiper relative position (0-100%)

Arduino code is straightforward. The main point is to create a fixed time loop for accurate mAh integration.

What I learnt on batteries:
Not all batteries are created equal; I get results from 662 to 2764 mAh (all AA size)
Ageing does reduce battery capacity; some batteries where discarded after test
Internal resistance is a real issue, 1500 mAmp will definitely bring voltage down, below 1 Volt.

What I learnt as a bonus:
NPN Bipolar Junction Transistor in the active region, versus saturation region   http://en.wikipedia.org/wiki/Bipolar_junction_transistor#Regions_of_operation
Operational amplifier (comparator configuration)    http://en.wikipedia.org/wiki/Comparator
Circuit simulation using LTSPICE (a magic world)
and... learning to post on a message board

Additional readings
TIP41C datasheet:    http://www.datasheetcatalog.com/datasheets_pdf/T/I/P/4/TIP41C.shtml
LM324 datasheet:     http://www.datasheetcatalog.com/datasheets_pdf/L/M/3/2/LM324.shtml
LTSpice Homepage:  http://www.linear.com/designtools/software/
LTSpice Tutorial:      http://claymore.engineer.gvsu.edu/~steriana/Videos/

Next steps
- Add some decoupling capacitor (should I ???)
- Take into account Base/Emitter current in calculation
- Use a MCP3208 12 bits A/D Converter for further accuracy
- install an LCD display and piezo buzzer for stand alone operation
- reconnect to PC for graphical trends of voltage versus time

Thanks for reading
« Last Edit: May 20, 2014, 07:23:17 am by kas » Logged

0
Offline Offline
Sr. Member
****
Karma: 17
Posts: 389
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Oops... forgot the code   :smiley

Here it is
Code:
//Battery monitoring      V1      Basic edition
// Copyleft KAS         November 2009

#define     VMIN              700           // Battery protection      Vmin > WMIN
#define     WMAX              2000          // Transistor protection   Wmax < WMAX
#define     LOOP              2000          // loop time (ms)

#define     Vpin              0             // battery voltage pin
#define     Apin              1             // Amp reading pin
#define     RELAY             3             // relay pin

long loopTime = LOOP;
long loopUsedTime = LOOP;
long loopStart = 0;
float mVolt = 0;
float mAmp = 0;
float mW = 0;
float mAmpH = 0;
long loopCount = 0;
boolean testOn = false;

void setup()  {
  Serial.begin(19200);
  pinMode(RELAY, OUTPUT);
  digitalWrite(RELAY,HIGH);                     // Close relay
  testOn = true;
  delay(100);
}

void loop()  {
  loopStart = millis();
  
  mVolt = getmVolts();
  mAmp = getmAmps();
  mW = (mAmp * mVolt) /1000;
  mAmpH += mAmp * loopTime / 3600 /1000;
  if(testOn)    display();
  else          while(1);                    // Loops forever
  testStop(VMIN, WMAX);

  loopCount++;
  loopUsedTime = millis()-loopStart;
  if(loopUsedTime < LOOP)         delay(LOOP - loopUsedTime);
  loopTime = millis() - loopStart;
}

int getmVolts()  {
  return int(analogRead(Vpin)*4.8828125);          // read the battery voltage
}

int getmAmps()  {
  return int(analogRead(Apin)*4.8828125/0.47);      // read the Amps
}

void display()  {
  Serial.print(loopCount/(60000/LOOP));                Serial.print(":");
  if(((loopCount%(60000/LOOP))*LOOP/1000)<10)          Serial.print("0");
  Serial.print((loopCount%(60000/LOOP))*LOOP/1000);    Serial.print("    ");
  Serial.print((int)mVolt);                            Serial.print(" mV   ");
  Serial.print((int)mAmp);                             Serial.print(" mA   ");
  Serial.print((int)mW);                               Serial.print(" mW       ");
  Serial.print((int)mAmpH);                            Serial.println(" mAh");
}

void testStop(float Vmin, float Wmax)  {
  if((mVolt < Vmin)||(mW > Wmax))
  {  digitalWrite(RELAY,LOW);                      // disconnect tested battery
     testOn = false;
     Serial.println("Stop");  
  }
}
Logged

0
Offline Offline
Full Member
***
Karma: 0
Posts: 126
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Interesting, to say the least.

Some questions for you: your objective is to measure battery capacity (Ah). And you also want to measure linearity of this capacity. Is this right ?

Quote
Internal resistance is a real issue, 1500 mAmp will definitely bring voltage down, below 1 Volt.
Surely. This is due to how batteries work internally, chemically speaking.
Quote
- Add some decoupling capacitor (should I ???)
No need. What for ?
Quote
- Take into account Base/Emitter current in calculation
It's too small compared to C-E current. But yes, perform a slight adjust.
Quote
- Use a MCP3208 12 bits A/D Converter for further accuracy
Time is more important here than instantaneous current. IMHO. So make sure your timebase is accurate. But you're measuring voltage between ground and D2? if so, you're actually (if you compensate for the resistor temperature) measuring current. If you place R2 between ground and battery (-), then you can more accurately see discharge current.
Quote
- reconnect to PC for graphical trends of voltage versus time
I might help here smiley Send me an email or so if you're interested to test my new serial protocol http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1257971980/23#23
Álvaro
Logged

0
Offline Offline
Sr. Member
****
Karma: 17
Posts: 389
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hi Alvaro,

Thanks for the kind words; As your mention, the objective is to measure capacity (mAh) and the influence of current load (mA) on battery behaviour.

Quote
If you place R2 between ground and battery (-), then you can more accurately see discharge current.
I do compute mA based on mV between D2 and ground
If I place R2 between ground and battery (-), the battery voltage measured at D3 will be biased, won't it??


Quote
I might help here  Send me an email or so if you're interested to test my new serial protocol http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1257971980/23#23
:o  :o good job... may be overkill for this application.
I just need to pass one integer every other second
I am developping the project using StampPlot lite
Will report progress this week-end
+yves+
Logged

0
Offline Offline
Full Member
***
Karma: 0
Posts: 126
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
If I place R2 between ground and battery (-), the battery voltage measured at D3 will be biased, won't it??
Yes, but since you also know V(R2) you can compensate. Which might be easier than doing compensation based on transistor values (they vary quite a bit depending on junction temperature.

Álvaro
Logged

0
Offline Offline
Sr. Member
****
Karma: 17
Posts: 389
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
Yes, but since you also know V(R2) you can compensate.
Got it: V(bat) = V(A0) - V(A1)   smiley-wink

This is Version 2:
I have also modified D1 and D2 to A1 and A2 to reflect the (analog) type of measurement


Thanks Alvaro
Yves

Logged

0
Offline Offline
Sr. Member
****
Karma: 17
Posts: 389
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Code modification for Version 2 as suggested by Alvaro:

getmVolts() should be modified as follow:

Code:
int getmVolts()  {
  return int((analogRead(Vpin)-analogRead(Apin))*4.8828125);          // read the battery voltage
}
Logged

0
Offline Offline
Sr. Member
****
Karma: 17
Posts: 389
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

This chart reflects the discharge process (@1C) of a 1.2V AA battery:


The diagram is obtained using Stamp Plot light from Selmaware.
This freeware can be obtained here: www.parallax.com/tabid/441/Default.aspx   smiley-wink

Additional code:
Code:
#define     CHART             1             // Trend mode

In setup():
Code:
#if defined CHART
  delay(200);                                                       //------- Stamplot ---------------
  Serial.print("!TITL Battery tester");  Serial.print(13, BYTE);    // Set window title
  Serial.print(MESSAGE);                 Serial.print(13, BYTE);    // Set Status message
  Serial.println("!PNTS 6000");          Serial.print(13, BYTE);    // Set number of data points to collect
  Serial.println("!SPAN 500, 1500");     Serial.print(13, BYTE);    // Set maxi & mini range
  Serial.println("!AMUL 1");             Serial.print(13, BYTE);    // Set the value to multiply da
  Serial.println("!CLRM");               Serial.print(13, BYTE);    // Clear the message list
  Serial.println("!CLMM");               Serial.print(13, BYTE);    // Clear the MIN/MAX values
  Serial.println("!RSET");               Serial.print(13, BYTE);    // Reset the plot and all data
  Serial.println("!TMAX 3600");          Serial.print(13, BYTE);    // seconds maxi on x axis
#endif

in display():
Code:
#if defined CHART                                                 //StampPlot data for trending
    Serial.print((int)mVolt);            Serial.print(13, BYTE);
#endif
Logged

0
Offline Offline
Full Member
***
Karma: 0
Posts: 126
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Amazing work. Let me congratulate you for the achievement!

What exactly are you plotting there ? battery voltage vs. time ?

I wonder if you can overlay also current (or voltage across sense resistor). I am curious if integration of this one will lead to "700mAh" they advertise.

Any chance you can provide me the data (data points+timebase) for both ?

Best,

Álvaro
Logged

0
Offline Offline
Sr. Member
****
Karma: 17
Posts: 389
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hi Alvaro

Quote
What exactly are you plotting there ? battery voltage vs. time ?
Yes, Battery voltage (mV) versus time; I am sure you recognized the typical S shape.

Quote
I wonder if you can overlay also current (or voltage across sense resistor)
Data,including time, appear in the list box at the bottom of the diagram.
Current is kept at a constant value and needs no trending.

For this test: I=700mA, mAh integration ended up at 658 mAh, total discharge time: 56' 20"

I am preparing the LCD stand alone version, I hope to be ready this week end.

Yves
« Last Edit: December 02, 2009, 01:50:33 pm by kas » Logged

0
Offline Offline
Sr. Member
****
Karma: 17
Posts: 389
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Now, the stand alone version with integrated LCD



This a serial display, back from my P*r*ll*x time  smiley-wink

The additional code
Code:
#define     LCDdisplay       1           // LCD display

In Setup()
Code:
#if defined LCDdisplay
  pinMode(TXPin, OUTPUT);              //------LCD setup-------//
  digitalWrite(TXPin,HIGH);  
  LCD.begin(9600);                     //9600 baud is chip comm speed
  LCD.print(22, BYTE);                 // cursor off, no blink
  LCD.print(12, BYTE);                 // clear screen
  delay(5);                            //----------------------
#endif

in display()
Code:
#if defined LCDdisplay
  LCD.print(12, BYTE);                         // **LCD**  clear screen
  delay(5);                                    
  LCD.print(L1, BYTE);
  if((loopCount/(60000/LOOP))<100)             LCD.print("0");
  if((loopCount/(60000/LOOP))<10)              LCD.print("0");              
                                               LCD.print((loopCount-1)/(60000/LOOP));
  LCD.print(L1+3, BYTE);                       LCD.print(":");
  LCD.print(L1+4, BYTE);
  if(((loopCount%(60000/LOOP))*LOOP/1000)<10)  LCD.print("0");              
                                               LCD.print((loopCount%(60000/LOOP))*LOOP/1000);
  LCD.print(L1+8, BYTE);                       LCD.print("mAh");
  LCD.print(L1+12, BYTE);                      LCD.print((int)mAmpH);
  LCD.print(L2, BYTE);                         LCD.print("mV");
  LCD.print(L2+3, BYTE);                       LCD.print((int)mVolt);
  LCD.print(L2+9, BYTE);                       LCD.print("mA");
  LCD.print(L2+12, BYTE);                      LCD.print((int)mAmp);
#endif

That's all folks, hope you enjoyed reading

@+
Yves
Logged

tytower
Guest
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
P*r*ll*x
Whats this ? and why the necessity to cloak it ?
Are you using this in the picture . What is its relevence?
« Last Edit: December 05, 2009, 04:31:31 pm by tytower » Logged

0
Offline Offline
Sr. Member
****
Karma: 17
Posts: 389
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
P*r*ll*x

Whats this ? and why the necessity to cloak it ?
Are you using this in the picture . What is its relevence?

Private joke  smiley-wink
Some of us started learning microcontrollers with the Basic Stamp from Parallax: http://www.parallax.com/tabid/295/Default.aspx

Easy language, tons of documentation,
allthough technically limited, Basic Stamp is, in my opinion, the best option for absolute beginers (Julien...  :smiley )
« Last Edit: December 07, 2009, 01:15:19 pm by kas » Logged

0
Offline Offline
Newbie
*
Karma: 0
Posts: 8
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hello Kas,

your battery discharger is exactly the type of projects I bought my Arduino for, but I'm afraid I'm not fit enough yet to get it done by the plan and the photos, so I would very much appreciate if you could answer me some questions:
-what is the green (quite big) part on your photos? I assume it is R2? You talk about a shunt resistor in your text. Is this the part and what are the specifications that I have to search for when I would like to order it?
-I would like to build your AdaFruit Shield version. In the photo I saw that you use a different IC there. Is it LM358N? Is it used the same way as the LM324?
-Do you have some more photos of the AdaFruid Shield version? Is it Version 2 already?
-how is the jumper for different voltages wired?

Thanks in advance. I'm looking forward to measure the capacity of my rechargeable battery collection (mainly AA and AAA-types)


« Last Edit: April 20, 2010, 02:58:58 pm by bitcurrent » Logged

0
Offline Offline
Sr. Member
****
Karma: 17
Posts: 389
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hi bitcurrent

You are right, the green big thingy is R2; this is a 0.47R 8W shunt resistor (SETA RB60)
Only one OpAmp is required for this project.
LM324 is a Quad OpAmp, LM358 is a dual OpAmp, both are inexpensive and OK for the job.
I finally switched to LM358 (8 pins) to save room on the PCB

The top side looks nice

http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1266140108


The other side is... a bit more cluttered smiley-wink



Adafruit shield is V.5 as per http://www.adafruit.com/index.php?main_page=product_info&cPath=17_21&products_id=51


My advices:
First build your prototype on a breadboard http://www.adafruit.com/index.php?main_page=product_info&cPath=17&products_id=64&zenid=f74428807bfbe75ac921a42ac9b73ff6
Install only basic parts, ignore relay, buzzer and voltage divider
You don't need the heatsink if you only want to test AA or AAA batteries
Make sure everything is OK before any soldering
Develop a simple software that displays Volts and Amps on your computer.
It will be easy to add features once you have the basic design right

Oh... I finally built vesion 1 circuit, please ignore V2
Good luck,this is a very educational project
yves
« Last Edit: April 24, 2010, 10:36:15 am by kas » Logged

Pages: [1] 2   Go Up
Jump to: