Arduino 12V Lead-Acid Battery Charger

In this post we are going learn how to make a smart automatic lead-acid battery charger which can charge 6V and 12V battery types with capacity ranging from 4.5Ah to 15Ah. The proposed lead-acid battery charger is feature-rich and packed with several safety and convenience functions, yet simple design. We will also learn how to charge a standard lead-acid battery and its important charging parameters.

This lead-acid battery charger is closely related to previous smart li-ion battery charger circuit.

 We will see:

  • Functions of the proposed lead-acid battery charger.
  • How to charge a standard lead-acid battery.
  • Circuit diagram of the 12v / 6V lead-acid battery charger.
  • Program code for Arduino.
  • Prototype.
  • How to operate this charger and its functions.

Functions of this automatic lead-acid battery charger:

Arduino Lead-Acid Battery Charger
  1. Automatic full battery cut-off.
  2. Automatic timer cut-off.
  3. Overcharge current cut-off.
  4. Automatic current sensor calibration.
  5. CC and CV Charging.
  6. Real-time current consumption and CC / CV mode on display.
  7. Reverse polarity protection.
  8. Charging current recommendation. 
  9. Wide charging range from 4.5Ah to 15Ah and can charge 6V and 12V battery types.

We will dive into each and every functions mentioned here in the later part of this post.

How to charge a lead-acid battery properly?

Before we start building the project it is very important to know how to charge a lead-acid battery properly with its correct voltage, current and cut-off parameters. Only after knowing these factors we can build a charger that can charge a battery properly with negligible harm.

Standard lead-acid batteries are charged in 3 phases:

  1. Constant current.
  2. Constant voltage.
  3. Trickle charge.

Charging characteristics graph of a lead acid battery:

Lead Acid battery charging characteristics
Lead Acid battery charging characteristics

Constant current phase: When we connect a discharged battery to a charger, the charger voltage falls to a point where the battery is discharged and voltage rises slowly and the battery will try to consume all the current available (limited by the charger).

Maximum current will be consumed by the battery till the terminal voltage reaches 14.4V (for 12V battery) which is the voltage limited by the charger. Approximately 70% of the battery is charged in this phase and this is the fastest charging phase.

In a nutshell, constant current is the phase where the voltage is varying (rising) and current is constant with time. See the part of the blue line (current) which is constant with time and rising yellow line (voltage).   

Constant voltage phase: When the battery reaches 14.4V, current start to fall as shown in the graph (blue line). Meanwhile the voltage is now constant with time (yellow line).

In this phase rest of the 30% battery is charged and this is the slowest part of charging phase.

In a nutshell, constant voltage is the phase where the voltage is constant with time and current is varying (falling).

Trickle charge: Trickle charging is done by applying current equal to battery’s self-discharge rate; this will keep the batteries at full voltage and ready to take over the load when needed.

In the proposed charger, trickle charge function is not included; this is because we will remove the battery from the charger for our intended use soon or later once the battery reached full charge.

What is “cyclic” and “standby” usage of lead-acid battery?

Charging parameters of a lead-acid battery also depends on how you discharge the battery and this is classified into two types:

  • Cyclic usage
  • Standby usage

Cyclic usage: The battery usage is said to be cyclic when you use the battery as primary power source on regular basis and you recharge it when the battery is empty.

Example: Portable electronics, Electric wheel chair, Electric rickshaw, Golf cart etc.  

Standby usage: The battery usage is said to be standby when you use the battery as an emergency supply for your load. The battery is kept at float charge to keep the battery full so that in case of main power supply fails the battery can kick-in immediately and take over the load.

Example: Inverters, computer UPS, emergency lights etc.

What is charging voltage for a lead-acid battery?

NOTE: we are going to charge the battery according to cyclic usage parameter.

For 12V battery:

  • Standby usage: 13.6V to 13.8V
  • Cyclic usage: 14.1 to 14.4V

We will be applying 14.4V to charge a 12V battery.

