You are on page 1of 15

/* This programme is written for charging Trojan T-225Ah 6/12Volt open Lead Acid

batteries (LAB),
* but it can easily be adapted for another LAB's and/or charge values.
* Before I give an explanation, intended as a guide, about charging LAB's; an
important note:
* ***** Do NOT leave a LAB in a discharged condition or discharge it too low
******
* This will drastically shorten its life, if not completely destroy it! Always
charge
* a LAB after usage, a.s.a.p.! There are different types of LAB's, each with its
own characteristics.
* There are open LAB's and closed LAB's, also called VRLA (valve-regulated-lead-
acid), such as gell-
* and AGM-batteries. Batteries are build for different purposes; deep-cycle, car,
marine, etc, etc. Each
* have their own characteristics and charge patterns. If you want to know more
about LAB's, a highly
* recommended read would be: http://www.victronenergy.dk/upload/documents/Book-
Energy-Unlimited-EN.pdf
* Each LAB knows 3x charge-stages; Float-, Absorption- and an Equalisation-
charge. Normally an
* absorption-charge is sufficient to recharge the battery and to keep it in a
good shape. After
* the absorption-charge, a float-charge can be applied to keep the battery
constantly "topped-up".
* An Equalisation-charge is only required either; every few months or when the
specific-gravity of
* the acid in a individual cell differs more than 0.02 sg compared to the other
cells, from
* the same battery. Via a switch, the charger can be set for 6V or 12V. Another
mode-switch selects
* absorption-charge (Trojan 6V T-225: 7.40V, 12V: 14.8V) or equalization charge
(Trojan: 7.75V / 15.5V).
* In either case, this sketch will keep the voltage at the absorption voltage /
float level,
* or at the equalization voltage level; whichever charge-mode has been selected.
* In the absorption-mode, when the current reaches 2% of the battery capacity,
* the battery is considered to be full; in this case 2% of 225Ah = 4.5Amps @
7.40V.
* When in absorption charge, this sketch switches to float-charge as soon as the
"battery full
* current" is reached. Be aware that this isn't the case in equalization mode!!
* The duration of an Equalisation-charge should be no longer until the acid
specific gravity of all cells
* have an equal, or nearly equal readings. An Equalisation charge is very hard on
the battery
* and should only be performed when necessary, as short as possible and
manually / observed.
* In no way the charger & battery should be left unattended during an
equalisation charge.
* Each type of LAB has its own manufacture recommended charge-voltages. Check
yours first!!
* Since charging of a LAB is a chemical process, it needs time to occur. The
charge-current
* for a LAB is therefor max. 10% of the battery capacity. For a 225Ah LAB, this
is no more
* than 22.5 Amps (lower is fine too). Of course, the charge-source self, the
Mosfet and the cables,
* all have to be suitably rated for these high currents.
* During charging, a close eye needs to be kept on the temperatures of all
components involved;
* the Mosfet, the battery, the cables, panels / transformer etc.
* The same schematic pricipals were used as from lewis Loflin
(http://www.bristolwatch.com/solar1.htm).
* If you like an excellent thorough explanation of how the schematic works,
please visit his website.
* An Arduino (in this case a Arduino mini pro) steers, via a NPN transistor, a
"P-channel" Mosfet.
* The In/Out voltage is read via a resistor voltage divider and the current is
measured via
* a 25Amp ASC711 Hall Sensor.
* Combined with LED-indicators, a 16x2 LCD is added for read-out, checks &
messages.
* The Arduino is powered via a 5V L7805, 1.5 Amp voltage regulator. The regulator
is connected to
* the incoming voltage on the charge-side.
* When, instead of Solar-panels, a transformer is used, a circuitry protection
against induction
* Voltage-spikes has to be included.
* When the charger is connected the the battery and switched on, best is to press
the reset-button.
* This will ensure that the Arduino has the latest correct Voltage readings.
Failure to do so,
* may cause that the Arduino has incorrect readings in its memory, taken while
starting up / connecting up.
* For in the 12Volt charging mode, a cooling fan with an LM35 temperature sensor
can be included.
* To include, all the code in between the "optional cooling fan" dotted lines
have to be Uncommented.
* This example code is in the public domain.
*
modified 24 November 2015
by RvD.
*/

