#include
LiquidCrystal_I2C lcd(0x3F, 16, 2);
#define M1 5
#define M2 4
#define M3 3
#define D1 10
#define D2 9
#define D3 8
#define BUZZER 7
#define B1_high A0
#define B2_high A1
#define B3_high A2
#define Button 2
int buttonState = 0;
int printStart = 0;
int interval = 5000; // Measurement Interwal (ms)
float battLow = 2.8; // End of measurement - voltage level
float voltRef = 4.37; // Reference voltage (pin 5V)
int l=0;
boolean finished1 = false;
boolean finished2 = false;
boolean finished3 = false;
float mAh1 = 0;
float mAh2 = 0;
float mAh3 = 0;
int poj1 = 0;
int poj2 = 0;
int poj3 = 0;
float R1 = 4; // Resistor R1 value [Ohm]
float RB1 = 4.1; // Measured B1 circuit resistance [Ohm]
float R2 = 4; // Resistor R1 value [Ohm]
float RB2 = 4.1; // Measured B2 circuit resistance [Ohm]
float R3 = 4; // Resistor R1 value [Ohm]
float RB3 = 4.1; // Measured B3 circuit resistance [Ohm]
float current1 = 0.0;
float current2 = 0.0;
float current3 = 0.0;
float B1start = 0.0;
float B2start = 0.0;
float B3start = 0.0;
float B1V1 = 0.0; // voltage before R1
float B2V1 = 0.0; // voltage before R2
float B3V1 = 0.0; // voltage before R3
float Rw1 = 0;
float Rw2 = 0;
float Rw3 = 0;
float roznica1 = 0;
float roznica2 = 0;
float roznica3 = 0;
float suma1 = 0;
float suma2 = 0;
float suma3 = 0;
float X1 = 2; // voltage divider 1 ratio
float X2 = 2; // voltage divider 2 ratio
float X3 = 2; // voltage divider 3 ratio
int pomiar = 0;
int k;
boolean menu1_end = false;
boolean menu_end = false;
int mode = 0;
unsigned long previousMillis1 = 0;
unsigned long previousMillis2 = 0;
unsigned long previousMillis3 = 0;
unsigned long millisPassed1 = 0;
unsigned long millisPassed2 = 0;
unsigned long millisPassed3 = 0;
void setup() {
lcd.init();
lcd.backlight();
pinMode(M1, OUTPUT);
pinMode(M2, OUTPUT);
pinMode(M3, OUTPUT);
pinMode(D1, OUTPUT);
pinMode(D2, OUTPUT);
pinMode(D3, OUTPUT);
pinMode(BUZZER, OUTPUT);
digitalWrite(M1, LOW);
digitalWrite(M2, LOW);
digitalWrite(M3, LOW);
digitalWrite(D1, LOW);
digitalWrite(D2, LOW);
digitalWrite(D3, LOW);
menu(); // enter the menu
lcd.print("Battery test");
lcd.setCursor(0, 1);
lcd.print("Please wait");
delay(2000);
B1start = X1 * analogRead(B1_high) * voltRef / 1024.0; // B1 voltage - no load applied
B2start = X2 * analogRead(B2_high) * voltRef / 1024.0; // B2 voltage - no load applied
B3start = X3 * analogRead(B3_high) * voltRef / 1024.0; // B3 voltage - no load applied
lcd.clear();
finished1 = false;
finished2 = false;
finished3 = false;
digitalWrite(BUZZER, HIGH);
delay(500);
digitalWrite(BUZZER, LOW);
}
void loop() {
if(mode == 1){
test();
}
if(mode == 2){
discharge();
}
}
////////////////////////////////////////////////////////////////////////////////////////////////
void discharge() {
B1V1 = X1 * analogRead(B1_high) * voltRef / 1024.0; // B1 voltage
B2V1 = X2 * analogRead(B2_high) * voltRef / 1024.0; // B2 voltage
B3V1 = X3 * analogRead(B3_high) * voltRef / 1024.0; // B3 voltage
if ((finished1 == true) && (finished2 == true) && (finished3 == true)) {
if(l < 3){
for (k = 0; k < 3; k++) {
digitalWrite(BUZZER, HIGH);
delay(200);
digitalWrite(BUZZER, LOW);
delay(200);
}
l++;
}
}
if (B1V1 >= battLow && finished1 == false)
{
digitalWrite(M1, HIGH);
digitalWrite(D1, HIGH);
lcd.setCursor(0, 0);
lcd.print("1:");
lcd.print(B1V1);
lcd.print("V");
}
if ((B1V1 < battLow) || (finished1 == true)) // Disconnects load, prints the result
{
digitalWrite(M1, LOW);
finished1 = true;
digitalWrite(D1, LOW);
lcd.setCursor(0, 0);
lcd.print("1:END");
}
if (B2V1 >= battLow && finished2 == false)
{
digitalWrite(M2, HIGH);
digitalWrite(D2, HIGH);
lcd.setCursor(9, 0);
lcd.print("2:");
lcd.print(B2V1);
lcd.print("V");
}
if ((B2V1 < battLow) || (finished2 == true)) // Disconnects load, prints the result
{
digitalWrite(M2, LOW);
finished2 = true;
digitalWrite(D2, LOW);
lcd.setCursor(9, 0);
lcd.print("2:END");
}
if (B3V1 >= battLow && finished3 == false)
{
digitalWrite(M3, HIGH);
digitalWrite(D3, HIGH);
lcd.setCursor(0, 1);
lcd.print("3:");
lcd.print(B3V1);
lcd.print("V");
}
if ((B3V1 < battLow) || (finished3 == true)) // Disconnects load, prints the result
{
digitalWrite(M3, LOW);
finished3 = true;
digitalWrite(D3, LOW);
lcd.setCursor(0, 1);
lcd.print("3:END ");
}
delay(interval/4);
digitalWrite(D1, LOW);
digitalWrite(D2, LOW);
digitalWrite(D3, LOW);
delay(interval/4);
lcd.clear();
}
///////////////////////////////////////////////////////////////////////////////////////////////////////
void test(){
B1V1 = X1 * analogRead(B1_high) * voltRef / 1024.0; // B1 voltage
B2V1 = X2 * analogRead(B2_high) * voltRef / 1024.0; // B2 voltage
B3V1 = X3 * analogRead(B3_high) * voltRef / 1024.0; // B3 voltage
if ((finished1 == true) && (finished2 == true) && (finished3 == true)) {
if(l < 3){
for (k = 0; k < 3; k++) {
digitalWrite(BUZZER, HIGH);
delay(200);
digitalWrite(BUZZER, LOW);
delay(200);
}
l++;
}
}
if (B1V1 >= battLow && finished1 == false)
{
digitalWrite(M1, HIGH);
millisPassed1 = millis() - previousMillis1;
current1 = (B1V1) / R1; // Current calculation
mAh1 = mAh1 + (current1 * 1000.0) * (millisPassed1 / 3600000.0); // Capacity sum
previousMillis1 = millis();
if (pomiar > 0 && pomiar < 5) // 4 x voltage measurement
{
suma1 = suma1 + B1V1;
}
if (pomiar == 6)
{
suma1 = suma1 / 4;
roznica1 = B1start / suma1;
Rw1 = (roznica1 - 1) * RB1; // Internal resistance
}
digitalWrite(D1, HIGH);
lcd.clear();
lcd.home();
lcd.print("U:");
lcd.print(B1V1);
lcd.print("V");
lcd.setCursor(9, 0);
lcd.print("I:");
lcd.print(current1);
lcd.print("A");
lcd.setCursor(0, 1);
poj1 = mAh1;
lcd.print(poj1);
lcd.print("mAh");
if (pomiar > 6)
{
lcd.setCursor(9, 1);
lcd.print("Rw:");
lcd.print(Rw1);
}
pomiar++;
delay(interval);
digitalWrite(D1, LOW);
}
if ((B1V1 < battLow) || (finished1 == true)) // Disconnects load, prints the result
{
digitalWrite(M1, LOW);
finished1 = true;
digitalWrite(D1, HIGH);
lcd.clear();
lcd.home();
lcd.print("1 - Koniec");
lcd.setCursor(0, 1);
poj1 = mAh1;
lcd.print(poj1);
lcd.print("mAh ");
lcd.setCursor(8, 1);
lcd.print("Rw1:");
lcd.print(Rw1);
delay(interval * 2);
digitalWrite(D1, LOW);
}
if (B2V1 >= battLow && finished2 == false)
{
digitalWrite(M2, HIGH);
millisPassed2 = millis() - previousMillis2;
current2 = (B2V1) / R2; // Current calculation
mAh2 = mAh2 + (current2 * 1000.0) * (millisPassed2 / 3600000.0); // Capacity sum
previousMillis2 = millis();
if (pomiar > 0 && pomiar < 5) // 4 x voltage measurement
{
suma2 = suma2 + B2V1;
}
if (pomiar == 6)
{
suma2 = suma2 / 4;
roznica2 = B2start / suma2;
Rw2 = (roznica2 - 1) * RB2; // Internal resistance
}
digitalWrite(D2, HIGH);
lcd.clear();
lcd.home();
lcd.print("U:");
lcd.print(B2V1);
lcd.print("V");
lcd.setCursor(9, 0);
lcd.print("I:");
lcd.print(current2);
lcd.print("A");
lcd.setCursor(0, 1);
poj2 = mAh2;
lcd.print(poj2);
lcd.print("mAh");
if (pomiar > 6)
{
lcd.setCursor(9, 1);
lcd.print("Rw:");
lcd.print(Rw2);
}
delay(interval);
digitalWrite(D2, LOW);
}
if ((B2V1 < battLow) || (finished2 == true)) // Disconnects load, prints the result
{
digitalWrite(M2, LOW);
finished2 = true;
digitalWrite(D2, HIGH);
lcd.clear();
lcd.home();
lcd.print("2 - Koniec");
lcd.setCursor(0, 1);
poj2 = mAh2;
lcd.print(poj2);
lcd.print("mAh ");
lcd.setCursor(8, 1);
lcd.print("Rw2:");
lcd.print(Rw2);
delay(interval * 2);
digitalWrite(D2, LOW);
}
if (B3V1 >= battLow && finished3 == false)
{
digitalWrite(M3, HIGH);
millisPassed3 = millis() - previousMillis3;
current3 = (B3V1) / R3; // Current calculation
mAh3 = mAh3 + (current3 * 1000.0) * (millisPassed3 / 3600000.0); // Capacity sum
previousMillis3 = millis();
if (pomiar > 0 && pomiar < 5) // 4 x voltage measurement
{
suma3 = suma3 + B3V1;
}
if (pomiar == 6)
{
suma3 = suma3 / 4;
roznica3 = B3start / suma3;
Rw3 = (roznica3 - 1) * RB3; // Internal resistance
}
digitalWrite(D3, HIGH);
lcd.clear();
lcd.home();
lcd.print("U:");
lcd.print(B3V1);
lcd.print("V");
lcd.setCursor(9, 0);
lcd.print("I:");
lcd.print(current3);
lcd.print("A");
lcd.setCursor(0, 1);
poj3 = mAh3;
lcd.print(poj3);
lcd.print("mAh");
if (pomiar > 6)
{
lcd.setCursor(9, 1);
lcd.print("Rw:");
lcd.print(Rw3);
}
delay(interval);
digitalWrite(D3, LOW);
}
if ((B3V1 < battLow) || (finished3 == true)) // Disconnects load, prints the result
{
digitalWrite(M3, LOW);
finished3 = true;
digitalWrite(D3, HIGH);
lcd.clear();
lcd.home();
lcd.print("3 - Koniec");
lcd.setCursor(0, 1);
poj3 = mAh3;
lcd.print(poj3);
lcd.print("mAh ");
lcd.setCursor(8, 1);
lcd.print("Rw3:");
lcd.print(Rw3);
delay(interval * 2);
digitalWrite(D3, LOW);
}
}
////////////////////////////////////////////////////////////////////////////////////////////
void menu(){
lcd.clear();
lcd.setCursor(0,0);
lcd.print("SELECT MODE");
lcd.setCursor(0,1);
lcd.print("<--CLICK");
while(menu1_end==false){
while(digitalRead(Button) == LOW){}
delay(800);
if(digitalRead(Button) == HIGH){
menu1_end = true;
lcd.setCursor(0,0);
if(mode == 1){lcd.print(">Mode: CAP TEST");}
if(mode == 2){lcd.print(">Mode: DISCHARGE");}
}
else{
if(mode==2){
mode = 1;
}
else{
mode++;
}
lcd.clear();
lcd.setCursor(0,0);
if(mode == 1){lcd.print("Mode: CAP TEST");}
if(mode == 2){lcd.print("Mode: DISCHARGE");}
}
digitalWrite(D1, HIGH);
delay(100);
digitalWrite(D1, LOW);
}
while(menu_end==false){
while(digitalRead(Button) == LOW){}
delay(800);
if(digitalRead(Button) == HIGH){
menu_end = true;
lcd.setCursor(0,1);
lcd.print(">Low V: "); lcd.print(battLow); lcd.print("V");
}
else{
if(battLow > 3.8){
battLow = 2.9;
}
else{
battLow = battLow+0.1;
}
lcd.setCursor(0,1);
lcd.print("Low V: "); lcd.print(battLow); lcd.print("V");
}
digitalWrite(D2, HIGH);
delay(100);
digitalWrite(D2, LOW);
}
delay(2000);
lcd.clear();
}