Unocharge NiMh battery charger

Here is my plan for John Zogg’s battery charger. It uses 3 analog inputs for each battery cell. I decided to use this one that flyback found on the internet is because it can turn off when it is done. It has a temperature sensor. It uses an Arduino Uno to control it. USB is not recommended for charging it as the 2x 10-ohm resistors go over the current limit on USB Current. The TMP-36 sensors must be attached to the batteries case. This is so it measures its temperature.

/*
 * UnoCharge - the arduino nimh charger
 * This is my version of the Arduino NiMh battery charger 
 * its modifications include Charge LED and multiple Battery support
 * Orginally from https://www.allaboutcircuits.com/projects/create-an-arduino-controlled-battery-charger/ 
 * Modified by delphijustin
 * Special Thanks to John Zogg and flyback
 */
byte nBatteries=2;//Number of batteries(1 through 5), other array variables must have the same number of values.
byte chargedLED = 2; // digital pin for LED
int batteryCapacity[] = {2500,2500};     //capacity rating of battery in mAh
float resistance[] = {10.0,10.0};     //measured resistance[b] of the power resistor
int cutoffVoltage = 1600;     //maximum battery voltage (in mV) that should not be exceeded
float cutofftemperatureC = 35;     //maximum battery temperature that should not be exceeded (in degrees C)
//float cutoffTemperatureF = 95;     //maximum battery temperature that should not be exceeded (in degrees F)
long cutoffTime = 46800000;     //maximum charge time of 13 hours that should not be exceeded
byte outputPin[] = {9,6};     // Output signal wire connected to digital pin 9
int outputValue[] = {150,150};     //value of PWM output signal 
byte analogPinOne[] = {0,3};     //first voltage probe connected to analog pin 1
float ValueProbeOne[] = {0,0};     //variable to store the value of analogPinOne[b]
float voltageProbeOne[] = {0,0};     //calculated voltage at analogPinOne[b]
byte analogPinTwo[] = {1,4};     //second voltage probe connected to analog pin 2
float valueProbeTwo[] = {0,0};     //variable to store the value of analogPinTwo[b]
float voltageProbeTwo[] = {0,0};     //calculated voltage at analogPinTwo[b]
byte analogPinThree[] = {2,5};     //third voltage probe connected to analog pin 2
float valueProbeThree[] = {0,0};     //variable to store the value of analogPinThree[b]
float tmp36voltage[] = {0,0};     //calculated voltage at analogPinThree[b]
float temperatureC[] = {0,0};     //calculated temperature of probe in degrees C
//float temperatureF = 0;     //calculated temperature of probe in degrees F
float voltageDifference[] = {0,0};     //difference in voltage between analogPinOne[b] and analogPinTwo[b]
float batteryVoltage[] ={0,0};     //calculated voltage of battery
float current[] = {0,0};     //calculated current through the load (in mA)
float targetCurrent[] = {0,0};     //target output current (in mA) set at C/10 or 1/10 of the battery capacity per hour
float currentError[] = {0,0};     //difference between target current and actual current (in mA)

void setup()
{
pinMode(chargedLED,OUTPUT);
digitalWrite(chargedLED,LOW);
  Serial.begin(9600);     //  setup serial
  for(byte x=0;x<nBatteries;x++){
  targetCurrent[x]=batteryCapacity[x]/10;
  pinMode(outputPin[x], OUTPUT);     // sets the pin as output
  }
}

byte chargeStatus(){
  byte s=0;
  for(byte b=0;b<nBatteries;b++){
    if(outputValue[b]==0){s++;}
  }
if(s==nBatteries){
  digitalWrite(chargedLED,HIGH);
  }
  return s;
}