For 6V battery:

  • Standby usage: 6.75 to 6.9V
  • Cyclic usage: 7.20 to 7.5V

We will be applying 7.5V to charge a 6V battery.

What is charging current for a lead acid battery?

The battery should be charged with a current less than or equal to manufacturer’s recommendation mentioned on the battery as “maximum initial current”. Universally A lead acid battery can be charged with current limit of 10% to 30% of the battery capacity that is 0.1C to 0.3C. C = battery capacity.

For example if your battery is 7Ah (12V or 6V) you can apply current from:

  • 7Ah x 0.1 = 0.7A (to) 7Ah x 0.3 = 2.1A

Some battery manufacturers say not to charge above 0.2C while some manufacturers say not to above 0.3C. Since our charger must suit all the brands, we found charging a lead-acid battery at 0.2C was optimal and safe.

What is the cut-off current for lead-acid battery?

A lead-acid battery is said to be fully charged (generally) when the charging current reaches 3% to 5% of the battery capacity. The proposed charger will cut-off the supply when the charging current reaches 4% of the battery capacity.

For example, a 7Ah battery is said to be fully charged when the current falls below,

4% x Ah = I (cut-off current)

4 / 100 x 7 = 280mA.

A battery is also said to be charged fully when charging current is no more falling.

Circuit diagram for lead-acid battery charger:

Arduino Lead-Acid Battery Charger Circuit

Circuit description:

The circuit consists of fewer components for a smart battery charger. Read the below given explanation clearly to get an idea how to setup the hardware correctly.

Input current and voltage:

Voltage:

  • If you are charging a 12V battery the input voltage must be strictly 15V (no less or no more).
  • If you are charging a 6V battery the input voltage is 9V.

Current:

If you are charging a 7Ah battery the minimum current must be 1.9A and this calculated as follows:

0.2 x 7Ah = 1.4A

1.4A + 0.5A = 1.9A (minimum input current). Addition of 500mA is for powering Arduino, LCD, relay etc.

For 4.5Ah battery:

0.2 x 4.5Ah = 0.9A

0.9A + 0.5A = 1.4A (minimum)

You should calculate input current for other battery capacities if you want.

CC / CV Buck converter:

CC / CV Buck Converter
CC / CV Buck Converter

This is a buck converter module with current limiting feature and this will limit current and voltage to the battery undercharge. We have to set appropriate voltage and current by adjusting the potentiometer provided on the board.   

How to set voltage:

  • Apply 15V to the buck converter.
  • Connect your multimeter with DC 20V range at buck converter’s output.
  • Rotate the voltage potentiometer using a tiny screw driver clockwise to increase the voltage and anti-clockwise to decrease.
  • For charging a 12V battery set the output to exactly 14.4V.
  • For charging a 6V battery set the output to exactly 7.5V.

How to set current:

  • Set you multimeter to 10A DC range.
  • Connect your multimeter at the output of buck converter, which will short circuit the output. Since the output is current limited this won’t harm the buck converter. You may even see some sparks while touching multimeter probes at the output.
  • Using a small screw driver, rotate the current potentiometer clockwise to increase the current and anti-clockwise to decrease.
  • You must set the current limit according to I = 0.2 x Ah. (You should not add 0.5A here)

ACS712 5A current sensor:

ACS712 current sensor 5A
ACS712 current sensor 5A

ACS712 is a Hall Effect current sensor which comes in 5A, 20A and 30A variants, in this project we are going to use only the 5A variant and rest of the two variants won’t work with this project.

ACS712 sensor works on the principle that a current carrying conductor induces magnetic field around it and the strength of the field depends on the current flow. The magnetic field is measured by the on-board IC which outputs analog signal proportional to the current flow through the sensor. 

A problem with this type of current sensor is that the output is rich in noise and picks-up stray electromagnetic fields around the sensor. Fortunately this can be overcome by properly calibrating the sensor and noise can be further reduced by doing the following which will give us reliable current measurement:

Add a 0.47uF capacitor in parallel with the shown SMD component:

