3S Battery Charger with auto shutoff

Note: the following article contains printed circuit boards (PCB) of my own design. I am not an electronics engineer. If you make this, it is your responsibility, I am not liable for anything you do, or any derivations of it. Don't be dumb. 100W of power is a lot. It is 1/8 of a toaster, and some soldering irons run off of less. You wouldn't lick a live incadescent lightbulb, treat this the same way.

As mentioned in the previous article on Sox, I ran into an issue trying to find a power delivery system that would charge a 3S (3 batteries in Series) battery bank. After searching for a long while, I ended up using a Constant Current/Constant Voltage (CC/CV) buck regulator to step my 20V input down to the 12.6V the batteries need, while also choking the input current to 3A. The only issue that remained was trying to get the CC/CV regulator to shut down after the batteries were full. As mentioned earlier, there was nothing available at the time to buy, so I had to make my own.

The image at the top shows the final outcome of that process. What it is is an Arduino nano being powered by a voltage regulator, executing a basic script to read the voltage current sensor on the output of the CC/CV regulator. The script switches on and off a mosfet on the ground wire, cutting power downstream to the CC/CV regulator. Code and images below

All can be downloaded from GitHub

Front of PCB

Back of PCB

PCB Schematic


#include 

Adafruit_INA260 ina260 = Adafruit_INA260();

bool debug = false;
float maxVoltageThreshold = 12520;
float minCurrentThreshold = 50;
int maxIntervalCheck = 300; //in seconds
int numIntervals=maxIntervalCheck+1;

 enum : byte {CHARGING,CHARGED};
auto state = CHARGED;

void setup() {
  Serial.begin(115200);

  pinMode(LED_BUILTIN, OUTPUT);
  pinMode(A2, OUTPUT);

  // Wait until serial port is opened max 500 ms
  int startupDelay = 0;
  int startupDelayMax = 500;
  while (!Serial || startupDelay < startupDelayMax) { 
    delay(10); 
    startupDelay += 10;
  }

  
  
  Serial.println("Adafruit INA260 Test");

  if (!ina260.begin()) {
    Serial.println("Couldn't find INA260 chip");
    while (1);
  }
  Serial.println("Found INA260 chip");
}

void loop() {
  if(state==CHARGING){
    
    if( ina260.readBusVoltage() >= maxVoltageThreshold && ina260.readCurrent() < minCurrentThreshold){
      digitalWrite(A2, LOW);
      digitalWrite(LED_BUILTIN, LOW); 
      Serial.println("off");
      state = CHARGED;
    }

  }

  if(state == CHARGED){

    if(numIntervals>= maxIntervalCheck){
      numIntervals = 0;
      digitalWrite(A2, HIGH);
      delay(2000);
      Serial.println("timeout test on");
      if( ina260.readBusVoltage() >= maxVoltageThreshold*0.95 && ina260.readCurrent() < minCurrentThreshold){
        digitalWrite(A2, LOW);
        digitalWrite(LED_BUILTIN, LOW); 
        Serial.println("timeout test off");
      }
      else{
        Serial.println("timeout test on");
        state = CHARGING;
      }
      
    }
  }

  if(debug){
    Serial.print("Current: ");
    Serial.print(ina260.readCurrent());
    Serial.println(" mA");

    Serial.print("Bus Voltage: ");
    Serial.print(ina260.readBusVoltage());
    Serial.println(" mV");

    Serial.print("Power: ");
    Serial.print(ina260.readPower());
    Serial.println(" mW");

    Serial.println();
  }
  delay(1000);
  numIntervals++;
}

Comments

You need to log in to post comments