#include<Wire.h>// include I2C wiring LCD display


#include<LiquidCrystal_I2C.h> // include display I2C, connect SDA to A4, SCL
to A5
LiquidCrystal_I2C LCD(0x3F, 16, 2); // tells Adruino the LCD I2C address and
display size. The chip ACF8574-AT
// has I2C address 0x3F, the chip ACF8574-T has
I2C address 0x27
# define chargeReading A0 // Analog pin for reading charger voltage
# define batteryReading A1 // analog pin for reading battery voltage
# define ampReading A2 // analog pin for reading output-voltage from
the current-sensor
# define transistorPin 13 // output pin via a 2.2kΩ resistor to NPN-
transistor basis for Mosfet control.
# define modeSwitchPin 2 // selector Switch for absorption or
equalization charge
# define zenerByPassPin 11 // to write transistor High to Bypass zener in
6V mode
# define absorptionLed 3 // pin to steer absorption indicator Led
# define equalizationLed 4 // pin to steer equalization indicator Led
# define twelveVLed 5 // pin to steer twelve-volt indicator Led
# define sixVLed 6 // pin to steer six-volt indicator Led
//--------------------------Begin of optional cooling fan-------------------
# define tempCPin A3 // Pin for LM35 temperature sensor input
# define temperatureLed 8 // warning Led in case the temperature exceeds
max-temperature
# define fanPWMTransistor 9 // pin, via 2.2kΩ resistor, to base of fan PWM
switching transistor
//--------------------------End of optional cooling fan-------------------
int batteryVoltage = 0; // initialize and define batteryVoltage
int chargeVoltage = 0; // initialize and define chargeVoltage
int ampVoltage = 0; // initialize and define voltage from ACS711
current-sensor
int floatVoltage6V = 260; // float voltage 6.60V => ADC reading over
1k/6.8k divider
int absorptionVoltage6V = 292; // absorption voltage 7.40V => ADC reading over
a 1k/6.8k divider
int equalizeVoltage6V = 306; // equalization voltage 7.75V => ADC reading
over a 1k/6.8k divider
int lowCutOffVoltage6V = 217 ; // Below 5.5V something is wrong with the
clamps or worse, the battery
float conversionFactor6V = 0.02534; // Conversion factor in the 6V range to get
from the analog value to Voltage
int sixOrTwelvePoint = 475; // six-or-twelve volt charge cross-over point
set at around 11.5V
int floatVoltage12V = 522; // float voltage 13.2V => ADC reading over
1k/6.8k divider
int absorptionVoltage12V = 586; // absorption voltage 14.8V => ADC reading over
a 1k/6.8k divider
int equalizeVoltage12V = 614; // equalization voltage 15.5V => ADC reading
over a 1k/6.8k divider
int lowCutOffVoltage12V = 455; // Battery Voltage below 11.5 V, something is
wrong with the clamps or the battery
float conversionFactor12V = 0.02525;// Conversion factor in the 12V range to get
from the analog value to Voltage
float battFullCurrent = 4.0; // Current (in Amps) at which the batt is
considered full during absoption and
// switches over to float charge.
float battFullCurrentAnalog; // number used after conversion from
battFullCurrent to analog number.
int currentZero = 514; // ADC number given by the ACS711 current-
sensor with no current flowing
int gridFrequency = 50; // Grid Frequency, change if required.
float periodTime; // time in milltseconds of 1 full grid-cycle;
50Hz = 20ms, 60Hz = 16.66ms
float averageAmpVoltage = 0; // Since the Current is AC, averages are taken
float averageChargeReading; // Since the charge Voltage is AC, averages are
taken
float currentADCRatio = 16.735; // current-sensor ADC reading calibrated for 1
ampere.
float ampere; // declare a variable
int switchPosition; // declare a variable for absorption or
equalize position
//-------------------------Begin of optional cooling fan--------------------
int tempC; // temperature read from the temperature sensor
int fanSpeed; // the PWM duty cycle for the fan speed
int tempMin = 70; // minimum temerature in degC at which the fan
has to start cooling at minimum speed
int tempMax = 85; // the maximum temperature in degC at which the
fan has to run full speed
long previousMillis = 0;
long interval = 1000; // setting the blaink rate in milli-seconds
//--------------------------End of optional cooling fan--------------------