ACS712 current sensor 5A
ACS712 current sensor 5A

Twist the current carrying wire as shown:

ACS712 current sensor 5A
ACS712 current sensor 5A

Relay:

A 12V relay is employed here to cut-off and to connect the battery to the charging supply. 12V relay is chosen so that you can charge a 6V battery where we will apply 9V as input and a 12V relay can fully activate at 9V.

When you charge a 12V battery you will apply (exactly) 15V at input and a 12V relay can operate at 15V (which the maximum) without any issues.

The relay is activated by a low power transistor and a diode across the relay coil will absorb high voltage spikes that generated during triggering the relay and ON and OFF, thus protecting the transistor and Arduino board from high voltage. 

LCD with I2C adapter:

LCD with I2C Adapter
LCD with I2C Adapter

A 16 x 2 LCD display is employed in this project to show the status about the connected battery. An I2C adapter is used here to drive the display with just 4 wires, this reduces wiring related issues that may arise and connections can be done with ease.

Battery Reverse polarity protection:

Lead-acid batteries can release huge amount of current when short-circuited or charged with its polarity reversed. This result in extreme heat on wires which can even glow red and eventually cause permanent damage to the battery if this occurs frequently. Reverse polarity can kill the charger in one shot.

To avoid such situation we must include some mechanism to break the short circuit quick enough so that our charger and battery will remain unharmed. This is achieved by connecting a fuse in series with one of the battery polarity and connecting a diode (in reverse bias) across the battery, as shown below:

Battery Reverse Polarity Protection

When the battery is connected in correct polarity the diode is reverse biased which will result in current flowing through the load. But when the battery polarity is reversed the diode forward biases and short-circuit the battery which will blow the fuse instantly and stop further harm to the battery or to the charger.

INC and START push buttons:

Two push buttons are provided, one (INC – increment) for entering battery capacity to the charger and another one (START) to start charging process. Using INC- increment button you can set battery capacity from 4500mAh to 15000mAh.

Download library files:

ACS712 library: github link

I2C library: github link

Program Code:

//-------© Electronics-Project-hub-------//
#include "ACS712.h"
#include <EEPROM.h>
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27, 16, 2);
#define sensorInput A0
ACS712 sensor(ACS712_05B, sensorInput);

//------ Time out Setting --------//
int h_lt = 7; // in hrs
int m_lt = 0; // in min
// -------------------------------//

const int relay = 5;
const int inc = 4;
const int ok = 3;
int address = 0;
int batt_cap;
int current_lt = 0;
float peak_I_lt = 0;
float cut_off = 0;
boolean set_batt = true;
boolean var = true;
int i = 0;
int hrs = 0;
int Min = 0;
int sec = 0;
float currentReading;
float CV_current = 0;
void setup()
{
  pinMode(relay, OUTPUT);
  digitalWrite(relay, LOW);
  pinMode(inc, INPUT_PULLUP);
  pinMode(ok, INPUT_PULLUP);
  lcd.init();
  lcd.backlight();
  EEPROM.get(address, batt_cap);
  if (batt_cap < 4500)
  {
    EEPROM.put(address, 4500);
  }
  lcd.clear();
  while (set_batt)
  {
    lcd.setCursor(0, 0);
    lcd.print("Enter capacity:");
    lcd.setCursor(0, 1);
    EEPROM.get(address, batt_cap);
    lcd.print(batt_cap);
    lcd.print(" mAh");
    if (digitalRead(inc) == LOW)
    {
      while (var)
      {
        if (digitalRead(ok) == LOW) var = false;
        if (digitalRead(inc) == LOW)
        {
          lcd.setCursor(0, 1);
          batt_cap = batt_cap + 500;
          if (batt_cap > 15000)
          {
            batt_cap = 4500;
            lcd.clear();
          }
          lcd.setCursor(0, 0);
          lcd.print("Enter capacity:");
          lcd.setCursor(0, 1);
          lcd.print(batt_cap);
          lcd.print(" mAh");
          delay(250);
        }
      }
    }
    if (digitalRead(ok) == LOW)
    {
      EEPROM.put(address, batt_cap);
      lcd.clear();
      lcd.setCursor(0, 0);
      lcd.print("Your battery");
      lcd.setCursor(0, 1);
      lcd.print("is ");
      lcd.print(batt_cap);
      lcd.print(" mAh.");
      delay(2000);
      lcd.clear();
      lcd.setCursor(0, 0);
      lcd.print("Set current");
      lcd.setCursor(0, 1);
      lcd.print("limit = ");
      //------- Charging Parameters ----------//
      current_lt = batt_cap * 0.2;
      peak_I_lt = batt_cap * 0.3 * 0.001;
      cut_off = batt_cap * 0.04 * 0.001; 
      //-------------------------------------//
      lcd.print(current_lt);
      lcd.print(" mA");
      delay(3000);
      set_batt = false;
    }
  }
  current_calib();
  CCCV();
}

