AA/AAA Battery Charger

Introduction

Battery Charger

Many AA or AAA battery chargers charge batteries in pairs, but plenty of devices use 1 or 3 batteries, meaning that some of your batteries get overcharged and some get undercharged. NiCd and NiMH batteries also benefit from an occasional full discharge, which most normal battery chargers won't do.

If you're anything like me you'll end up with a lot of rechargeable batteries, none of which end up being charged properly, and some of which turn out to be completely unusable. It'd be perfect if you had a low-power battery charger that you could leave on all the time, that would charge your batteries individually, automatically discharge them, and give you an idea of their real capacity. That's what you'll make in this tutorial!

Note: To make this nice and simple, the charger uses Espruino's GPIO pins to directly charge and discharge the batteries. This means it can't charge batteries very quickly (it can take days to charge and discharge them!).

You'll Need

Wiring Up

Battery Charger Wiring

Battery Charger

And you're done!

Software

Connect to the Web IDE, copy the following software into the right-hand side, and upload it:

var g;

B3.write(0); // GND
// B4.write(1); // Backlight
B5.write(1); // VCC

// The pins each battery is connected to
var BATS = [ B1, A7, A6, A5 ];

// The resistor's value
var RESISTOR_VALUE = 100;

// Are we charging or discharging batteries?
var batCharge = [ 0, 0, 0, 0 ];

// How much charge has gone into batteries (in mAh-ish)
var cntCharge = [ 0, 0, 0, 0 ];

// How much have batteries been discharged (in mAh-ish)
var cntDischarge = [ 0, 0, 0, 0 ];

function getBatteryVoltages() {
  var voltages = [0,0,0,0];
  // read voltages multiple times, and take an average
  var N = 20;
  for (var i=0;i<N;i++) {
    for (var b=0;b<BATS.length;b++) {
      digitalWrite(BATS[b], 0);
      voltages[b] += analogRead(BATS[b])*3.3/N;
    }
  }
  // Check for disconnected battery be enabling the pullup and seeing
  // if the voltage rises
  for (var b=0;b<BATS.length;b++) {
    pinMode(BATS[b], "input_pullup");
    if (digitalRead(BATS[b]))
      voltages[b] = -1; // no battery
    pinMode(BATS[b]); // auto
  }
  return voltages;
}

var lastInterval;

function onInterval() {
  var time = getTime() - lastInterval;
  lastInterval = getTime();
  var hrs = time/3600; // fractions of an hour

  // for each battery...
  var volts = getBatteryVoltages();
  for (var i=0;i<4;i++) {
    // update charge counters
    if (batCharge[i])
      cntCharge[i] += hrs*(3.3-volts[i])/RESISTOR_VALUE;
    else
      cntDischarge[i] += hrs*volts[i]/RESISTOR_VALUE;
    // work out if we're charging or discharging
    if (!batCharge[i] && volts[i]<=0.8)
      batCharge[i] = 1; // now charge
    if (volts[i] < 0) {
      // no battery - reset to defaults
      batCharge[i] = 0;
      cntCharge[i] = 0;
      cntDischarge[i] = 0;
    }
    digitalWrite(BATS[i], batCharge[i]);
  }

  // now update display
  g.clear();
  g.drawString("Battery Charger",0,0);
  g.drawLine(0,8,84,8);
  for (i=0;i<4;i++) {
    var x = 84*(i+0.5)/4;
    g.drawStringCenter(i+1, x, 12);
    g.drawLine(x-8,18,x+8,18);
    if (volts[i] >= 0) {
      g.drawStringCenter(batCharge[i] ? "CHG" : "DIS", x, 20);
      g.drawStringCenter(volts[i].toFixed(2), x, 28);
      g.drawStringCenter(cntDischarge[i] ? (cntDischarge[i]|0) : "-", x, 36);
      g.drawStringCenter(cntCharge[i] ? (cntCharge[i]|0) : "-", x, 42);
    } else {
      g.drawStringCenter("-", x, 20);
    }
  }
  g.flip();
}

function onInit() {
  var spi = new SPI();
  spi.setup({ sck:B6, mosi:B7 });
  g = require("PCD8544").connect(spi, A8 /*DC*/, B10 /*CE*/, B13 /*RST*/, function() {
    g.setRotation(2);
    g.clear();
    g.drawString("Loading...",0,0);
    g.drawLine(0,10,84,10);
    g.flip();
  });
  g.drawStringCenter = function(txt,x,y) {
    this.drawString(txt, x-this.stringWidth(txt)/2, y);
  };

  lastInterval = getTime();
  setInterval(onInterval, 2000);
}

// What happens when we press a button
setWatch(function() {
  if (batCharge=="0,0,0,0") batCharge.fill(1);
  else batCharge.fill(0);
  cntCharge.fill(0);
  cntDischarge.fill(0);
  onInterval();
}, BTN, { repeat: true, edge:"rising", debounce:50});

Then type save() in the left-hand size of the IDE, it should show Loading... on the LCD display, and 2 seconds later will start showing the charging status of the 4 batteries.

Using

Just plug in your batteries and they'll be recognised. The LCD will show the current voltage, and DIS next to the battery to mark that is is discharging (at around 20mA - this could take a few days!).

Next Steps

This page is auto-generated from GitHub. If you see any mistakes or have suggestions, please let us know.