void setup() {

Serial.begin(9600); // Setup the serial monitor, very handy for


trouble shooting
analogReference(EXTERNAL); // Instead of using the default 5V supply, a
TL431 with 2.5 voltage reference is used
pinMode(chargeReading, INPUT); // setup pinMode for input from voltage
divider charger side
pinMode(batteryReading, INPUT); // setup pinMode for input from voltage
divider battery side
pinMode(ampReading, INPUT); // setup pinMode for input from current-sensor
pinMode(zenerByPassPin, OUTPUT); // setup pinMode for output to bypass
transistor zener.
digitalWrite(zenerByPassPin, LOW); // set the base of the zener bypass transistor
LOW = OFF.
pinMode(transistorPin, OUTPUT); // Mosfet steering is done via the transistor
base. Putting the transistor base
// HIGH, pulls the Mosfet Gate to ground = LOW
=> Mosfet "ON"
digitalWrite(transistorPin, LOW); // set the base of the switching Transistor
LOW => OFF
pinMode (modeSwitchPin, INPUT); // Switch (STDP) for selecting absorption or
equalize-charge
digitalWrite(modeSwitchPin, LOW); // write mode-switch low for absorptiob charge
pinMode(sixVLed, OUTPUT); // set six-volt LedPin mode as output
digitalWrite(sixVLed, LOW); // set low = 6V indicator led off
pinMode(twelveVLed, OUTPUT); // set twelve-volt LedPin as output
digitalWrite(twelveVLed, LOW); // set low = q2V indicator led off
pinMode(absorptionLed, OUTPUT); // set absorption indicator ledpin as output
digitalWrite(absorptionLed, LOW); // set pin Low
pinMode(equalizationLed, OUTPUT); // set equalization indicator ledpin as output
digitalWrite(equalizationLed, LOW);// set pin Low
//---------------------------Begin of optional cooling fan-----------------
pinMode (tempCPin, INPUT); // set pin to receive LM35 temperature sensor
output
pinMode (fanPWMTransistor, OUTPUT);// set the pin to steer the base of the fan
steering transistor
digitalWrite(fanPWMTransistor,LOW);// set pin low = transistor off
pinMode (temperatureLed, OUTPUT); // set the pin for the high temperature
warning led
digitalWrite(temperatureLed,LOW); // set pin low = temperature Led off
//---------------------------End of optional cooling fan-------------------
LCD.init(); // initialise LCD
LCD.backlight(); // Turn-on backlight, which is oof in default
LCD.setCursor(0, 0); // set the cursor at the top-left-hand corner
periodTime = 1000 / gridFrequency; // in milliseconds
battFullCurrentAnalog = (battFullCurrent * currentADCRatio); // converting user
amp input to ADC reading

void loop() {

// Determine whether the charger is set for 6V or 12V charge


// Because the Charge-Transformer is AC, more Voltage readings are taken and then
averaged out
int j = 1; // set, or reset, counter
averageChargeReading = 0; //reset averageAmpVoltage
while (j <= 2 * periodTime) {
averageChargeReading += analogRead(chargeReading);
j++;
delay(1);
}
chargeVoltage = (averageChargeReading / (2 * periodTime)); // calculating the
average charge Voltage

if (chargeVoltage <= sixOrTwelvePoint) { // if lower than sixOrTwelvePoint, do


the 6V charge, else 12V charge

// ------------------------- Initialization of 6 Volt


charge-----------------------------

digitalWrite(sixVLed, HIGH); // Led indicating the program is in 6V charge


mode
digitalWrite(twelveVLed, LOW); // as a precaution and to remove previous
settings
switchPosition = digitalRead(modeSwitchPin); // check the mode switch
selection; absorption or equalize

if (switchPosition == HIGH && chargeVoltage <= sixOrTwelvePoint) { // mode


switch HIGH means 6V equalisation has been selected

//---------------------------Begin of 6V Equalisation
loop------------------------------

digitalWrite(equalizationLed, HIGH); // set equalization indicator Led


digitalWrite(absorptionLed, LOW); // set absorption indicator Led

batteryVoltage = analogRead(batteryReading); // Read battery Voltage

// Because the Charge-Transformer is AC, more Voltage readings are taken and
then averaged out
int j = 1; // set, or reset, counter
averageChargeReading = 0; //reset averageAmpVoltage
while (j <= 2 * periodTime) {
averageChargeReading += analogRead(chargeReading);
j++;
delay(1);
}

chargeVoltage = (averageChargeReading / (2 * periodTime)); // calculating the


average charge Voltage

Serial.println(chargeVoltage);

if ((chargeVoltage < equalizeVoltage6V) && (batteryVoltage >


lowCutOffVoltage6V)) { // check charge voltage
LCD.home();
LCD.print("Charge Volt Low ");
LCD.setCursor(0, 1);
LCD.print(" ");
} // end of if statement

if ((chargeVoltage <= equalizeVoltage6V) && (batteryVoltage <=


lowCutOffVoltage6V)) { // check both Voltages
LCD.home();
LCD.print("IN & OUT too Low");
LCD.setCursor(0, 1);
LCD.print(" ");
} // end of if statement

if ((chargeVoltage > equalizeVoltage6V) && (batteryVoltage <=


lowCutOffVoltage6V)) {
/* check battery voltage.
If below the set threshold "lowCutOffVoltage", the charger will not
start to charge.
* Either the clamps are not good connected or the battery has been
drained so far, that it most likely has been damaged.
* In that case, the threshold voltage can be set lower, but now the
battery has to be supervised during the charge process.
* Even if the battery (partially) recovers, damage has been done and
has shorten its lifetime / capacity */

LCD.home();
LCD.print("Batt Volt LOW!");
LCD.setCursor(0, 1);
LCD.print(" ");
}

if ((chargeVoltage > batteryVoltage) && (chargeVoltage <= sixOrTwelvePoint)


&& (batteryVoltage <= equalizeVoltage6V) && (chargeVoltage > equalizeVoltage6V) &&
(batteryVoltage > lowCutOffVoltage6V)) {
// if all these 5 conditions are true, start charging.
// if one of the conditions is not true, no charging will occur. This also
means that when the battery clamps are not connected,
// no voltage is supplied to them and therefor no risk of shorting them.

LCD.home();
LCD.print("Equal ");
LCD.print("Batt=");
LCD.print(batteryVoltage * conversionFactor6V);
LCD.print ("V");

int chargeON = (equalizeVoltage6V - batteryVoltage) * 100; // determine the


Mosfet ON time
chargeON = abs(chargeON); // make it alway a positive number

digitalWrite(zenerByPassPin, HIGH); // set zener bypass Mosfet high, to


exclude Mosfet Vgs protection zener
digitalWrite (transistorPin, HIGH); // transistor turns Mosfet gate LOW =
ON
delay (0.5 * chargeON); // to get the charge current started and stabelize

// Because the chargeCurrent is an AC current, more readings are taken and


then averaged out
int j = 1; // set, or reset, counter
averageAmpVoltage = 0; //reset averageAmpVoltage
while (j <= 2 * periodTime) {
averageAmpVoltage += analogRead(ampReading);
j++;
delay(1);
}

averageAmpVoltage = averageAmpVoltage / (2 * periodTime);


ampVoltage = currentZero - averageAmpVoltage;
ampVoltage = abs(ampVoltage); // make ampVoltage always a positive voltage
ampere = ampVoltage / currentADCRatio; // convert ampVoltage to amperes
LCD.setCursor(0, 1); // reset cursor
LCD.print("Current:"); // print to LCD
LCD.print(ampere); // print to LCD
LCD.print(" Amp"); // print to LCD

delay(0.5 * chargeON);
digitalWrite(transistorPin, LOW); // transistor turns off, Mosfet gate goes
HIGH => OFF
digitalWrite(zenerByPassPin, LOW); // set zener bypass Mosfet LOW, to
include Mosfet Vgs protection zener

} // end of if statement

switchPosition = digitalRead(modeSwitchPin); //check swithMode for changes


chargeVoltage = analogRead(chargeReading); // check the chargeVoltage again
for 6-12V chargeMode
delay(10); // to allow anolagReading to
settle

} // end of if statement

//----------------------------End of 6V Equalize loop-----------------------------

//--------------------------- Begin of 6V Absorption loop-------------------------

else {

digitalWrite(equalizationLed, LOW); // set equalization indicator Led


digitalWrite(absorptionLed, HIGH); // set absorption indicator Led

// Because the Charge-Transformer is AC, more Voltage readings are required


and then averaged out
int j = 1; // set, or reset, counter
averageChargeReading = 0; //reset average Voltage on the AC charge side
while (j <= 2 * periodTime) { // take readings for 2 periods
averageChargeReading += analogRead(chargeReading); // compound readings
j++; // add to counter
delay(1);
} // delay 1ms

chargeVoltage = (averageChargeReading / (2 * periodTime));


batteryVoltage = analogRead(batteryReading);
ampVoltage = abs(currentZero - analogRead(ampReading));

if ((chargeVoltage < absorptionVoltage6V) && (batteryVoltage >


lowCutOffVoltage6V)) { // check the charge voltage
LCD.home();
LCD.print("Charge Volt LOW ");
LCD.setCursor(0, 1);
LCD.print(" ");
} // end of if statement

if ((chargeVoltage <= absorptionVoltage6V) && (batteryVoltage <=


lowCutOffVoltage6V)) {// check charge and batt
LCD.home();
LCD.print("IN & OUT too LOW");
LCD.setCursor(0, 1);
LCD.print(" ");
} // end of if-statement

if ((chargeVoltage > absorptionVoltage6V) && (batteryVoltage <=


lowCutOffVoltage6V)) {
/* check battery voltage,
if below the set threshold "lowCutOffVoltage", the charger will not
charge.
* Either the clamps are not good connected or the battery has been
drained so far, that it most likely has been damaged.
* In that case, the threshold voltage can be set lower, but now the
battery has to be supervised during the charge process.
* Even if the battery (partially) recovers, damage has been done and
has shorten its lifetime / capacity */

LCD.home();
LCD.print("Batt Volt LOW! ");
LCD.setCursor(0, 1);
LCD.print(" ");
}

if ((chargeVoltage > batteryVoltage) && (chargeVoltage <= sixOrTwelvePoint)


&& (batteryVoltage <= absorptionVoltage6V) && (chargeVoltage > absorptionVoltage6V)
&& (batteryVoltage > lowCutOffVoltage6V)) {
// if all these 5 conditions are true, start charging.
// if one of the conditions is not true, no charging will occur. This also
means that when the battery clamps are not connected, no voltage is supplied
// to them and therefor no risk of shorting.

LCD.home();
if (absorptionVoltage12V == floatVoltage12V) {
LCD.print("Float ");
}

else {
LCD.print("AbsP ");
}

LCD.print("Batt=");
LCD.print(batteryVoltage * conversionFactor6V);
LCD.print ("V");

int chargeON = (absorptionVoltage6V - batteryVoltage) * 100; // determine


the Mosfet ON time
chargeON = abs(chargeON); // make it alway a positive number

digitalWrite(zenerByPassPin, HIGH); // set zener bypass Mosfet high, to


exclude Mosfet Vgs protection zener
digitalWrite (transistorPin, HIGH); // transistor turns Mosfet gate LOW =
ON
delay (0.5 * chargeON); // time to give charge current to start and
stabelize

// Because the chargeCurrent is an AC current, more readings are taken and


then averaged out
int j = 1; // set, or reset, counter
averageAmpVoltage = 0; //reset averageAmpVoltage
while (j <= 2 * periodTime) {
averageAmpVoltage += analogRead(ampReading);
j++;
delay(1);
}

averageAmpVoltage = averageAmpVoltage / (2 * periodTime);


ampVoltage = currentZero - averageAmpVoltage;
ampVoltage = abs(ampVoltage); // make ampVoltage always a positive voltage
ampere = ampVoltage / currentADCRatio; // convert ampVoltage to amperes
LCD.setCursor(0, 1); // reset cursor
LCD.print("Current:"); // print to LCD
LCD.print(ampere); // print to LCD
LCD.print(" Amp"); // print to LCD
Serial.println(ampere);

delay(0.5 * chargeON);
digitalWrite(transistorPin, LOW); // transistor turns off, Mosfet gate goes
HIGH => OFF
digitalWrite(zenerByPassPin, LOW); // set zener bypass Mosfet LOW, to
include Mosfet Vgs protection zener

} // end of if-statement

if (ampVoltage <= battFullCurrentAnalog && batteryVoltage >=


absorptionVoltage6V && chargeVoltage >= floatVoltage6V) {
// if raw ampreading <= battery full current and battery Voltage >=
floatVoltage

absorptionVoltage6V = floatVoltage6V; // change absorption Voltage to float


Voltage.
batteryVoltage = analogRead (batteryReading);
LCD.clear();
LCD.home();
LCD.print("Float charge");
LCD.setCursor(0, 1);
LCD.print("Batt: ");
LCD.print(batteryVoltage * conversionFactor6V);
LCD.print("V");
delay(200);
}

switchPosition = digitalRead(modeSwitchPin); //check swithMode for changes


chargeVoltage = analogRead(chargeReading); // check the chargeVoltage again
for 6-12V chargeMode
delay(10); // to allow anolagReading to
settle

} // end of else statement


//---------------------------------End of 6V Absoption
loop-------------------------------
} // end of 6V charging mode

else { // -----------------------Initialization of 12V charging


----------------------------
digitalWrite(zenerByPassPin, LOW); // set zener bypass Mosfet low, to include
Mosfet Vgs protection zener
digitalWrite(sixVLed, LOW); // as a precaution and to remove previous
settings.
digitalWrite(twelveVLed, HIGH); // Led indicating the program is in 6V charge
mode

//---------------------------------Begin optional cooling fan


----------------------------

tempC = (analogRead(tempCPin)* 0.48828125);// read temperature sensor and


convert to Celcius

if(tempC < tempMin) { // if temp is lower than minimum


temp
fanSpeed = 0; // set value of variable.
digitalWrite(fanPWMTransistor, LOW); // write base of fan transistor
LOW => Fan = OFF.
}
if(tempC >= tempMin) { // if temperature is
higher than minimum temp, start cooling
fanSpeed = map(tempC, tempMin, tempMax, 60, 255); // convert temperature
reading to PWM output range, a starting
// duty cycle of 60 to
overcome initial fan starting friction
fanSpeed = constrain (fanSpeed, 60, 255); // constrain fanSpeed
within PWM range
analogWrite(fanPWMTransistor, fanSpeed); // PWM to the fan.
}

if(tempC > tempMax) { // if temp is higher than


tempMaxa, start the temperature waring Led
unsigned long currentMillis = millis(); // Read current
milliseconds clock
if(currentMillis - previousMillis > interval){ // compare
previousMillis = currentMillis;
if(temperatureLed == LOW){ // if temperature Led is
Low, set High.
digitalWrite(temperatureLed, HIGH);
}
else { // if temperature Led is
High, set Low.
digitalWrite(temperatureLed, LOW);
}
}
}
//---------------------------------End of optional cooling fan
--------------------------

switchPosition = digitalRead(modeSwitchPin); // check the mode switch


selection; absorption or equalize

if (switchPosition == HIGH && chargeVoltage > sixOrTwelvePoint) { // mode


switch HIGH means 12V equalisation has been selected

//---------------------------------Begin of 12V Equalisation


loop---------------------

digitalWrite(equalizationLed, HIGH); // set equalization indicator Led


digitalWrite(absorptionLed, LOW); // set absorption indicator Led

batteryVoltage = analogRead(batteryReading); // Read battery Voltage

// Because the Charge-Transformer is AC, more Voltage readings are taken and
then averaged out
int j = 1; // set, or reset, counter
averageChargeReading = 0; //reset averageAmpVoltage
while (j <= 2 * periodTime) {
averageChargeReading += analogRead(chargeReading);
j++;
delay(1);
}

chargeVoltage = (averageChargeReading / (2 * periodTime)); // calculating the


average charge Voltage

if ((chargeVoltage < equalizeVoltage12V) && (batteryVoltage >


lowCutOffVoltage12V)) { // check charge voltage
LCD.home();
LCD.print("Charge Volt Low ");
LCD.setCursor(0, 1);
LCD.print(" ");
} // end of if statement

if ((chargeVoltage <= equalizeVoltage12V) && (batteryVoltage <=


lowCutOffVoltage12V)) { // check both Voltages
LCD.home();
LCD.print("IN & OUT too Low");
LCD.setCursor(0, 1);
LCD.print(" ");
} // end of if statement

if ((chargeVoltage > equalizeVoltage12V) && (batteryVoltage <=


lowCutOffVoltage12V)) {
/* check battery voltage.
If below the set threshold "lowCutOffVoltage", the charger will not
start to charge.
* Either the clamps are not good connected or the battery has been
drained so far, that it most likely has been damaged.
* In that case, the threshold voltage can be set lower, but now the
battery has to be supervised during the charge process.
* Even if the battery (partially) recovers, damage has been done and
has shorten its lifetime / capacity */

LCD.home();
LCD.print("Batt Volt LOW! ");
LCD.setCursor(0, 1);
LCD.print(" ");
}

if ((chargeVoltage > batteryVoltage) && (batteryVoltage <=


equalizeVoltage12V) && (chargeVoltage > equalizeVoltage12V) && (batteryVoltage >
lowCutOffVoltage12V)) {
// if all these 4 conditions are true, start charging.
// if one of the conditions is not true, no charging will occur. This also
means that when the battery clamps are not connected,
// no voltage is supplied to them and therefor no risk of shorting them.
LCD.home();
LCD.print("Equal ");
LCD.print("Batt=");
LCD.print(batteryVoltage * conversionFactor12V);
LCD.print ("V");

int chargeON = (equalizeVoltage12V - batteryVoltage) * 100; // determine


the Mosfet ON time
chargeON = abs(chargeON); // make it alway a positive number

digitalWrite (transistorPin, HIGH); // transistor turns Mosfet gate LOW =


ON
delay (0.5 * chargeON); // to get the charge current started and stabelize

// Because the chargeCurrent is an AC current, more readings are taken and


then averaged out
int j = 1; // set, or reset, counter
averageAmpVoltage = 0; //reset averageAmpVoltage
while (j <= 2 * periodTime) {
averageAmpVoltage += analogRead(ampReading);
j++;
delay(1);
}

averageAmpVoltage = averageAmpVoltage / (2 * periodTime);


ampVoltage = currentZero - averageAmpVoltage;
ampVoltage = abs(ampVoltage); // make ampVoltage always a positive voltage
ampere = ampVoltage / currentADCRatio; // convert ampVoltage to amperes
LCD.setCursor(0, 1); // reset cursor
LCD.print("Current:"); // print to LCD
LCD.print(ampere); // print to LCD
LCD.print(" Amp"); // print to LCD

delay(0.5 * chargeON);
digitalWrite(transistorPin, LOW); // transistor turns off, Mosfet gate goes
HIGH => OFF
} // end of if statement

switchPosition = digitalRead(modeSwitchPin); //check swithMode for changes


chargeVoltage = analogRead(chargeReading); // check the chargeVoltage again
for 6-12V chargeMode
delay(10); // to allow anolagReading to settle
} // end of if statement

//-----------------------------End of 12V Equalize loop-----------------------

//-----------------------------Begin of 12V Absorption loop----------------------

else {

digitalWrite(equalizationLed, LOW); // set equalization indicator Led


digitalWrite(absorptionLed, HIGH); // set absorption indicator Led

// Because the Charge-Transformer is AC, more Voltage readings are required


and then averaged out
int j = 1; // set, or reset, counter
averageChargeReading = 0; //reset average Voltage on the AC charge side
while (j <= 2 * periodTime) { // take readings for 2 periods
averageChargeReading += analogRead(chargeReading); // compound readings
j++; // add to counter
delay(1);
} // delay 1ms

chargeVoltage = (averageChargeReading / (2 * periodTime));


batteryVoltage = analogRead(batteryReading);
ampVoltage = abs(currentZero - analogRead(ampReading));

if ((chargeVoltage < absorptionVoltage12V) && (batteryVoltage >


lowCutOffVoltage12V)) { // check the charge voltage
LCD.home();
LCD.print("Charge Volt LOW ");
LCD.setCursor(0, 1);
LCD.print(" ");
} // end of if statement

if ((chargeVoltage <= absorptionVoltage12V) && (batteryVoltage <=


lowCutOffVoltage12V)) {// check charge and batt
LCD.home();
LCD.print("IN & OUT too LOW");
LCD.setCursor(0, 1);
LCD.print(" ");
}

if ((chargeVoltage > absorptionVoltage12V) && (batteryVoltage <=


lowCutOffVoltage12V)) {
/* check battery voltage,
if below the set threshold "lowCutOffVoltage", the charger will not
charge.
* Either the clamps are not good connected or the battery has been
drained so far, that it most likely has been damaged.
* In that case, the threshold voltage can be set lower, but now the
battery has to be supervised during the charge process.
* Even if the battery (partially) recovers, damage has been done and
has shorten its lifetime / capacity */

LCD.home();
LCD.print("Batt Volt LOW! ");
LCD.setCursor(0, 1);
LCD.print(" ");
}

if ((chargeVoltage > batteryVoltage) && (batteryVoltage <=


absorptionVoltage12V) && (chargeVoltage > absorptionVoltage12V) && (batteryVoltage
> lowCutOffVoltage12V)) {
// if all these 4 conditions are true, start charging.
// if one of the conditions is not true, no charging will occur. This also
means that when the battery clamps are not connected, no voltage is supplied
// to them and therefor no risk of shorting them.

LCD.home();
if (absorptionVoltage12V == floatVoltage12V) {
LCD.print("Float ");
}
else { LCD.print("AbsP ");}
LCD.print("Batt=");
LCD.print(batteryVoltage * conversionFactor12V);
LCD.print ("V");
int chargeON = (absorptionVoltage12V - batteryVoltage) * 100; // determine
the Mosfet ON time
chargeON = abs(chargeON); // make it alway a positive number

digitalWrite (transistorPin, HIGH); // transistor turns Mosfet gate LOW =


ON
delay (0.5 * chargeON); // time to give charge current to start and
stabelize

// Because the chargeCurrent is an AC current, more readings are taken and


then averaged out

int j = 1; // set, or reset, counter


averageAmpVoltage = 0; //reset averageAmpVoltage
while (j <= 2 * periodTime) {
averageAmpVoltage += analogRead(ampReading);
j++;
delay(1);
}
averageAmpVoltage = averageAmpVoltage / (2 * periodTime);
ampVoltage =abs (currentZero - averageAmpVoltage);
ampere = ampVoltage / currentADCRatio; // convert ampVoltage to amperes
LCD.setCursor(0, 1); // reset cursor
LCD.print("Current:"); // print to LCD
LCD.print(ampere); // print to LCD
LCD.print(" Amp"); // print to LCD

delay(0.5 * chargeON);
digitalWrite(transistorPin, LOW); // transistor turns off, Mosfet gate goes
HIGH => OFF

} // end of if-statement

if (ampVoltage <= battFullCurrentAnalog && batteryVoltage >=


absorptionVoltage12V && chargeVoltage >= floatVoltage12V) {
// if raw ampreading <= battery full current and battery Voltage >=
floatVoltage

absorptionVoltage12V = floatVoltage12V; // change absorption Voltage to


float Voltage.

LCD.home();
LCD.print("Float charge ");
LCD.setCursor(0, 1);
LCD.print("Batt: ");
LCD.print(batteryVoltage * conversionFactor12V);
LCD.print("V ");
delay(20);

}
switchPosition = digitalRead(modeSwitchPin); // check swithMode for changes
chargeVoltage = analogRead(chargeReading); // check the chargeVoltage again
for 6-12V chargeMode
delay(10); // to allow anolagReading to
settle
} // end of else statement
//-----------------------------------End of 12V Absoption
loop------------------------
} // end of else statement.

}// end of void-loop

You might also like