void loop()
{
  for (i = 0; i < 10; i++)
  {
    currentReading = sensor.getCurrentDC();
    delay(100);
  }
  timer();
  lcd.clear();
  lcd.setCursor(0, 0);
  if (currentReading <= CV_current)
  {
    lcd.print("MODE:CV");
  }
  if (currentReading > CV_current)
  {
    lcd.print("MODE:CC");
  }
  lcd.setCursor(0, 1);
  lcd.print("CURRENT: ");
  lcd.print(currentReading);
  lcd.print(" A");
  if (currentReading <= cut_off)
  {
    for (i = 0; i < 10; i++)
    {
      currentReading = sensor.getCurrentDC();
      delay(100);
    }
    if (currentReading <= cut_off)
    {
      digitalWrite(relay, LOW);
      lcd.clear();
      lcd.setCursor(0, 0);
      lcd.print("BATTERY FULLY");
      lcd.setCursor(0, 1);
      lcd.print("CHARGED.");
      while (true) {}
    }
  }
  currentReading = sensor.getCurrentDC();
  if (currentReading >= peak_I_lt)
  {
    digitalWrite(relay, LOW);
    current_calib();
    digitalWrite(relay, HIGH);
    delay(3000);
    currentReading = sensor.getCurrentDC();
    if (currentReading >= peak_I_lt)
    {
      while (true)
      {
        digitalWrite(relay, LOW);
        lcd.clear();
        lcd.setCursor(0, 0);
        lcd.print("Overcharging");
        lcd.setCursor(0, 1);
        lcd.print("current detected");
        delay(2000);
        lcd.clear();
        lcd.setCursor(0, 0);
        lcd.print("Charging halted.");
        lcd.setCursor(0, 1);
        lcd.print("Press reset.");
        delay(2000);
      }
    }
  }
}

void current_calib()
{
  lcd.clear();
  lcd.print("Auto Calibrating");
  lcd.setCursor(0, 1);
  lcd.print("Current Sensor.");
  sensor.calibrate();
  delay(1000);
  currentReading = sensor.getCurrentDC();
  if (currentReading >= 0.02 || currentReading <= -0.02 )
  {
    sensor.calibrate();
    delay(5000);
    currentReading = sensor.getCurrentDC();
    if (currentReading >= 0.02)
    {
      current_calib();
    }
  }
}

void timer()
{
  sec = sec + 1;
  if (sec == 60)
  {
    sec = 0;
    Min = Min + 1;
    re_calib();
  }
  if (Min == 60)
  {
    Min = 0;
    hrs = hrs + 1;
  }
  if (hrs == h_lt && Min == m_lt)
  {
    digitalWrite(relay, LOW);
    while (true)
    {
      lcd.clear();
      lcd.setCursor(0, 0);
      lcd.print("Time out !!!");
      lcd.setCursor(0, 1);
      lcd.print("Charge Completed");
      delay(2000);
      lcd.clear();
      lcd.setCursor(0, 0);
      lcd.print("  Press reset");
      lcd.setCursor(0, 1);
      lcd.print("****************");
      delay(2000);
    }
  }
}

