Hackster is hosting Hackster Holidays, Ep. 7: Livestream & Giveaway Drawing. Watch previous episodes or stream live on Friday!Stream Hackster Holidays, Ep. 7 on Friday!
Alvaro Morales
Published © GPL3+

Battery capacity tester

Battery tester using an ESP32, micro SD cards and Arduino

IntermediateFull instructions provided1 hour7,174
Battery capacity tester

Things used in this project

Hardware components

ESP32S
Espressif ESP32S
×1
Adafruit INA219 High Side DC Current Sensor Breakout
×1
Gravity I2C OLED-2864 Display
DFRobot Gravity I2C OLED-2864 Display
×1
Adafruit Micro SD SPI or SDIO Card Breakout Board
×1
Grove - Relay
Seeed Studio Grove - Relay
×1
Gravity: Analog LM35 Temperature Sensor For Arduino
DFRobot Gravity: Analog LM35 Temperature Sensor For Arduino
×1
Gravity: Analog LM35 Temperature Sensor For Arduino
DFRobot Gravity: Analog LM35 Temperature Sensor For Arduino
×1
HS50E3 6R F M145
×1
Battery Holder, 18650 x 1
Battery Holder, 18650 x 1
×1
Pushbutton switch 12mm
SparkFun Pushbutton switch 12mm
×1
Resistor 100k ohm
Resistor 100k ohm
×1

Software apps and online services

Arduino IDE
Arduino IDE

Story

Read more

Custom parts and enclosures

Frizzing schematics

Schematics

Connection Diagram

Code

Code

Arduino
/*Conexiones
//SDA 21
//SCL 22

 ** MOSI - pin 23
 ** MISO - pin 19
 ** SCK - pin 18
 ** CS - pin 5 (Pin reset 
*/

//Oled
#include <SPI.h>
#include <Wire.h> //Comunicacin I2C
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#define SCREEN_WIDTH 128 // OLED display ancho, en pixeles
#define SCREEN_HEIGHT 64 // OLED display alto, en pixeles
#define OLED_RESET -1 // para compartir el pin de reset con la ESP32
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);

//INA219
#include <Wire.h> //No sera necesario ya que est declarado una vez
#include <Adafruit_INA219.h>
Adafruit_INA219 ina219;
float shuntvoltage = 0;
float busvoltage = 0;
float current_mA = 0;
float loadvoltage = 0;
float power_mW = 0;
float capacidad = 0;

//Pulsador
const int pulsador = 23;
int estado = 0;

//Timer
 unsigned long timer;
 unsigned long timerOn;

// Tarjeta SD
#include "FS.h"
#include "SD.h"
#include <SPI.h>
#define SD_CS 5 // Pin CS para la tarjeta SD
String dataMessage;
String tiempo;
String bus;
String shunt;
String carga;
String corriente;
String potencia;

//Rel
const int rele = 12;

//LM35
const int analogIn = 35;
int RawValue= 0;
float Voltage = 0;
float tempC = 0;
float media = 0;
float mediaT = 0;
int i;