void loop()
{
  for(byte b=0;b<nBatteries;b++){ 
  Serial.println("Battery "+b);
  analogWrite(outputPin[b], outputValue[b]);  //Write output value to output pin

  Serial.print("Output: ");     //display output values for monitoring with a computer
  Serial.println(outputValue[b]); 

  ValueProbeOne[b] = analogRead(analogPinOne[b]);    // read the input value at probe one
  voltageProbeOne[b] = (ValueProbeOne[b]*5000)/1023;     //calculate voltage at probe one in milliVolts
  Serial.print("Voltage Probe One (mV): ");     //display voltage at probe one
  Serial.println(voltageProbeOne[b]);  
  
  valueProbeTwo[b] = analogRead(analogPinTwo[b]);    // read the input value at probe two
  voltageProbeTwo[b] = (valueProbeTwo[b]*5000)/1023;     //calculate voltage at probe two in milliVolts
  Serial.print("Voltage Probe Two (mV): ");     //display voltage at probe two
  Serial.println(voltageProbeTwo[b]);  
  
  batteryVoltage[b] = 5000 - voltageProbeTwo[b];     //calculate battery voltage
  Serial.print("Battery Voltage (mV): ");     //display battery voltage
  Serial.println(batteryVoltage[b]); 

  current[b] = (voltageProbeTwo[b] - voltageProbeOne[b]) / resistance[b];     //calculate charge current[b]
  Serial.print("Target Current (mA): ");     //display target current[b] 
  Serial.println(targetCurrent[b]);  
  Serial.print("Battery Current (mA): ");     //display actual current[b]
  Serial.println(current[b]);  
      
  currentError[b] = targetCurrent[b] - current[b];     //difference between target current[b] and measured current[b]
  Serial.print("Current Error  (mA): ");     //display current[b] error 
  Serial.println(currentError[b]);     

  valueProbeThree[b] = analogRead(analogPinThree[b]);    // read the input value at probe three  
  tmp36voltage[b] = valueProbeThree[b] * 5.0;     // converting that reading to voltage
  tmp36voltage[b] /= 1024.0; 
 
  temperatureC[b] = (tmp36voltage[b] - 0.5) * 100 ;     //converting from 10 mv per degree wit 500 mV offset to degrees ((voltage - 500mV) times 100)
  Serial.print("Temperature (degrees C) ");     //display the temperature in degrees C
  Serial.println(temperatureC[b]); 
 
 /*
  temperatureF = (temperatureC[b] * 9.0 / 5.0) + 32.0;     //convert to Fahrenheit
  Serial.print("Temperature (degrees F) ");
  Serial.println(temperatureF); 
 */
 
  Serial.println();     //extra spaces to make debugging data easier to read
  Serial.println();  



  if(abs(currentError[b]) > 10)     //if output error is large enough, adjust output
   {
    outputValue[b] = outputValue[b] + currentError[b] / 10;

    if(outputValue[b] < 1)    //output can never go below 0
     {
      outputValue[b] = 0;
     }

    if(outputValue[b] > 254)     //output can never go above 255
     {
      outputValue[b] = 255;
     }
    
    analogWrite(outputPin[b], outputValue[b]);     //write the new output value
   }
 
 
  if(temperatureC[b] > cutofftemperatureC)     //stop charging if the battery temperature exceeds the safety threshold
   {
    outputValue[b] = 0;
    Serial.print("Max Temperature Exceeded");
   }
   
  /*
  if(temperatureF > cutoffTemperatureF)     //stop charging if the battery temperature exceeds the safety threshold
   {
    outputValue[b] = 0;
   }
   */
   
   if(batteryVoltage[b] > cutoffVoltage)     //stop charging if the battery voltage exceeds the safety threshold
   {
    outputValue[b] = 0;
    Serial.print("Max Voltage Exceeded");
   }  
 
   if(millis() > cutoffTime)     //stop charging if the charge time threshold
   {
    outputValue[b] = 0;
    Serial.print("Max Charge Time Exceeded");
   }  
   delay(10000);     //delay 10 seconds for before next iteration
}
Serial.println();
Serial.print(chargeStatus());
Serial.print(" Out of ");
Serial.print(nBatteries);
Serial.print(" batteries fully charged");
}
Circuit
Charge LED Circuit(LED turns on only when all batteries are fully charged

Also, I am not sure if the MOSFET has to be special but it controls the charging voltage according to the All About Circuits page so I will use a IRF510 MOSFET from eBay.

Published by Justin Roeder

I am an electronics engineer and computer programmer that has autism. I learned by myself

Leave a comment

Your email address will not be published. Required fields are marked *