void re_calib()
{
  if (Min == 10 || Min == 20 || Min == 30 || Min == 40 ||
      Min == 50 || Min == 60 && sec == 0)
  {
    digitalWrite(relay, LOW);
    current_calib();
    digitalWrite(relay, HIGH);
  }
}

void CCCV()
{
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("Analyzing CC/CV");
  lcd.setCursor(0, 1);
  lcd.print("Modes...");
  digitalWrite(relay, HIGH);
  for (i = 0; i < 20; i++)
  {
    currentReading = sensor.getCurrentDC();
    delay(100);
  }
  if (currentReading <= -0.1)
  {
    while (true)
    {
      digitalWrite(relay, LOW);
      lcd.clear();
      lcd.setCursor(0, 0);
      lcd.print("Reverse current");
      lcd.setCursor(0, 1);
      lcd.print("detected.");
      delay(2000);
      lcd.clear();
      lcd.setCursor(0, 0);
      lcd.print("Flip current");
      lcd.setCursor(0, 1);
      lcd.print("sensor polarity.");
      delay(2000);
    }
  }
  CV_current = currentReading * 0.8;
}
//-------© Electronics-Project-hub-------//

Prototype:

12V Arduino Lead-Acid Battery Charger
12V Arduino Lead-Acid Battery Charger
12V Arduino Lead-Acid Battery Charger

How to operate this lead-acid battery charger:

Step 1: Set CC / CV buck converter’s output to 14.4V for 12V battery or 7.5V for 6V battery.

Step 2: Set CC / CV buck converter’s output to 0.2 x Ah.

Step 3: Press INC (increment) button to set the battery capacity. You can set from 4500 mAh to 15000 mAh.

Step 4: Press Start button. Charging process will begin.

Functions of this lead-acid battery charger:

  • Automatic full battery cut-off:

The battery automatically gets disconnected when the battery is full, that is when the current falls to 4% of the battery capacity.

  • Automatic timer cut-off:

When the battery is taking too long to reach full charge, this is a sign of a bad battery and current may not fall below the threshold. Any further charge could damage the battery and it must be cut-off soon. If the battery did not reach full charge within 7 hours, time-out algorithm will kick-in to disconnect the battery. 

  • Overcharge current cut-off:

If you (unintentionally) set a current limit beyond 0.3C, there is risk of damage to your battery. If the charging current is above 0.3C, charger will cut-off immediately and information will be displayed on the LCD.

Now you have to set the correct current limit to the CC/ CV buck converter.

  • Automatic current sensor calibration:

We are using ACS712 current sensor and its output is rich in noise, calibration need to be done to compensate the noise at the sensor’s output. We have programmed Arduino to automatically calibrate the current sensor. Auto calibration will be done at the beginning of the charge and every 10 minutes till the battery reaches full charge.

  • CC and CV charging:

The proposed charger will charge the battery in two stages constant current and constant voltage. You can know in which phase the battery is begin charged currently on the display. Constant voltage phase is detected when the current falls by 20% of the initial current. 

  • Charging current recommendation:

At the beginning of every charge for the given battery capacity the charger will recommend current limit (0.2 x Ah) that you should to set to CC / CV Buck converter, this is the optimal current for the battery.

The above shown current limit is for representative purpose only.

Points worth noting:

  • If your charger says “reverse current detected” on the LCD while building this project, you need to reverse the wire connections at screw terminals of ACS712 current sensor, this is because the current passing in reverse direction through the sensor and the program code cannot handle -Ve current readings.
  • If your battery reaches full charge quickly (and unexpectedly) and says battery is fully charged, this could be because of the following reasons:
  • You charged your battery fully recently.
  • Insufficient current at input (at buck converter’s input). You should apply minimum current as per [I = 0.2 x Ah + 0.5A].
  • You connected a dying battery (bad battery) which is not able to accept current provided by the charger. 

If you have any questions regarding this project, ask us in the comment you will get a guaranteed reply from us.