void setup() {
  Serial.begin(115200);
  while (!Serial) {
      delay(1);}
  digitalWrite(rele, HIGH);   // Se cierra el rel 

//---------Inicializa pantalla OLED---------//
  display.begin(SSD1306_SWITCHCAPVCC, 0x3C); /* Se inicializa la pantalla con la direccin 0x3C */
  display.clearDisplay();  /* Se limpia la pantalla */
  display.setTextSize(1);  /* Tamao del texto */
  display.setTextColor(WHITE);  /* Color del texto, esta pantalla slo permite texto en blanco*/
//-----------------------------------------//


//---------Inicializa sensor INA219---------//  
  uint32_t currentFrequency; 
  // Se Comprueba que el sensor est conectado
  if (! ina219.begin()) {
    Serial.println("Sensor no conectado");
      display.setCursor(10,25);
      display.print("Sensor no conectado");
      display.display();
    while (1) { delay(10); }
  }
  Serial.println("Sensor iniciado");  
//-----------------------------------------//


//---------Iniciamos tarjeta SD y creamos fichero---------//  
  SD.begin(SD_CS);
  if (!SD.begin(SD_CS)) {
    Serial.println("Fallo montando SD");
    return;
  }
  uint8_t cardType = SD.cardType();
  if (cardType == CARD_NONE) {
    Serial.println("No hay tarjeta insertada");
    return;
    display.setCursor(15,25);
    display.print("No hay SD");
    display.display();
  }
  Serial.println("Iniciando tarjeta SD...");
  if (!SD.begin(SD_CS)) {
    Serial.println("ERROR iniciando la tarjeta SD");
    return;    // init failed
    display.setCursor(15,25);
    display.print("ERROR iniciando la SD");
    display.display();
  }


  File file = SD.open("/data.txt"); //Se abre el fichero data.txt
  if (!file) { //Si el fichero no existe se crea y se le aaden los cabeceros
    Serial.println("No existe el fichero");
    Serial.println("Creando fichero...");
    writeFile(SD, "/data.txt", "Tiempo, Bus, Shunt, Carga, Corriente, Potencia, Capacidad, Temeperatura \r\n"); //Cabeceros
//    writeFile(SD, "/data.txt", "Reading ID, Date, Hour, Temperature \r\n");
  }
  else {
    Serial.println("Existe el fichero");
  }
  file.close();
//--------------------------------------------------------//  

//---------Rel---------//  
  pinMode(rele, OUTPUT);  //definir pin como salida
//----------------------//  
  

//---------Iniciamos el programa con el botn---------//  
  pinMode(pulsador, INPUT); //Declaramos el pulsador como entrada

    display.setCursor(15,25);
    display.print("Pulsar bot");display.write(162);display.print("n para        iniciar");
    display.display();

  while(estado != 1){                //Hasta que no se pulsa el botn no se inicia el programa para asegurar
    estado = digitalRead(pulsador);  //que el montaje est preparado
  if(estado == HIGH){
    Serial.println("Pulsador pulsado");
    estado = 1;
    display.clearDisplay();
  } 
    
  }
  digitalWrite(rele, LOW);   // Se cierra el rel 
    delay(1000);
//----------------------------------------------------//


}

