Arduino - Adjustable & Smart Battery Charger




After building a wireless controlled DCC garden train powered by 12volt battery packs of lead acid or NiMH or Li-Ion types, I required a battery charger that would charge them all in one go rather than individually. On finding an interesting article on the web for a design of a constant current source (thanks to Henry's Bench), I decided to adapt the design to create a battery charger.

This is an Arduino based, adjustable and smart battery charger, designed for 12 volt packs that can be adapted for single cells also. A LCD display gives the settings and charging values. A selector switch for set and run plus 3 potentiometers to set constant current, max charge voltage and charge time are included in the design.

Parts used: (all available on ebay unless indicated)
Arduino Pro Mini 5 Volt ATMEGA328 £3.00
MOS FET IRLB8743Pbf £1.25
5 Volt , 0.5 Amp Regulator - R-78C5.0-0.5 £4.46
Dual Op Amp (only one half used) - LM358 8 pin £0.36
3 Amp Current sense module - MAX471 £4.99
12 BitDigital to Analog Converter - MCP4725 £4.45
16 x 2 LCD module - HD44780 Backlit 1602 £3.19
Aluminium enclosure 192x112x61mm (RS) £13.78
3 off 10K potentiometers £4.92
1 off toggle switch SPDT £0.50
Strip board, connectors, wire and resistors £2.00

Step 1: Circuit Diagram

It is vital to know what you are doing when attempting to charge different types of batteries.

Over-charge or under-charge can damage certain types and can be dangerous.

Please read the website for details.

Here we have a flexible design to enable adjustment of max charge voltage, constant charge current and charge time.

For NiMH batteries, the timer is selected (> 5 minutes) the charger will deliver a preset constant current and the battery charge voltage is monitored for peak value before reducing by >50mv while charging 10 batteries in series (for a 12v supply). The timer should be set to about 4 hours as a back up to ensure no over charging

For lead acid and Li-Ion batteries , the timer is not set, the preset constant current will run until the preset max charge voltage is reached (lead acid typ 13.65v and Li-Ion typ 12.6v), after which it reduces the current by 10% each time the max is reached, thus giving a slow reduction in current during the saturation phase important to Lithium-Ion batteries.
This charger is not designed to charge Li-Poly batteries where each cell must be monitored and controlled separately.

When the maximum power across the MOSFET is reached (Wmax) the system shuts down.
Wmax value will depend on the heatsink attached to the MOSFET.
For example, a cast aluminium box with 500 sq cm surface area.
To achieve a maximum temperature increase above ambient of 45 deg C with a heat sink/box rated at 1.5 deg C per watt, Wmax, the max power dissipated by MOSFET = 45/1.5 = 30;

A LM358 controls the bias on a Mosfet until the current measured by the MAX471, matches what has been called for at pin 3 of the op amp.

A MCP4725 Digital to Analog Converter provides an input to pin three of the op amp.

The MAX471 will provide a 1 volt output for 1 Amp of current measured. Its measurement range is limited to 3 amps, this sketch limits the constant current to 2.5 amps Max.

Step 2: Arduino Sketch

#include "Wire.h"
#include "Adafruit_MCP4725.h"
#include "Adafruit_LiquidCrystal.h"

Get these library files from Github.

Adafruit_LiquidCrystal lcd(12, 11, 5, 4, 3, 2);
These are the pins connected to the LCD display.

Values used in this circuit are:
Ardunio Vdd = 5.02 R1 = 22k, R2 = 4.7k, Voh = (analogRead(A2) x 5.02 /1023) * ((22+4.7)/4.7)
R1 and R2 are the resistors across the supply and another pair across the MOS FET
The value of each graduation on the analog inputs is,
mv = (float) 1000 * (Vdd/1023) * ((R1+R2)/R2) = = 27.87 mv

Voh = analogRead(A2) * mv
Power supply input, Vin = 16.2 rated at 3 Amps;

dac.begin(0x60); // The I2C Address: Run the I2C Scanner if you're not sure
uint32_t dac_value;
dac.setVoltage(Vdac, false); - sets the digital to analog output of the MCP4725
Vdac = 0; sets current to zero
To provide 1 Amp constant current -
dac.setVoltage(819, false);
Iset = 1.0;

A value of819 sets a current of1 Amp, therefore other values can be calculated
Iset = (float)Vdac / 819.00; // 819 = 1 Amp // 2046 max // 2046/819 = 2.5 Amp max

For NiMH batteries, we need to detect peak battery charge voltage, Vbat then detect a drop off by 50mv for 10 in series (5mv per cell) - only applies when timer is set.
Timer should be set to about 240 mins to ensure no over charging
The peak battery voltage is calculated from 10 readings of Vbat then an average value calculated Vbat_avg

For Lead Cell and Li-Ion batteries, charge limited to specified max charge volts - only applies when timer is not set. When the charge voltage Vbat, meets the pre-set value Vset, the current is reduced to 90%.
This continues to reduce each time Vset is reached until a minimum value of 10% of Iset is reached, then power is turned off. This routine allows the battery to go through a saturation phase, important ti Lithium batteries.

if (Vbat >= Vset && Tset < 5) // Detect Vbat reaches Vset, provided timer is off
Vdac = 0.9*Vdac; // reduce Vdac / Iset to 90%
if (Iact < (0.1 * Iset)){ // test to check actual current is below 10% of Iset
charged = true; // if true, switch of current
Vdac = 0;



    • Paper Contest

      Paper Contest
    • Remix Contest

      Remix Contest
    • Tape Contest

      Tape Contest

    12 Discussions


    9 months ago

    what components would you recommend for a 60v system litium-ion batteries please ?


    11 months ago

    I am considering a variation of your circuit to build a helicopter external power source, called Ground Power Unit (GPU). Helicopters work on 28 VDC. I would use two 12 Volt gel batteries and two 2 V cells. Could you be so kind as suggest adaptations on your circuit and program? very many thanks.


    11 months ago

    Hi, i cant find MOS FET IRLB8743 from local store,,can you suggest me another transistor equivalent characteristics or replacable to it,,,,

    waiting for your answer,,,,,


    6 replies

    Reply 11 months ago

    thnx for reply,,,i made this project accordint to the circuit diagram u provided...

    my half lcd display is not showing results,,i also replaced the lcd but same results(lcd is ok ,,kindly check the circuit)

    need help


    Reply 11 months ago

    kindly tell me what is the purpose of 2 switches (near max471)


    in circuit ACS712 is used as current sensing module ,,

    i used max471 instead of ACS712 (is it ok??)

    w8ing for reply



    Reply 11 months ago

    this circuit is little bit different from the previous u uploaded in tutorial section...

    thnxx for reply,,gonna try this ...

    will contact you if i found any difficulty...



    Reply 11 months ago

    kindly tell me what is the purpose of 2 switches (near max471)


    in circuit ACS712 is used as current sensing module ,,

    i used max471 instead of ACS712 (is it ok??)

    w8ing for reply



    1 year ago

    what components would you recommend for a 48v system

    2 replies

    Reply 1 year ago

    Would this be a 48v lead acid cell battery? You would need to increase R1 and R4 to 87k, increased C3 voltage to >60v and replace the 5v regulator with one that can take at least 60 volt input. High transient voltage peaks may need to be considered in the design. Not sure if all this would work for you, but maybe worth a go.


    Reply 1 year ago

    thank you very much for your response. It is a 48V lithium pack for a golf cart. I have since decided that it would be much better to charge the cells in parallel in order increase the balancing of the cells.