sim-flynn-13
Published © GPL3+

Simple Arduino Battery Capacity Tester

This tester can be used for NiCd, NiMh, and all flavors of Li-Ion rechargeables.

IntermediateShowcase (no instructions)4 hours43,858
Simple Arduino Battery Capacity Tester

Things used in this project

Hardware components

Arduino Pro Mini 328 - 5V/16MHz
SparkFun Arduino Pro Mini 328 - 5V/16MHz
Can be gotten just about anywhere online.
×1
20x4 LCD white on blue, with backlite
Original project used Nokia 5110 LCD. I don't have any on hand. I do have several of these....
×1
Power MOSFET N-Channel
Power MOSFET N-Channel
Close enough, I used what I had on hand, an AO D3N50 HEXFET.
×1
I2C/twi/spi interface module for 20x4 LCD
Saves pins, and libraries work quite well with these.
×1
Pushbutton switch 12mm
SparkFun Pushbutton switch 12mm
×1
Female Header 8 Position 1 Row (0.1")
Female Header 8 Position 1 Row (0.1")
Close. I bought several 20x1 sticks from eBay, and cut what I needed from them.
×1
terminal block two position
generic screw terminal block
×2
8 ohm 2w resistor
Needs to be at least 2W.
×1
Resistor 10k ohm
Resistor 10k ohm
×2
Speaker: 0.25W, 8 ohms
Speaker: 0.25W, 8 ohms
×1
prototyping pc board
×1
wire
×1

Software apps and online services

Arduino IDE
Arduino IDE

Hand tools and fabrication machines

Soldering iron (generic)
Soldering iron (generic)
solder
diagonal cutters

Story

Read more

Schematics

battery tester

fritzing file for breadboard. I haven't changed it from the original with the Nokia 5110. I will need to make the part in fritzing, along with the I2C/TWI/SPI interface board.

Code

Battery_Capacity_Check.ino

Arduino
/*
 * Li-Ion capacity tester.
 * set up:
 * 8 Ohm discharge load
 * ~190mA discharge rate.
 * I2C LCD.
 * MOSFET for discharge control.
 * 
 * software from e-battle.blogspot.com
 *
 * SCl pin = A5
 * SDA pin = A4
 *
 */


#include <Wire.h> 
#include <LiquidCrystal_I2C.h>

//LCD set-up
LiquidCrystal_I2C lcd(0x27,20,4);  // set the LCD address to 0x27 for a 20 chars and 4 line lcd

// definitions

#define STATE_WAITING 0
#define STATE_MEASURING 1
#define STATE_MEASURING_ENDED 2
#define BAT_LI 0
#define BAT_NI 1
#define BAT_UNREC 2
#define BAT_LI_DISCHARGED 3

//variables

float vtgBatLoaded; //shows the drop in cell V under load
float vtgBatUnloaded; //cell V for no load
float vtgLoad;
float vtgDropOnLoad;
float vtgDropRin; 
float rLoad=8; //resistanse of the load in Ohms
float rIn; //calculated cell internal resistance
float batCurrent;
float mAh; //running total cell capacity
uint8_t FET_Base=7; //otherwise known as the Gate.
uint8_t button = 6; 
uint8_t speaker= 5;
uint8_t state=STATE_WAITING;
float LiChargedVtg=4.35;
float LiCutoffVtg=2.9;
float NiChargedVtg=1.45;  
float NiCutoffVtg=1.1;
float cutoff;
uint8_t BatteryType;
boolean DischargeAllowed=false;
String BatTypeString;

void setup()
{
  pinMode(FET_Base,OUTPUT);
  pinMode(button,INPUT); //can be changed in the circuit to active low,
                         // will need to turn on the internal pull-up
  pinMode(speaker,OUTPUT);
  digitalWrite(FET_Base,LOW);
  noTone(speaker);
  lcd.init();
  lcd.backlight();
}

void loop()
{
   if (state==STATE_MEASURING)
   {
  
  vtgBatUnloaded=analogRead(0)*5.0/1024.0; //get the voltage of UNLOADED battery
  
  if (vtgBatUnloaded<cutoff)
  {
    state=STATE_MEASURING_ENDED;
    DischargeAllowed=false;
    for (uint8_t i=0;i<4;++i)
    {tone(speaker,2000,500); delay(500);noTone(5);delay(300);}
  }
  digitalWrite(FET_Base,HIGH); //turn the MOSFET on
  delay(1000);
  vtgBatLoaded=analogRead(0)*5.0/1024.0;   //get the voltage of LOADED battery
  vtgLoad=analogRead(1)*5.0/1024.0;
  digitalWrite(FET_Base,LOW);//turn the MOSFET off
  vtgDropOnLoad=vtgBatLoaded-vtgLoad;
  if(vtgDropOnLoad>0) batCurrent=vtgDropOnLoad/rLoad;
   else batCurrent=0;
  vtgDropRin=vtgBatUnloaded-vtgBatLoaded;
  if(batCurrent>0) rIn=vtgDropRin/batCurrent;
  else rIn=0;
  mAh+=batCurrent/3.6; //*1000.0/3600.0;
  lcd.clear();
  lcdState();
    lcd.setCursor(0,0);
    lcd.print(" Bat   Load    I ");
  lcd.setCursor(0,1);
  lcd.print(vtgBatUnloaded); lcd.print("V  ");lcd.print(vtgBatLoaded); lcd.print("V  ");lcd.print(batCurrent); lcd.print("A");
  lcd.setCursor(0,2);
  lcd.print("Rin= "); lcd.print(rIn); lcd.setCursor(11,2); lcd.print(" Ohm");
  lcd.setCursor(0,3);
  lcd.print("Cap= "); lcd.print(mAh); lcd.print(" mA/h"); 
  delay(500);
   } 
   else if (state==STATE_WAITING)
   {
     digitalWrite(FET_Base,LOW);//turn the MOSFET off
     vtgBatUnloaded=analogRead(0)*5.0/1024.0; //get the voltage of UNLOADED battery
     DefBatteryType();
     lcd.clear();
     lcdState();
     lcd.setCursor(0,0);
     lcd.print("Bat= "); lcd.print(vtgBatUnloaded); lcd.print(" V");
     lcd.setCursor(0,1);
     lcd.print(BatTypeString);
     lcd.setCursor(0,2);
     lcd.print("Test ");
     if (DischargeAllowed) lcd.print("allowed");
     else lcd.print("denied");
     CheckButtons();
     delay(500);
   }
   else if (state==STATE_MEASURING_ENDED)
   {
     digitalWrite(FET_Base,LOW);//turn the MOSFET off
     vtgBatUnloaded=analogRead(0)*5.0/1024.0; //get the voltage of UNLOADED battery
     lcd.clear();
     lcdState();
     lcd.setCursor(0,0);
     lcd.print("Bat= "); lcd.print(vtgBatUnloaded); lcd.print(" V");
     lcd.setCursor(0,1);
     lcd.print("Cap= ");lcd.print(mAh); lcd.print(" mA/h");     
     CheckButtons();
     delay(500);
   }
}

void CheckButtons(void) {
   
   if (digitalRead(button)==HIGH){ // if changed to active low.....you know what to do!
    switch (state){
      
    case STATE_WAITING : DefBatteryType();
    if (DischargeAllowed){ mAh=0; state=STATE_MEASURING;
    tone(speaker,1000,500); delay(500);noTone(5);}
    break;
    
    case STATE_MEASURING : state=STATE_MEASURING_ENDED;
    break;
    
    case STATE_MEASURING_ENDED : state=STATE_WAITING;
    break;
   }
 }
 }


void lcdState(void){
   String stateString;
   lcd.setCursor(0,0);
   if(state==STATE_WAITING) stateString="Waiting       ";
   if(state==STATE_MEASURING) stateString="Measuring     ";
   if(state==STATE_MEASURING_ENDED) stateString="Measuring done";
   lcd.print(stateString);
 }
    
void DefBatteryType(void){
   
       if (vtgBatUnloaded>LiCutoffVtg&&vtgBatUnloaded<LiChargedVtg)
       {BatteryType=BAT_LI; DischargeAllowed=true;BatTypeString="Li-ion battery";cutoff=LiCutoffVtg;}
       if (vtgBatUnloaded>NiCutoffVtg&&vtgBatUnloaded<NiChargedVtg)
       {BatteryType=BAT_NI; DischargeAllowed=true;BatTypeString="Ni-MH battery ";cutoff=NiCutoffVtg;}
       if (vtgBatUnloaded<LiCutoffVtg&&vtgBatUnloaded>NiChargedVtg)
       {BatteryType=BAT_LI_DISCHARGED; DischargeAllowed=false;BatTypeString="Li-ion battery";}
       if (vtgBatUnloaded<NiCutoffVtg||vtgBatUnloaded>LiChargedVtg)
       {BatteryType=BAT_UNREC; DischargeAllowed=false;BatTypeString="UNKNOWN bat   ";}
 }

Credits

sim-flynn-13

sim-flynn-13

1 project • 11 followers
Backyard Engineer

Comments