void loop() {

//---------Mediciones sensor---------//
  shuntvoltage = ina219.getShuntVoltage_mV();
  busvoltage = ina219.getBusVoltage_V();
  current_mA = ina219.getCurrent_mA();
  power_mW = ina219.getPower_mW();
  loadvoltage = busvoltage + (shuntvoltage / 1000);
  capacidad = capacidad + (current_mA * 5/3600);
  
  Serial.print("Bus Voltaje:   "); Serial.print(busvoltage); Serial.println(" V"); //Nos interesa
  Serial.print("Shunt Voltaje: "); Serial.print(shuntvoltage); Serial.println(" mV");
  Serial.print("Carga Voltaje:  "); Serial.print(loadvoltage); Serial.println(" V");
  Serial.print("Corriente:       "); Serial.print(current_mA); Serial.println(" mA");
  Serial.print("Potencia:         "); Serial.print(power_mW); Serial.println(" mW");
  Serial.print("Tiempo en ejecucin: "); Serial.print(timerOn); Serial.println(" s");
  Serial.print("Capacidad: "); Serial.print(capacidad); Serial.println(" mA");
  Serial.println("");
//-----------------------------------//

//------------LM35------------//
  media = 0;
  mediaT = 0;
   for(i=0; i<10; i++){
  RawValue = analogRead(analogIn);
  media = (RawValue / 2048.0) * 4600;
  mediaT = ((mediaT + media)/10);
 }
  RawValue = analogRead(analogIn);
  Voltage = (RawValue / 2048.0) * 4600; // 5000 to get millivots.
  tempC = Voltage * 0.1;
  Serial.print("\t Temperature in C = ");
  Serial.print(tempC,1);
  Serial.print("\t Media = ");
  Serial.println(mediaT,1);
//----------------------------//


//---------Tiempo en ejecicin---------//
 if(estado == 1){
  timer = millis();
//  timerOn = millis() - timer;
  estado = 2;
 }
   timerOn = (millis() - timer)/1000;

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


//---------Mostrar datos OLED---------//
delay(10);
display.clearDisplay();
//    display.setTextSize(1);
    
display.setCursor(0,0);
    display.print("Temp: "); display.print(mediaT,1); display.print((char)247); display.println("C");
display.setCursor(0,10);
    display.print("Shunt Volt: "); display.print(shuntvoltage); display.println(" mV");
display.setCursor(0,20);
    display.print("Carga Volt: "); display.print(loadvoltage); display.println(" V");
display.setCursor(0,30);
    display.print("Corriente: "); display.print(current_mA); display.println(" mA");
display.setCursor(0,40);
    display.print("Pot: "); display.print(power_mW); display.println(" mW");
display.setCursor(0,50);
    display.print("Tiempo: "); display.print(timerOn); display.print(" s");
display.setCursor(90,50);
    display.print(capacidad);
    display.display();
//------------------------------------//

//---------Cargar datos SD---------//
  tiempo = timerOn;
  bus = busvoltage;
  shunt = shuntvoltage;
  carga = loadvoltage;
  corriente = current_mA;
  potencia = power_mW;
  capacidad;
  mediaT;
  logSDCard();
  
//---------------------------------//

//---------Proteccin bateria mediante rel---------//
while(loadvoltage <= 2.8){

  digitalWrite(rele, HIGH);   // Se abre el rel para proteger la bateria y evitar que se descargue ms
// horas(timerOn);
  int horas = (timerOn / 3600); //Pasamos los segndos a horas, minutos y segundos
int minutos = ((timerOn-horas*3600)/60);
int segundos = timerOn-(horas*3600+minutos*60);

 display.clearDisplay();
 display.setCursor(0,0);
    display.print("Capacidad: ");
 display.setCursor(0,15);
    display.print(capacidad); display.print(" mA");
 display.setCursor(0,30);
    display.print("Tiempo: "); 
 display.setCursor(0,45);
    display.print(horas); display.print(":"); display.print(minutos); display.print(":"); display.print(segundos);
 display.setCursor(55,30);
    display.print("Temperatura:"); 
 display.setCursor(55,45);
    display.print(mediaT); display.print((char)247); display.print("C");
    display.display();
    Serial.print("Capacidad: "); Serial.print(capacidad); Serial.println(" mA");
    Serial.print("Tiempo: "); Serial.print(horas); Serial.print(":"); Serial.print(minutos); Serial.print(":"); Serial.println(segundos);
    Serial.print("Temperatura: "); Serial.print(mediaT); Serial.println(" C");
    delay(100000);
}
//--------------------------------------------------//

  delay(5000);
}



//---------Funciones---------//
void logSDCard() {
  dataMessage = String(tiempo) + "," + String(bus) + "," + String(shunt) + "," + String(carga) + "," + String(corriente) + "," + String(potencia) + "," + String(capacidad) + "," + String(mediaT) +"\r\n";
  Serial.print("Save data: ");
  Serial.println(dataMessage);
  appendFile(SD, "/data.txt", dataMessage.c_str());
}

// Escribir en la tarjeta SD (NO MODIFICAR NADA)
void writeFile(fs::FS &fs, const char * path, const char * message) {
  Serial.printf("Writing file: %s\n", path);

  File file = fs.open(path, FILE_WRITE);
  if (!file) {
    Serial.println("Failed to open file for writing");
    return;
  }
  if (file.print(message)) {
    Serial.println("File written");
  } else {
    Serial.println("Write failed");
  }
  file.close();
}

// Aadir cosas a la tarjeta (NO MODIFICAR NADA)
void appendFile(fs::FS &fs, const char * path, const char * message) {
  Serial.printf("Appending to file: %s\n", path);

  File file = fs.open(path, FILE_APPEND);
  if (!file) {
    Serial.println("Failed to open file for appending");
    return;
  }
  if (file.print(message)) {
    Serial.println("Message appended");
  } else {
    Serial.println("Append failed");
  }
  file.close();
}

//void horas(int tiempo){
//  int horas = (tiempo / 3600);
//int minutos = ((tiempo-horas*3600)/60);
//int segundos = tiempo-(horas*3600+minutos*60);
//    Serial.print(horas); Serial.print(":"); Serial.print(minutos); Serial.print(":"); Serial.println(segundos);
//}
//---------------------------//

Credits

Alvaro Morales
4 projects • 3 followers

Comments