#include <LiquidCrystal_I2C.h>
#include<JC_Button.h>
//equipment
LiquidCrystal_I2C lcd(0x27, 20, 4);
Button UP_Button(52, 100, false, true);
Button DOWN_Button(50, 100, false, true);
Button MODE_Button(51, 100, false, false);
Button VALID_Button(53, 100, false, false);
//choice option
String STATE_FULL[] = {"STB", "DSG", "CHG", "STR", "PSE", "STP", "RST"};
String STATE_SHORT[] = {"S", "D", "C", "T", "P", "X", "R", "O", "F"};
int state_index = 1;
int CURRENT_SELECTED[] = {50, 100, 200, 300, 400, 500, 600, 700, 800, 900, 1000};
int current_selected_index = 5;
//bat values
String BAT_STATE[] = {"S", "S", "S", "S"};
String BAT_ACTION_STATE[] = {"O", "O", "O", "O"};
String ERROR_MSG[] = {"", "", "", ""};
float STARTING_VOLTAGE[] = {0, 0, 0, 0};
float VOLTAGE[] = {0, 0, 0, 0};
int CURRENT[] = {0, 0, 0, 0};
float CAPACITY[] = {0, 0, 0, 0};
int IRES[] = {0, 0, 0, 0};
const int RES_LOAD[] = {1, 1, 1, 1};
unsigned long STARTED_TIME[] = {0, 0, 0, 0};
unsigned long TIME[] = {0, 0, 0, 0};
//time control
unsigned long previousMillis[] = {0, 0, 0, 0};
unsigned long millisPassed[] = {0, 0, 0, 0};
//bat pinout
const int reading_pin[] = {A0, A2, A4, A6};
const int charging_current_pin[] = {A1, A3, A5, A7};
const int discharge_control_pin[] = {8, 9, 10, 11};
const int charge_control_pin[] = {22, 24, 26, 28};
//state algo
int screenState = 0;
int precedentScreenState = 0;
int batteryToSet = 1;
int STATE = 0;
int discharge_state[] = {0, 0, 0, 0};
int charge_state[] = {0, 0, 0, 0};
int storage_state[] = {0, 0, 0, 0};
//calcul
float vccCorrected = 0;
float storageVoltage = 3.80;
//Special caracter
byte OhmChar[8] = {
B00000,
B01110,
B10001,
B10001,
B10001,
B01010,
B11011,
B00000
};
byte flecheChar1[8] = {
0b10000,
0b11000,
0b11100,
0b11110,
0b11110,
0b11100,
0b11000,
0b10000
};
byte losange[8] = {
0b00100,
0b00100,
0b01110,
0b11111,
0b01110,
0b00100,
0b00100,
0b00000
};
void setup() {
// put your setup code here, to run once:
Serial.begin(9600);
lcd.begin(20, 4);
UP_Button.begin();
DOWN_Button.begin();
MODE_Button.begin();
VALID_Button.begin();
//pinMode
for (int i = 0; i < 4; i++) {
pinMode(reading_pin[i], INPUT);
pinMode(charging_current_pin[i], INPUT);
pinMode(discharge_control_pin[i], OUTPUT);
pinMode(charge_control_pin[i], OUTPUT);
digitalWrite(charge_control_pin[i], HIGH);
analogWrite(discharge_control_pin[i], 0);
}
// lecture de la tension d'alimentation 100 fois pour une bonne estimation et un emeilleure précision
float vccTemp = 0;
for (int i = 0; i < 100; i++) {
vccTemp = vccTemp + readVcc() / 1000.0;
}
vccCorrected = vccTemp / 100.0 ;
// Serial.println(vccCorrected);
// creation des caractère scpeciaux
lcd.createChar(0, flecheChar1);
lcd.createChar(1, OhmChar);
lcd.createChar(2, losange);
lcd.clear();
lcd.setCursor(0, 0);
screen0();
delay(100);
lcd.clear();
}
void loop() {
//ecran all bat
if (screenState == 0) {
screenAllBat();
}
//ecran 2 bat
if (screenState == 1) {
screenDetail(batteryToSet, 1);
screenDetail(batteryToSet + (1 - 4 * (batteryToSet / 4)), 2);
}
//ecran setting bat
if (screenState == 2) {
option(batteryToSet);
}
checkButton();
checkBatteries();
}
void checkBatteries() {
for (int i = 0; i < 4; i++) {
//always
VOLTAGE[i] = readVoltage(i);
//decharge
if (BAT_STATE[i] == STATE_SHORT[1] && BAT_ACTION_STATE[i] == STATE_SHORT[7] ) {
switch (discharge_state[i]) {
//check tension et lancement pour IR si ok, enregistrement temps de depart ettension de depart
case 1:
if (readVoltage(i) >= 4.15) {
STARTING_VOLTAGE[i] = readVoltage(i);
analogWrite(discharge_control_pin[i], CURRENT[i]); ///////////////////need to be corrected for real current
previousMillis[i] = millis();
discharge_state [i] = 2;
Serial.println("check one done");
} else {
discharge_state [i] = 10;
BAT_ACTION_STATE[i] = STATE_SHORT[8];
ERROR_MSG[i] = "Need CHG";
Serial.println("check one KO");
Serial.println(BAT_ACTION_STATE[i]);
}
break;
//check IRES if ok go else fail, resume time
case 2:
millisPassed[i] = millis();
if (millisPassed[i] - previousMillis[i] >= 3000) {
float vTemp = readVoltage(i);
analogWrite(discharge_control_pin[i], 0);
IRES[i] = (float(RES_LOAD[i]) * ((STARTING_VOLTAGE[i] / vTemp) - 1.0)) * 1000.0;
if (IRES[i] < 300) {
discharge_state [i] = 3;
Serial.println("ri done");
Serial.println(IRES[i]);
} else {
discharge_state [i] = 10;
BAT_ACTION_STATE[i] = STATE_SHORT[8];
TIME[i] = millis();
ERROR_MSG[i] = "IR TO H";
Serial.println("ri KO");
Serial.println(IRES[i]);
}
STARTED_TIME[i] = millis();
previousMillis[i] = millis();
millisPassed[i] = millis();
}
break;
// check voltage after few sec if ok go else fail
case 3:
millisPassed[i] = millis();
if (millisPassed[i] - previousMillis[i] >= 10000 && (readVoltage(i) >= 4.10) ) {
discharge_state [i] = 4;
analogWrite(discharge_control_pin[i], CURRENT[i]); ///////////////////need to be corrected for real current
STARTED_TIME[i] = millis();
previousMillis[i] = millis();
millisPassed[i] = millis();
Serial.println("case 3 ok");
} else if (millisPassed[i] - previousMillis[i] >= 10000 && readVoltage(i) < 4.10) {
discharge_state [i] = 10;
BAT_ACTION_STATE[i] = STATE_SHORT[8];
ERROR_MSG[i] = "V bat KO";
Serial.println("case 3 KO");
}
break;
// calculate capacity
case 4:
millisPassed[i] = millis();
CAPACITY[i] = CAPACITY[i] + (float(CURRENT[i]) * ((float(millisPassed[i] - previousMillis[i])) / 3600000.0));
previousMillis[i] = millis();
if ((readVoltage(i) <= 2.75) ) {
discharge_state [i] = 5;
BAT_ACTION_STATE[i] = STATE_SHORT[5];
ERROR_MSG[i] = "FINI";
TIME[i] = millis();
previousMillis[i] = millis();
millisPassed[i] = millis();
Serial.println("case 4 ok");
}
break;
case 10:
// Serial.println("Fail");
break;
default:
// Serial.println("defautl");
break;
}
}
//reset des valeurs de dechargement ou chargement suite au passage statu reset
if ((BAT_STATE[i] == STATE_SHORT[1] || BAT_STATE[i] == STATE_SHORT[2]) && BAT_ACTION_STATE[i] == STATE_SHORT[6]) {
BAT_STATE[i] = STATE_SHORT[0];
BAT_ACTION_STATE[i] = STATE_SHORT[7];
discharge_state [i] = 0;
charge_state [i] = 0;
digitalWrite(charge_control_pin[i], HIGH);
analogWrite(discharge_control_pin[i], 0);
ERROR_MSG[i] = "";
STARTING_VOLTAGE[i] = 0;
CAPACITY[i] = 0;
CURRENT[i] = 0;
IRES[i] = 0;
STARTED_TIME[i] = 0;
TIME[i] = 0;
previousMillis[i] = 0;
millisPassed[i] = 0;
}
if (BAT_STATE[i] == STATE_SHORT[2] && BAT_ACTION_STATE[i] == STATE_SHORT[7]) {
switch (charge_state[i]) {
//check tension et lancement pour IR si ok, enregistrement temps de depart ettension de depart
case 1:
if (readVoltage(i) <= 4.15) {
STARTING_VOLTAGE[i] = readVoltage(i);
digitalWrite(charge_control_pin[i], LOW); ///////////////////need to be corrected for real current
previousMillis[i] = millis();
charge_state [i] = 2;
Serial.println("check charge one done");
} else {
charge_state [i] = 10;
BAT_ACTION_STATE[i] = STATE_SHORT[6];
ERROR_MSG[i] = "CHARGE OK";
Serial.println("check charge one KO");
}
break;
// check voltage, calculate capacity and stop charging when done
case 2:
millisPassed[i] = millis();
CURRENT[i] = readChargingCurrent(i);
CAPACITY[i] = CAPACITY[i] + (CURRENT[i] * ((float(millisPassed[i] - previousMillis[i])) / 3600000.0));
previousMillis[i] = millis();
if ((readVoltage(i) >= 4.15 && readChargingCurrent(i) < 50) ) {
charge_state [i] = 3;
digitalWrite(charge_control_pin[i], HIGH);
BAT_ACTION_STATE[i] = STATE_SHORT[5];
ERROR_MSG[i] = "FINI";
TIME[i] = millis();
previousMillis[i] = millis();
millisPassed[i] = millis();
Serial.println("case 4 ok");
}
break;
case 10:
// Serial.println("Fail");
break;
default:
// Serial.println("defautl");
break;
}
}
if (BAT_STATE[i] == STATE_SHORT[3] && BAT_ACTION_STATE[i] == STATE_SHORT[7]) {
switch (storage_state[i]) {
//check tension et lancement pour décharge ou charge suivant tension ref
case 1:
//go to charge mode
if (readVoltage(i) <= storageVoltage + 0.02 && readVoltage(i) >= storageVoltage - 0.02) {
storage_state [i] = 5;
analogWrite(discharge_control_pin[i], 0);
BAT_ACTION_STATE[i] = STATE_SHORT[5];
ERROR_MSG[i] = "ST IS OK";
TIME[i] = millis();
previousMillis[i] = millis();
millisPassed[i] = millis();
Serial.println("case storage is ok");
} else if (readVoltage(i) <= storageVoltage) {
STARTING_VOLTAGE[i] = readVoltage(i);
digitalWrite(charge_control_pin[i], LOW);
previousMillis[i] = millis();
storage_state [i] = 2;
ERROR_MSG[i] = "ST CHG";
Serial.println("check storage one to charge done");
} else if (readVoltage(i) >= storageVoltage + 0.2) {
CURRENT[i] = CURRENT_SELECTED[5];
analogWrite(discharge_control_pin[i], CURRENT[i]);
previousMillis[i] = millis();
storage_state [i] = 3;
ERROR_MSG[i] = "ST H DSG";
Serial.println("check storage one to high discharge done");
} else if (readVoltage(i) >= storageVoltage && readVoltage(i) <= storageVoltage + 0.2) {
CURRENT[i] = CURRENT_SELECTED[0];
analogWrite(discharge_control_pin[i], CURRENT[i]);
previousMillis[i] = millis();
storage_state [i] = 4;
ERROR_MSG[i] = "ST L DSG";
Serial.println("check storage one to low discharge done");
}
break;
//charge mode of storage
case 2:
CURRENT[i] = readChargingCurrent(i);
if ((readVoltage(i) >= storageVoltage + 0.3) ) {
storage_state [i] = 8;
digitalWrite(charge_control_pin[i], HIGH);
ERROR_MSG[i] = "CHG OK";
TIME[i] = millis();
previousMillis[i] = millis();
millisPassed[i] = millis();
Serial.println("case storage charge ok");
}
break;
// high discharge current to come close to value
case 3:
if (readVoltage(i) <= storageVoltage + 0.15) {
storage_state [i] = 8;
analogWrite(discharge_control_pin[i], 0);
ERROR_MSG[i] = "H DSG OK";
TIME[i] = millis();
previousMillis[i] = millis();
millisPassed[i] = millis();
Serial.println("case storage H discharge ok");
}
break;
// low discharge current to come next to value
case 4:
if (readVoltage(i) <= storageVoltage + 0.02 && readVoltage(i) >= storageVoltage - 0.02) {
storage_state [i] = 8;
analogWrite(discharge_control_pin[i], 0);
ERROR_MSG[i] = "L DSG OK";
TIME[i] = millis();
previousMillis[i] = millis();
millisPassed[i] = millis();
Serial.println("case storage H discharge ok");
}
break;
case 8:
millisPassed[i] = millis();
if (millisPassed[i] - previousMillis[i] >= 3000) {
storage_state [i] = 1;
previousMillis[i] = millis();
millisPassed[i] = millis();
}
break;
case 10:
// Serial.println("Fail");
break;
default:
// Serial.println("defautl");
break;
}
}
//si en décharge ou charge et ok alors décompte du temps
if ((BAT_STATE[i] == STATE_SHORT[1] || BAT_STATE[i] == STATE_SHORT[2] || BAT_STATE[i] == STATE_SHORT[3]) && BAT_ACTION_STATE[i] == STATE_SHORT[7]) {
TIME[i] = millis();
// Serial.println(millis());
}
}
}
float readVoltage(int batN) {
float vTemp = 0;
for (int i = 0; i < 100; i++) {
vTemp = vTemp + analogRead(reading_pin[batN]);
}
vTemp = vTemp / 100.0 ;
return vccCorrected * vTemp / 1023.0;
}
float readChargingCurrent(int batN) {
float vTemp = 0;
for (int i = 0; i < 100; i++) {
vTemp = vTemp + analogRead(charging_current_pin[batN]);
}
vTemp = vTemp / 100.0 ;
return 1000.0 * 0.97 * vccCorrected * vTemp / 1023.0;
}
//STATE_SHORT {"STB", "DSG", "CHG", "STR," "PSE", "STP","RST"};
// STATE_SHORT[]={"S", "D", "C", "T", "P", "X", "R", "O", "F"};
// 0 1 2 3 4 5 6 7 8
//BAT_ACTION_STATE
// check button pressed and do action depend on state
void checkButton() {
UP_Button.read();
DOWN_Button.read();
MODE_Button.read();
VALID_Button.read();
if (screenState == 0) {
if (MODE_Button.wasReleased() ) {
screenState = 1;
precedentScreenState = 0;
lcd.clear();
}
if (UP_Button.wasReleased() ) {
batteryToSet += 1;
if (batteryToSet > 4) {
batteryToSet = 1;
}
}
if (DOWN_Button.wasReleased() ) {
batteryToSet -= 1;
if (batteryToSet < 1) {
batteryToSet = 4;
}
}
if (VALID_Button.wasReleased() ) {
screenState = 2;
precedentScreenState = 0;
lcd.clear();
}
}
else if (screenState == 1) {
if (MODE_Button.wasReleased() ) {
screenState = 0;
precedentScreenState = 1;
lcd.clear();
}
if (UP_Button.wasReleased() ) {
batteryToSet += 1;
if (batteryToSet > 4) {
batteryToSet = 1;
}
lcd.clear();
}
if (DOWN_Button.wasReleased() ) {
batteryToSet -= 1;
if (batteryToSet < 1) {
batteryToSet = 4;
}
lcd.clear();
}
if (VALID_Button.wasReleased() ) {
screenState = 2;
precedentScreenState = 1;
lcd.clear();
}
}
else if (screenState == 2) {
if (MODE_Button.wasReleased() ) {
state_index += 1;
if (state_index > 6) {
state_index = 1;
}
}
if (UP_Button.wasReleased() ) {
current_selected_index += 1;
if (current_selected_index > 9) {
current_selected_index = 0;
}
}
if (DOWN_Button.wasReleased() ) {
current_selected_index -= 1;
if (current_selected_index < 0) {
current_selected_index = 9;
}
}
if (VALID_Button.wasReleased() ) {
// si en STBY
if (BAT_STATE[batteryToSet - 1] == STATE_SHORT[0]) {
if (STATE_SHORT[state_index] == STATE_SHORT[1]) {
lcd.setCursor(11, 3);
lcd.print(" DSG ");
STARTED_TIME[batteryToSet - 1] = millis();
TIME[batteryToSet - 1] = millis();
discharge_state[batteryToSet - 1] = 1;
BAT_STATE[batteryToSet - 1] = STATE_SHORT[1];
CURRENT[batteryToSet - 1] = CURRENT_SELECTED[current_selected_index];
current_selected_index = 5;
optionScrenReturnt();
} else if (STATE_SHORT[state_index] == STATE_SHORT[2]) {
lcd.setCursor(11, 3);
lcd.print(" CHG ");
STARTED_TIME[batteryToSet - 1] = millis();
TIME[batteryToSet - 1] = millis();
charge_state[batteryToSet - 1] = 1;
BAT_STATE[batteryToSet - 1] = STATE_SHORT[2];
optionScrenReturnt();
} else {
lcd.setCursor(11, 3);
lcd.print("Invalid");
}
}
//Si en decharge
else if (BAT_STATE[batteryToSet - 1] == STATE_SHORT[1]) {
checkACTION_STATE (batteryToSet);
}
//Si en charge
else if (BAT_STATE[batteryToSet - 1] == STATE_SHORT[2]) {
checkACTION_STATE (batteryToSet);
}
// si en pause alors resume ou stop
else if (BAT_ACTION_STATE[batteryToSet - 1] == STATE_SHORT[4]) {
checkACTION_STATE (batteryToSet);
}
}
}
}
void checkACTION_STATE (int batteryToSet) {
//si tout est ok alors soit pause soit stop
if (BAT_ACTION_STATE[batteryToSet - 1] == STATE_SHORT[7]) {
if (STATE_SHORT[state_index] == STATE_SHORT[4]) {
lcd.setCursor(11, 3);
lcd.print(" PSE ");
BAT_ACTION_STATE[batteryToSet - 1] = STATE_SHORT[4];
TIME[batteryToSet - 1] = millis();
optionScrenReturnt();
} else if (STATE_SHORT[state_index] == STATE_SHORT[5]) {
lcd.setCursor(11, 3);
lcd.print(" STP ");
BAT_ACTION_STATE[batteryToSet - 1] = STATE_SHORT[5];
TIME[batteryToSet - 1] = millis();
optionScrenReturnt();
} else {
lcd.setCursor(11, 3);
lcd.print("Invalid");
}
}
// si en pause alors resume ou stop
else if (BAT_ACTION_STATE[batteryToSet - 1] == STATE_SHORT[4]) {
if (STATE_SHORT[state_index] == STATE_SHORT[4]) {
lcd.setCursor(11, 3);
lcd.print(" RSM ");
BAT_ACTION_STATE[batteryToSet - 1] = STATE_SHORT[7];
STARTED_TIME[batteryToSet - 1] += millis() - TIME[batteryToSet - 1];
previousMillis[batteryToSet - 1] += millis() - millisPassed[batteryToSet - 1];
optionScrenReturnt();
} else if (STATE_SHORT[state_index] == STATE_SHORT[5]) {
lcd.setCursor(11, 3);
lcd.print(" STP ");
BAT_ACTION_STATE[batteryToSet - 1] = STATE_SHORT[5];
optionScrenReturnt();
} else {
lcd.setCursor(11, 3);
lcd.print("Invalid");
}
}
//Si en stop
else if (BAT_ACTION_STATE[batteryToSet - 1] == STATE_SHORT[5]) {
if (STATE_SHORT[state_index] == STATE_SHORT[6]) {
lcd.setCursor(11, 3);
lcd.print(" RST ");
BAT_ACTION_STATE[batteryToSet - 1] = STATE_SHORT[6];
optionScrenReturnt();
} else {
lcd.setCursor(11, 3);
lcd.print("Invalid");
}
}
//Si en fail
else if (BAT_ACTION_STATE[batteryToSet - 1] == STATE_SHORT[8]) {
if (STATE_SHORT[state_index] == STATE_SHORT[6]) {
lcd.setCursor(11, 3);
lcd.print(" RST ");
BAT_ACTION_STATE[batteryToSet - 1] = STATE_SHORT[6];
optionScrenReturnt();
} else {
lcd.setCursor(11, 3);
lcd.print("Invalid");
}
}
}
void optionScrenReturnt() {
delay(500);
screenState = precedentScreenState;
precedentScreenState = 2;
lcd.clear();
}
//ecran principal de bievenue
void screen0() {
lcd.clear();
lcd.setCursor(0, 0);
lcd.print(" Bienvenue");
lcd.setCursor(0, 1);
lcd.print(" Battery Tester");
lcd.setCursor(0, 2);
lcd.print(" Charger");
lcd.setCursor(0, 3);
lcd.print(" Storage");
}
//ecran ou tout est affiche moins de details
void screenAllBat() {
singleForAllScreen(1);
singleForAllScreen(2);
singleForAllScreen(3);
singleForAllScreen(4);
}
void singleForAllScreen(int batNumber) {
int positionX = 10 - 10 * (batNumber % 2);
int positionY = 2 * (batNumber / 3);
lcd.setCursor(positionX, positionY);
if (batteryToSet == batNumber) {
lcd.print(char(2));
} else {
lcd.print(" ");
}
lcd.print(batNumber);
lcd.print(BAT_STATE[batNumber - 1]);
lcd.print(BAT_ACTION_STATE[batNumber - 1]);
lcd.print(" ");
if (((TIME[batNumber - 1] - STARTED_TIME[batNumber - 1])) / 3600000 > 0) {
//H
if (((TIME[batNumber - 1] - STARTED_TIME[batNumber - 1])) / 3600000 < 10) {
lcd.print("0");
}
lcd.print((TIME[batNumber - 1] - STARTED_TIME[batNumber - 1]) / 3600000);
//M
lcd.print(":");
if (((TIME[batNumber - 1] - STARTED_TIME[batNumber - 1]) % 3600000) / 60000 < 10) {
lcd.print("0");
}
lcd.print(((TIME[batNumber - 1] - STARTED_TIME[batNumber - 1]) % 3600000) / 60000);
} else {
//M
if (((TIME[batNumber - 1] - STARTED_TIME[batNumber - 1]) % 3600000) / 60000 < 10) {
lcd.print("0");
}
lcd.print(((TIME[batNumber - 1] - STARTED_TIME[batNumber - 1]) % 3600000) / 60000);
//S
lcd.print(":");
if (((TIME[batNumber - 1] - STARTED_TIME[batNumber - 1]) % 60000) / 1000 < 10) {
lcd.print("0");
}
lcd.print(((TIME[batNumber - 1] - STARTED_TIME[batNumber - 1]) % 60000) / 1000);
}
lcd.setCursor(positionX, positionY + 1);
lcd.print(VOLTAGE[batNumber - 1], 1);
lcd.print("V ");
lcd.print(int(CAPACITY[batNumber - 1]));
// lcd.print("C");
}
void option(int batNumber) {
//battery information
lcd.setCursor(0, 0);
lcd.print(batNumber);
lcd.print(BAT_STATE[batNumber - 1]);
lcd.print(BAT_ACTION_STATE[batNumber - 1]);
lcd.print(" ");
lcd.print(int(CAPACITY[batNumber - 1]));
lcd.print("C");
lcd.setCursor(0, 1);
//H
if ((TIME[batNumber - 1] - STARTED_TIME[batNumber - 1]) / 3600000 < 10) {
lcd.print("0");
}
lcd.print((TIME[batNumber - 1] - STARTED_TIME[batNumber - 1]) / 3600000);
//M
lcd.print(":");
if (((TIME[batNumber - 1] - STARTED_TIME[batNumber - 1]) % 3600000) / 60000 < 10) {
lcd.print("0");
}
lcd.print(((TIME[batNumber - 1] - STARTED_TIME[batNumber - 1]) % 3600000) / 60000);
//S
lcd.print(":");
if (((TIME[batNumber - 1] - STARTED_TIME[batNumber - 1]) % 60000) / 1000 < 10) {
lcd.print("0");
}
lcd.print(((TIME[batNumber - 1] - STARTED_TIME[batNumber - 1]) % 60000) / 1000);
lcd.setCursor(0, 2);
lcd.print(VOLTAGE[batNumber - 1], 2);
lcd.print("V R");
lcd.setCursor(0, 3);
lcd.print(CURRENT[batNumber - 1]);
lcd.print("A");
lcd.setCursor(0 + 6, 3);
lcd.print(IRES[batNumber - 1]);
//option choice
lcd.setCursor(10, 0);
lcd.print("State:");
lcd.print(STATE_FULL[state_index]);
lcd.setCursor(10, 1);
lcd.print("Crate:");
lcd.print(CURRENT_SELECTED[current_selected_index]);
if (CURRENT_SELECTED[current_selected_index] != 1000) {
lcd.print(" ");
}
lcd.setCursor(10, 2);
lcd.print(ERROR_MSG[batNumber - 1]);
}
//fonction permettatn d'afficher l'ecran qui donne les détails de deux batteries (écran partagé en deux)
void screenDetail(int batNumber, int position) {
int positionY = 11 - 11 * (position % 2);
lcd.setCursor(positionY, 0);
if (batteryToSet == batNumber) {
lcd.print(char(2));
} else {
lcd.print(batNumber);
}
lcd.print(BAT_STATE[batNumber - 1]);
lcd.print(BAT_ACTION_STATE[batNumber - 1]);
lcd.print(" ");
lcd.print(int(CAPACITY[batNumber - 1]));
lcd.print("C");
lcd.setCursor(positionY, 1);
//H
if ((TIME[batNumber - 1] - STARTED_TIME[batNumber - 1]) / 3600000 < 10) {
lcd.print("0");
}
lcd.print((TIME[batNumber - 1] - STARTED_TIME[batNumber - 1]) / 3600000);
//M
lcd.print(":");
if (((TIME[batNumber - 1] - STARTED_TIME[batNumber - 1]) % 3600000) / 60000 < 10) {
lcd.print("0");
}
lcd.print(((TIME[batNumber - 1] - STARTED_TIME[batNumber - 1]) % 3600000) / 60000);
//S
lcd.print(":");
if (((TIME[batNumber - 1] - STARTED_TIME[batNumber - 1]) % 60000) / 1000 < 10) {
lcd.print("0");
}
lcd.print(((TIME[batNumber - 1] - STARTED_TIME[batNumber - 1]) % 60000) / 1000);
lcd.setCursor(positionY, 2);
lcd.print(VOLTAGE[batNumber - 1], 2);
lcd.print("V R");
lcd.setCursor(positionY, 3);
if ((BAT_STATE[batNumber - 1] == STATE_SHORT[1] || BAT_STATE[batNumber - 1] == STATE_SHORT[2]) && BAT_ACTION_STATE[batNumber - 1] == STATE_SHORT[7] && discharge_state[batNumber - 1] != 3) {
if (CURRENT[batNumber - 1] < 10) {
lcd.print(CURRENT[batNumber - 1]);
lcd.print("A ");
} else if (CURRENT[batNumber - 1] < 100) {
lcd.print(CURRENT[batNumber - 1]);
lcd.print("A ");
} else if (CURRENT[batNumber - 1] < 1000) {
lcd.print(CURRENT[batNumber - 1]);
lcd.print("A ");
} else {
lcd.print(CURRENT[batNumber - 1]);
lcd.print("A");
}
} else {
lcd.print("0");
lcd.print("A ");
}
lcd.setCursor(positionY + 6, 3);
lcd.print(IRES[batNumber - 1]);
}
//lecture de la tension d'alimentation pour une meilleur lecture de la tension de batterie
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;
}