Automated Battery charging and discharging station

Hi, I am having some trouble with an automated battery cycle station project.

Hardware used:

Arduino mega
12 x 2cell LiPo batteries --------> batt1 to batt12
2 x 6 way charger docks --------> charge_ON_OFF[2]
16way relay board( 12 relays connected to load resistors for discharge 4 relays to control charger on/off power
12 way voltage divider for analog voltage read

while everything electrical is working well, I am having issues when going form a charging to discharging. I would like to add a delay between each charge and discharge cycle to allow the batteries to stabilize/cool down. I have tried to set up the code in module's but I'm sure there is a better way of doing this so any advice is appreciated.

I also under stand that using a delay in most cases is non ideal but for this use case it seems to work well.


#include <LiquidCrystal_I2C.h>

LiquidCrystal_I2C lcd(0x27, 20, 4); // set the LCD address to 0x27 for a 16 chars and 2 line display

float Aref = 1.072;                // ***calibrate here*** | change this to the actual Aref voltage of ---YOUR--- Arduino
unsigned int total;                // can hold max 64 readings
float voltage;                     // converted to voltage to float for higher precision
float V_adjust = 15.750;                    // Value to adjust/calibrate voltage reading 
float batt1;      //float batt1CutOff = 6.4;
float batt2;      //float batt2CutOff = 6.4;
float batt3;      //float batt3CutOff = 6.4;
float batt4;      //float batt4CutOff = 6.4;
float batt5;      //float batt5CutOff = 6.4;
float batt6;      //float batt6CutOff = 6.4;
float batt7;      //float batt7CutOff = 6.4;
float batt8;      //float batt8CutOff = 6.4;
float batt9;      //float batt9CutOff = 6.4;
float batt10;     //float batt10CutOff = 6.4;
float batt11;     //float batt11CutOff = 6.4;
float batt12;     //float batt12CutOff = 6.4;


float batt_CUTOFF_LOW = 6.400;
float batt_CUTOFF_HIGH = 8.400;
float charg_OFF = constrain(batt_CUTOFF_HIGH, 8.390, 8.410);
float charg_ON  = constrain(batt_CUTOFF_LOW, 6.390, 6.410);

const int triggerType = LOW;   // your relay type

//-------------------------(0   1   2   3   4   5   6   7   8   9   10  11)--------> Control PIN LIST
const int controlPin[12] = {27, 29, 31, 33, 35, 37, 43, 45, 47, 49, 51, 53}; // define digital  output  pins  

//---------------------------(0   1)------------> Charge control pin list                                           
const int charge_ON_OFF[2] = {22,24};

unsigned long interval = 60*1000UL;    // To create Delay with out using delay function which halts all code 
unsigned long lastTime;
float batt_average;                   // average battery voltage of all 12 batteries 
 
//-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------//

void setup() {
  for (int i = 0; i < 13; i++)
  {
    pinMode(controlPin[i], OUTPUT);// set pin as output
    if (triggerType == LOW) {
      digitalWrite(controlPin[i], HIGH); // set initial state OFF for low trigger relay
    } 
  for (int i = 0; i < 3; i++)
  {
    pinMode(charge_ON_OFF[i], OUTPUT);// set pin as output
    if (triggerType == LOW) {
    
      digitalWrite(charge_ON_OFF[i], LOW); // set initial charger state on 
    }
  }
  
  }


  
  lcd.init();
  lcd.clear();
  lcd.backlight();                // Make sure backlight is on

  // Print a message on both lines of the LCD.
  lcd.setCursor(0, 0);            //Set cursor to character 2 on line 0
  lcd.print("Volt Master 2000");
  lcd.setCursor(0, 1);           //Move cursor to character 2 on line 1
  lcd.print(" Battery Tester");
  delay(2000);
  lcd.clear();

  analogReference(INTERNAL1V1); // use the internal ~1.1volt reference  | change (INTERNAL) to (INTERNAL1V1) for a Mega
  Serial.begin(9600); // set serial monitor to this value
}

void loop() {
 
  batt_1();
  batt_2();
  batt_3();
  batt_4();
  batt_5();
  batt_6();
  batt_7();
  batt_8();
  batt_9();
  batt_10();
  batt_11();
  batt_12();
  ChargeControl();
  
  
}

//------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
void batt_1() {

  for (int x = 0; x < 64; x++) { // multiple analogue readings for averaging
    total = total + analogRead(6); // add each value to a total
  }
  batt1 = (total / 64) * V_adjust * Aref / 1024 ; // convert readings to volt
 
  lcd.setCursor(0, 0);
    lcd.print("Batt 1 Voltage:");
    lcd.setCursor(0, 1);
    lcd.print(batt1 , 2);
    lcd.setCursor(5, 1);
    lcd.print(" V");
    Serial.print(voltage);
    total = 0; // reset value
    delay(1000); // 2 seconds between measurements
    
  if (batt1 <= batt_CUTOFF_LOW) {
    digitalWrite(controlPin[0], HIGH); // Stop Battery discharge at cut off volatage
  } 
  
}

//------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

void batt_2() {
  for (int x = 0; x < 64; x++) { // multiple analogue readings for averaging
    total = total + analogRead(5); // add each value to a total
  }
  batt2 = (total / 64) * V_adjust * Aref / 1024 ; // convert readings to volt
 
  lcd.setCursor(0, 0);
    lcd.print("Batt 2 Voltage:");
    lcd.setCursor(0, 1);
    lcd.print(batt2 , 2);
    lcd.setCursor(5, 1);
    lcd.print(" V");
    Serial.print(voltage);
    total = 0; // reset value
    delay(1000); // 2 seconds between measurements
    
  if (batt2 <= batt_CUTOFF_LOW) {
    digitalWrite(controlPin[1], HIGH); // Stop Battery discharge at cut off volatage
  } 
  
}
//--------------------------------------------------------------------------------------------------//
void batt_3() {

  for (int x = 0; x < 64; x++) { // multiple analogue readings for averaging
    total = total + analogRead(4); // add each value to a total
  }
  batt3 = (total / 64) * V_adjust * Aref / 1024 ; // convert readings to volt

  lcd.setCursor(0, 0);
    lcd.print("Batt 3 Voltage:");
    lcd.setCursor(0, 1);
    lcd.print(batt3 , 2);
    lcd.setCursor(5, 1);
    lcd.print(" V");
    Serial.print(voltage);
    total = 0; // reset value
    delay(1000); // 2 seconds between measurements
    
  if (batt3 <= batt_CUTOFF_LOW) {
    digitalWrite(controlPin[2], HIGH); // Stop Battery discharge at cut off volatage
  } 
  
}
//--------------------------------------------------------------------------------------------------//
void batt_4() {

  for (int x = 0; x < 64; x++) { // multiple analogue readings for averaging
    total = total + analogRead(3); // add each value to a total
  }
  batt4 = (total / 64) * V_adjust * Aref / 1024 ; // convert readings to volt

  lcd.setCursor(0, 0);
    lcd.print("Batt 4 Voltage:");
    lcd.setCursor(0, 1);
    lcd.print(batt4 , 2);
    lcd.setCursor(5, 1);
    lcd.print(" V");
    Serial.print(voltage);
    total = 0; // reset value
    delay(1000); // 2 seconds between measurements
    
  if (batt4 <= batt_CUTOFF_LOW) {
    digitalWrite(controlPin[3], HIGH); // Stop Battery discharge at cut off volatage
  } 
  
}
//--------------------------------------------------------------------------------------------------//
void batt_5() {

  for (int x = 0; x < 64; x++) { // multiple analogue readings for averaging
    total = total + analogRead(2); // add each value to a total
  }
  batt5 = (total / 64) * V_adjust * Aref / 1024 ; // convert readings to volt
    
    lcd.setCursor(0, 0);
    lcd.print("Batt 5 Voltage:");
    lcd.setCursor(0, 1);
    lcd.print(batt5 , 2);
    lcd.setCursor(5, 1);
    lcd.print(" V");
    Serial.print(voltage);
    total = 0; // reset value
    delay(1000); // 2 seconds between measurements
    
  if (batt5 <= batt_CUTOFF_LOW) {
    digitalWrite(controlPin[4], HIGH); // Stop Battery discharge at cut off volatage
  } 
  
}
//--------------------------------------------------------------------------------------------------//
void batt_6() {

  for (int x = 0; x < 64; x++) { // multiple analogue readings for averaging
    total = total + analogRead(1); // add each value to a total
  }
  batt6 = (total / 64) * V_adjust * Aref / 1024 ; // convert readings to volt

  lcd.setCursor(0, 0);
    lcd.print("Batt 6 Voltage:");
    lcd.setCursor(0, 1);
    lcd.print(batt6 , 2);
    lcd.setCursor(5, 1);
    lcd.print(" V");
    Serial.print(voltage);
    total = 0; // reset value
    delay(1000); // 2 seconds between measurements
    
  if (batt6 <= batt_CUTOFF_LOW) {
    digitalWrite(controlPin[5], HIGH); // Stop Battery discharge at cut off volatage
  } 
  
}
//--------------------------------------------------------------------------------------------------//
void batt_7() {

  for (int x = 0; x < 64; x++) { // multiple analogue readings for averaging
    total = total + analogRead(14); // add each value to a total
  }
  batt7 = (total / 64) * V_adjust * Aref / 1024 ; // convert readings to volt
 
  lcd.setCursor(0, 0);
    lcd.print("Batt 7 Voltage:");
    lcd.setCursor(0, 1);
    lcd.print(batt7 , 2);
    lcd.setCursor(5, 1);
    lcd.print(" V");
    Serial.print(voltage);
    total = 0; // reset value
    delay(1000); // 2 seconds between measurements
    
  if (batt7 <= batt_CUTOFF_LOW) {
    digitalWrite(controlPin[6], HIGH); // Stop Battery discharge at cut off volatage
  } 
  
}
//--------------------------------------------------------------------------------------------------//
void batt_8() {

  for (int x = 0; x < 64; x++) { // multiple analogue readings for averaging
    total = total + analogRead(13); // add each value to a total
  }
  batt8 = (total / 64) * V_adjust * Aref / 1024 ; // convert readings to volt

  lcd.setCursor(0, 0);
    lcd.print("Batt 8 Voltage:");
    lcd.setCursor(0, 1);
    lcd.print(batt8 , 2);
    lcd.setCursor(5, 1);
    lcd.print(" V");
    Serial.print(voltage);
    total = 0; // reset value
    delay(1000); // 2 seconds between measurements
    
  if (batt8 <= batt_CUTOFF_LOW) {
    digitalWrite(controlPin[7], HIGH); // Stop Battery discharge at cut off volatage
  } 
  
}
//--------------------------------------------------------------------------------------------------//
void batt_9() {

  for (int x = 0; x < 64; x++) { // multiple analogue readings for averaging
    total = total + analogRead(12); // add each value to a total
  }
  batt9 = (total / 64) * V_adjust * Aref / 1024 ; // convert readings to volt

  lcd.setCursor(0, 0);
    lcd.print("Batt 9 Voltage:");
    lcd.setCursor(0, 1);
    lcd.print(batt9 , 2);
    lcd.setCursor(5, 1);
    lcd.print(" V");
    Serial.print(voltage);
    total = 0; // reset value
    delay(1000); // 2 seconds between measurements
    
  if (batt9 <= batt_CUTOFF_LOW) {
    digitalWrite(controlPin[8], HIGH); // Stop Battery discharge at cut off volatage
  } 
  
}
//--------------------------------------------------------------------------------------------------//
void batt_10() {

  for (int x = 0; x < 64; x++) { // multiple analogue readings for averaging
    total = total + analogRead(11); // add each value to a total
  }
  batt10 = (total / 64) * V_adjust * Aref / 1024 ; // convert readings to volt

  lcd.setCursor(0, 0);
    lcd.print("Batt 10 Voltage:");
    lcd.setCursor(0, 1);
    lcd.print(batt10 , 2);
    lcd.setCursor(5, 1);
    lcd.print(" V");
    Serial.print(voltage);
    total = 0; // reset value
    delay(1000); // 2 seconds between measurements
    
  if (batt10 <= batt_CUTOFF_LOW) {
    digitalWrite(controlPin[9], HIGH); // Stop Battery discharge at cut off volatage
  } 
  
}
//--------------------------------------------------------------------------------------------------//
void batt_11() {

  for (int x = 0; x < 64; x++) { // multiple analogue readings for averaging
    total = total + analogRead(10); // add each value to a total
  }
  batt11 = (total / 64) * V_adjust * Aref / 1024 ; // convert readings to volt

  lcd.setCursor(0, 0);
    lcd.print("Batt 11 Voltage:");
    lcd.setCursor(0, 1);
    lcd.print(batt11 , 2);
    lcd.setCursor(5, 1);
    lcd.print(" V");
    Serial.print(voltage);
    total = 0; // reset value
    delay(1000); // 2 seconds between measurements
    
  if (batt11 <= batt_CUTOFF_LOW) {
    digitalWrite(controlPin[10], HIGH); // Stop Battery discharge at cut off volatage
  } 
  
}
//--------------------------------------------------------------------------------------------------//
void batt_12() {
  for (int x = 0; x < 64; x++) { // multiple analogue readings for averaging
    total = total + analogRead(9); // add each value to a total
  }
  batt12 = (total / 64) * V_adjust * Aref / 1024 ; // convert readings to volt
  
    lcd.setCursor(0, 0);
    lcd.print("Batt 12 Voltage:");
    lcd.setCursor(0, 1);
    lcd.print(batt12 , 2);
    lcd.setCursor(5, 1);
    lcd.print(" V");
    Serial.print(voltage);
    total = 0; // reset value
    delay(1000); // 2 seconds between measurements
    
  if (batt12 <= batt_CUTOFF_LOW) {
    digitalWrite(controlPin[11], HIGH); // Stop Battery discharge at cut off volatage
  } 
     
}

//----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

void ChargeControl()
{
  if ( ((batt1 >= charg_OFF)&&(controlPin[0], HIGH)) && ((batt2 >= charg_OFF)&&(controlPin[1], HIGH)) && ((batt3 >= charg_OFF)&&(controlPin[2], HIGH)) && ((batt4 >= charg_OFF)&&(controlPin[3], HIGH)) &&
       ((batt5 >= charg_OFF)&&(controlPin[4], HIGH)) && ((batt6 >= charg_OFF)&&(controlPin[5], HIGH)) && ((batt7 >= charg_OFF)&&(controlPin[6], HIGH)) && ((batt8 >= charg_OFF)&&(controlPin[7], HIGH)) &&
       ((batt9 >= charg_OFF)&&(controlPin[8], HIGH)) && ((batt10 >= charg_OFF)&&(controlPin[9], HIGH)) && ((batt11 >= charg_OFF)&&(controlPin[10], HIGH)) && ((batt12 >= charg_OFF)&&(controlPin[11], HIGH)))
       {
        digitalWrite(charge_ON_OFF[0], HIGH);
        digitalWrite(charge_ON_OFF[1], HIGH);
        lcd.clear();
        lcd.setCursor(0,0);
        lcd.print("Charge complete");
        lcd.setCursor(0,1);
        lcd.print("Cool Down !");
        

        delay(5000);
        lcd.clear();

        digitalWrite(controlPin[0], LOW);
        digitalWrite(controlPin[1], LOW);
        digitalWrite(controlPin[2], LOW);
        digitalWrite(controlPin[3], LOW);
        digitalWrite(controlPin[4], LOW);
        digitalWrite(controlPin[5], LOW);
        digitalWrite(controlPin[6], LOW);
        digitalWrite(controlPin[7], LOW);
        digitalWrite(controlPin[8], LOW);
        digitalWrite(controlPin[9], LOW);
        digitalWrite(controlPin[10], LOW);
        digitalWrite(controlPin[11], LOW);
        }

   if (  ((controlPin[0], HIGH) && (batt1 >= batt_CUTOFF_LOW) or (batt1 < batt_CUTOFF_HIGH))&&
         ((controlPin[1], HIGH) && (batt2 >= batt_CUTOFF_LOW) or (batt2 < batt_CUTOFF_HIGH))&&
         ((controlPin[2], HIGH) && (batt3 >= batt_CUTOFF_LOW) or (batt3 < batt_CUTOFF_HIGH))&&
         ((controlPin[3], HIGH) && (batt4 >= batt_CUTOFF_LOW) or (batt4 < batt_CUTOFF_HIGH))&&
         ((controlPin[4], HIGH) && (batt5 >= batt_CUTOFF_LOW) or (batt5 < batt_CUTOFF_HIGH))&&
         ((controlPin[5], HIGH) && (batt6 >= batt_CUTOFF_LOW) or (batt6 < batt_CUTOFF_HIGH))&&
         ((controlPin[6], HIGH) && (batt7 >= batt_CUTOFF_LOW) or (batt7 < batt_CUTOFF_HIGH))&&
         ((controlPin[7], HIGH) && (batt8 >= batt_CUTOFF_LOW) or (batt8 < batt_CUTOFF_HIGH))&&
         ((controlPin[8], HIGH) && (batt9 >= batt_CUTOFF_LOW) or (batt9 < batt_CUTOFF_HIGH))&&
         ((controlPin[9], HIGH) && (batt10 >= batt_CUTOFF_LOW) or (batt10 < batt_CUTOFF_HIGH))&&
         ((controlPin[10], HIGH) && (batt11 >= batt_CUTOFF_LOW) or (batt11 < batt_CUTOFF_HIGH))&&
         ((controlPin[11], HIGH) && (batt12 >= batt_CUTOFF_LOW) or (batt12 < batt_CUTOFF_HIGH)))
         
         {
          digitalWrite(charge_ON_OFF[0], LOW);
          digitalWrite(charge_ON_OFF[1], LOW);        
          }
}

Hi,
Welcome to the forum.

Can you please post your circuit diagram, include pin names and labels?

Thanks.. Tom... :grinning: :+1: :coffee: :australia:

The code you’ve posted would be a great candidate for structs, arrays, and a state-machine. (tidier, smaller and easier to maintain, expand)

millis() timing would be preferable, but in this ‘static’ application, delay() might work… if you want to add any more functionality later, delay() will probably get in the way.

It’s a relatively simple software project, and a good way to learn about the above - and might give you some ideas for better controls and monitoring.

will do

I’d probably also consider adding a real time clock and store charge related events in the eeprom. That would allow any cycling rules you want to implement to survive a system restart caused maybe by a power failure.