Text Fromat Battery - Capacitey - Tester
Text Fromat Battery - Capacitey - Tester
--------------------------------------------------------------
//-------------------------------------------------------Battery Manager and Tester
-----------------------------------------------------------------
#include <SPI.h>
#include <stdlib.h>
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27, 16, 2);
unsigned long previousMillis = 0;
unsigned long millisPassed = 0;
unsigned long BatFull = 0;
float BatVoltQuiescent = 0; // The
battery voltage when there is no load on the battery
float Capacity = 0.0; // The
calculated capacity of the battery, measured wile discharging
float mA=0;
float SetI = 0; // The
setpoint for the discharging current. Remember you can adjust the discharging
current using the 500K trimpot.
float ChargeI = 0;
float CurTP4056 = 0;
float ResTP4056 = 0;
float ratioRI = 0;
float BatLevel = 0; // The
percentage of battery charge/level
float BatVoltCorrected = 0; // The
voltage of the battery, measured based on the arduino internal reference
float A2VoltCorrected = 0;
float VoltTP4056Pin2 = 0;
float Rprog = 0;
float BatRes = 0; // The
internal battery resistance
const float RES = 0.500; // Value of
your resistor. Change it, if you use a different resistor value
#define clk 2
#define dt 3
#define sw 4
#define MOSFET_Discharge 8 // It is an
N-MOSFET, so HIGH is ON and LOW is OFF
#define MOSFET_Charge 12
char screen = 0;
char arrowpos = 0;
char charging = 0;
char discharging = 0;
char storage = 0;
char storagecharge = 0;
char storagedischarge = 0;
char BatVoltQuiescentValue = 0; // Whether
there is a value for "the battery voltage with no load" (BatVoltQuiescent) or not.
1 for yes and 0 for no.
//char nointermediate = 0;
const unsigned char PS_128 = (1 << ADPS2) | (1 << ADPS1) | (1 << ADPS0);
volatile boolean TurnDetected = false;
volatile boolean up = false;
volatile boolean button = false;
byte OhmChar[8] = {
B00000,
B01110,
B10001,
B10001,
B10001,
B01010,
B11011,
B00000
};
byte customChar1[8] = {
0b10000,
0b11000,
0b11100,
0b11110,
0b11110,
0b11100,
0b11000,
0b10000
};
ISR(PCINT2_vect) {
if (digitalRead(sw) == LOW) {
button = true;
}
}
void isr0 () {
TurnDetected = true;
up = (digitalRead(dt));
}
void setup() {
lcd.begin();
lcd.setCursor(0, 0);
pinMode(MOSFET_Discharge, OUTPUT);
pinMode(MOSFET_Charge, OUTPUT);
digitalWrite(MOSFET_Discharge, LOW);
digitalWrite(MOSFET_Charge, LOW);
pinMode(sw, INPUT_PULLUP);
pinMode(clk, INPUT);
pinMode(dt, INPUT);
PCICR |= 0b00000100;
PCMSK2 |= 0b00010000; // turn o PCINT20(D4)
attachInterrupt(0, isr0, RISING);
lcd.createChar(0, customChar1);
lcd.createChar(1, OhmChar);
lcd.clear();
screen0();
lcd.setCursor(0, 0);
lcd.write((uint8_t)0);
}
void loop() {
int in0 = analogRead(A0); //read the A0
pin value
int sensorValue1 = analogRead(A1); //read the A1
pin value
float val0 = in0 * 5.0 / 1024.0;
float supply = readVcc() / 1000.0;
SetI = sensorValue1 * (5.00 / 1024.00) / RES * 1000; // Calculate
the discharge rate of the battery
if (SetI <= 2000){
SetI = SetI;
}
else{
SetI = 2000;
}
BatVoltCorrected = supply / 5 * val0 * 4.28; //In case
you use different voltage dividers, you need to change the number 4.3 accordingly.
millisPassed = millis() - previousMillis;
previousMillis = millis();
//------------------------------------------------------------------- calculates
the charging current
------------------------------------------------------------------------
int in2 =
analogRead(A2); //read the A2
pin value
int in3 =
analogRead(A3); //read the A3
pin value
float val2 = in2 * 5.0 / 1024.0;
float val3 = in3 * 5.0 / 1024.0;
A2VoltCorrected = supply / 5 *
val2; //calculates reading of pin A2
based on internal voltage reference
VoltTP4056Pin2 = supply / 5 * val3;
//calculates reading of pin A3 based on internal voltage reference
//
calculates the Charging current based on numbers from TP4056 datasheet
if (Rprog >= 10000) {
CurTP4056 =130 ;
ResTP4056 =10000 ;
ratioRI = 0.107 ;
}
else if (Rprog < 10000 && Rprog >= 5000){
CurTP4056 = 250 ;
ResTP4056 = 5000 ;
ratioRI = 0.024 ;
}
else if (Rprog < 5000 && Rprog >= 4000){
CurTP4056 = 300 ;
ResTP4056 = 4000 ;
ratioRI = 0.050 ;
}
else if (Rprog < 4000 && Rprog >= 3000){
CurTP4056 = 400 ;
ResTP4056 = 3000 ;
ratioRI = 0.100 ;
}
else if (Rprog < 3000 && Rprog >= 2000){
CurTP4056 = 580 ;
ResTP4056 = 2000 ;
ratioRI = 0.180 ;
}
else if (Rprog < 2000 && Rprog >= 1660){
CurTP4056 = 690 ;
ResTP4056 = 1660 ;
ratioRI = 0.324 ;
}
else if (Rprog < 1660 && Rprog >= 1500){
CurTP4056 = 780 ;
ResTP4056 = 1500 ;
ratioRI = 0.563 ;
}
else if (Rprog < 1500 && Rprog >= 1330){
CurTP4056 = 900 ;
ResTP4056 = 1330 ;
ratioRI = 0.706 ;
}
else if (Rprog >= 1220){
CurTP4056 = 995 ;
ResTP4056 = 1220 ;
ratioRI = 0.864 ;
}
lcd.setCursor(0,1);
lcd.print("V:");
lcd.print(BatVoltCorrected);
lcd.print("V ");
lcd.setCursor(8,1);
lcd.print("I:");
lcd.print(ChargeI,0);
lcd.print("mA ");
digitalWrite(MOSFET_Charge, HIGH);
//delay(9000);
//digitalWrite(MOSFET_Charge, HIGH);
delay(1000);
}
else if (BatVoltCorrected < 4.35 ) {
lcd.setCursor(0,0);
lcd.print("Battery Full");
lcd.setCursor(0,1);
lcd.print("V:");
lcd.print(BatVoltCorrected);
lcd.print("V ");
lcd.setCursor(8,1);
lcd.print("I:");
lcd.print(ChargeI,0);
lcd.print("mA ");
digitalWrite(MOSFET_Charge, LOW);
delay(500);
}
}
//-------------------------------------------------------------------------------
---------Storage
mode-------------------------------------------------------------------------------
----------
// You need to adjust your voltages according to your batteries, for 3400mAh
batteries storage voltage (50% capacity) is 3.6-3.7V, for batteries below 2600mAh
it should be higher.
// For more info visit this:https://lygte-info.dk/info/BatteryChargePercent
%20UK.html
else if (screen == 3) {
delay(100);
if (BatVoltCorrected <= 1.5 ) {
lcd.setCursor(0,0);
lcd.print("No battery ");
lcd.setCursor(0,1);
lcd.print("V:");
lcd.print(BatVoltCorrected);
lcd.print("V ");
digitalWrite(MOSFET_Discharge, LOW);
digitalWrite(MOSFET_Charge, LOW);
charging = 0;
discharging = 0;
storage = 0;
storagecharge = 0;
storagedischarge = 0;
}
else if (BatVoltCorrected > 3.75 && charging == 0) {
// Checks if the "quiescent voltage" of the battery is above 3.7V and Starts the
discharge.
lcd.setCursor(0,0);
lcd.print("Discharging ");
lcd.setCursor(0,1);
lcd.setCursor(0,1);
lcd.print("V:");
lcd.print(BatVoltCorrected);
lcd.print("V ");
lcd.setCursor(9,1);
lcd.print("I:");
lcd.print(SetI,0);
lcd.print("mA ");
digitalWrite(MOSFET_Charge, LOW);
delay(100);
discharging = 1;
digitalWrite(MOSFET_Discharge, HIGH);
delay(5000);
digitalWrite(MOSFET_Discharge, LOW);
}
else if (storagedischarge == 1 && discharging == 1){
// Intermediate step before stopping the discharge
lcd.setCursor(0,0);
lcd.print("RDY for storage");
lcd.setCursor(0,1);
lcd.print("V:");
lcd.print(BatVoltCorrected);
lcd.print("V ");
discharging = 1;
digitalWrite(MOSFET_Charge, LOW);
delay(100);
digitalWrite(MOSFET_Discharge, HIGH);
delay(10000);
digitalWrite(MOSFET_Discharge, LOW);
}
else if (BatVoltCorrected >= 1.5 && BatVoltCorrected < 3.6) {
// Checks if the "quiescent voltage" of the battery is between 1.5V and 3.6V
if (discharging == 1 && BatVoltCorrected < 3.0)
{ // Stops discharging if the "discharge voltage" of the
battery is below 3.0V
lcd.setCursor(0,1);
lcd.print("V:");
lcd.print(BatVoltCorrected);
lcd.print("V ");
lcd.setCursor(9,1);
lcd.print("I:");
lcd.print(SetI,0);
lcd.print("mA ");
digitalWrite(MOSFET_Discharge, LOW);
}
if (discharging == 1 && BatVoltCorrected > 2){
// Prevents from charging (continues discharging) even if the "quiescent voltage"
is below 3.6V
lcd.setCursor(0,1);
lcd.print("V:");
lcd.print(BatVoltCorrected);
lcd.print("V ");
lcd.setCursor(9,1);
lcd.print("I:");
lcd.print(SetI,0);
lcd.print("mA ");
}
else if (discharging == 0 && BatVoltCorrected < 3.6){
// Starts to charge the battery
lcd.setCursor(0,0);
lcd.print("Charging... ");
lcd.setCursor(0,1);
lcd.print("V:");
lcd.print(BatVoltCorrected);
lcd.print("V ");
digitalWrite(MOSFET_Discharge, LOW);
delay(100);
digitalWrite(MOSFET_Charge, HIGH);
charging = 1;
delay(1000);
}
else {
// used for debugging
lcd.setCursor(0,0);
lcd.print("error? ");
}
}
//--------------------------------------------------------------------------------
TURN
-----------------------------------------------------------------------------------
--------------------
if (TurnDetected) {
delay(200);
switch (screen) {
case 0:
switch (arrowpos) {
case 0:
if (!up) {
screen0();
lcd.setCursor(0, 1);
lcd.write((uint8_t)0);
arrowpos = 1;
}
else {
screen0();
lcd.setCursor(8, 1);
lcd.write((uint8_t)0);
arrowpos = 2;
}
break;
case 1:
if (up) {
screen0();
lcd.setCursor(0, 0);
lcd.write((uint8_t)0);
arrowpos = 0;
}
else {
screen0();
lcd.setCursor(8, 1);
lcd.write((uint8_t)0);
arrowpos = 2;
}
break;
case 2:
if (up) {
screen0();
lcd.setCursor(0, 1);
lcd.write((uint8_t)0);
arrowpos = 1;
}
else {
screen0();
lcd.setCursor(0, 0);
lcd.write((uint8_t)0);
arrowpos = 0;
}
break;
}
break;
}
TurnDetected = false;
}
//---------------------------------------------------------------------------------
----------- BUTTON PRESS
-----------------------------------------------------------------------------------
---------
if (button) {
delay(200);
switch (screen) {
case 0:
if (arrowpos == 0) {
screen = 1;
screen1();
}
else if (arrowpos == 1){
screen = 2;
screen2();
}
else {
screen = 3;
screen3();
}
break;
case 1:
screen = 0;
screen0();
lcd.setCursor(0, 0);
lcd.write((uint8_t)0);
break;
case 2:
screen = 0;
screen0();
lcd.setCursor(0, 0);
lcd.write((uint8_t)0);
break;
case 3:
screen = 0;
screen0();
lcd.setCursor(0, 0);
lcd.write((uint8_t)0);
break;
}
arrowpos = 0;
button = false;
}
}
//---------------------------------------------------------------------------------
--------------------
SCREENS----------------------------------------------------------------------------
---------
void screen0() {
lcd.clear();
lcd.setCursor(1, 0);
lcd.print("Capacity test");
lcd.setCursor(1, 1);
lcd.print("Charge");
lcd.setCursor(9, 1);
lcd.print("Store");
digitalWrite(MOSFET_Discharge, LOW);
digitalWrite(MOSFET_Charge, LOW);
charging = 0;
discharging = 0;
storage = 0;
storagecharge = 0;
storagedischarge = 0;
}
void screen1() {
lcd.clear();
}
void screen2() {
lcd.clear();
}
void screen3() {
lcd.clear();
}
//-------------------------------------------------------------------voltage based
on internal reference-------------------------------------------------------------
long readVcc() {
long result;
// Read 1.1V reference against AVcc
#if defined(__AVR_ATmega32U4__) || defined(__AVR_ATmega1280__) ||
defined(__AVR_ATmega2560__)
ADMUX = _BV(REFS0) | _BV(MUX4) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1);
#elif defined (__AVR_ATtiny24__) || defined(__AVR_ATtiny44__) ||
defined(__AVR_ATtiny84__)
ADMUX = _BV(MUX5) | _BV(MUX0);
#elif defined (__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) ||
defined(__AVR_ATtiny85__)
ADMUX = _BV(MUX3) | _BV(MUX2);
#else
ADMUX = _BV(REFS0) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1);
#endif
delay(2); // Wait for Vref to
settle
ADCSRA |= _BV(ADSC); // Convert
while (bit_is_set(ADCSRA, ADSC));
result = ADCL;
result |= ADCH << 8;
result = 1126400L / result; // Calculate Vcc (in
mV); 1126400 = 1.1*1024*1000
return result;
}
//void buz()
// {
// digitalWrite(9, HIGH);
// delay(100);
// digitalWrite(9, LOW);
// delay(10);
//}