#include <Chrono.h>
Chrono chronoA; 
Chrono chronoB;
Chrono button; 
 
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27, 16, 2);

#include <DHT.h>;  
#define DHTPIN 5 // what pin we're connected to
#define DHTTYPE DHT22   // DHT 22  (AM2302)
DHT dht(DHTPIN, DHTTYPE); 
// Initialize DHT sensor for normal 16mhz Arduino
int chk;

int buttonPin = 6;
int piezoPin= 7;
int ledPin1=8;
int ledPin2=9;
int ledPin3=4;
int relay1Pin =10;
int relay2Pin =11;
int ledFlipflopPin= 12;

//int ledPin1State=LOW;
int ledFlipFlopState= LOW;
const long interval = 250;// interval at which to blink
const long interval2 = 900;// interval change text in LCD
const long interval3 = 400;
int buttonPushCounter = 0; // counter for the number of button presses

bool buttonState = false; // current state of the button
bool lastbuttonState = false; // previous state of the button
unsigned long lcdOn=40000;
unsigned long previousTimeLcdOnOff=0;
unsigned long previousTimeNormal=0;
unsigned long previousTimeLedFlipFlop=0;
unsigned long previousTimeTemp=0;
unsigned long previousTimebatVolAlarm=0;
unsigned long previousTimeSourceVolAlarm=0;
float temp; //Stores temperature
float sourceCutoff = 49.00; //Source Cutoff voltage
float batCutoff = 10.80; //Battery Cutoff voltage
float sourceOvervoltage = 56.20; //Source Overvoltage
float batOvervoltage = 14.30;//Battery Overvoltage
float voltageHysteresis = 0.20;

int analogInput1 = A0; // voltage measurement pin
int value1 = 0;
float vout1 = 0.0;
float vSource = 0.0;
float R1a =130000;
float pot1 = 12000;

int analogInput2 = A1; // voltage measurement pin
int value2 = 0;
float vout2 = 0.0;
float vBat = 0.0;
float R2a =130000;
float pot2 = 15000;

byte count = 0;

bool firstScreenFlag = false;
bool secondScreenFlag = false;
bool thirdScreenFlag = false;
bool fourthScreenFlag= false;
bool lastpin1State=false;
bool pin1State=false;
bool lastpin2State=false;
bool pin2State=false;

long time=11000;
long target1 = 25000; //15 in sec
//long test1 = target1 - chronoA.elapsed();
int mins1 = (target1 / 1000)/60;
int secs1 = round(target1 /1000)%60;
long target2 = 20000; //20 in sec
int mins2 = (target2 / 1000)/60;
int secs2 = round(target2 /1000)%60;

void setup() {
  Serial.begin(9600);
  pinMode(analogInput1,INPUT); // Set pin A0 as Voltage input
  pinMode(analogInput2,INPUT); // Set pin A1
  pinMode(relay1Pin, OUTPUT);
  pinMode(relay2Pin, OUTPUT);
  pinMode(ledPin1, OUTPUT);//Source Cutoff voltage
  pinMode(ledPin2, OUTPUT);//Battery Cutoff voltage
  pinMode(ledFlipflopPin, OUTPUT);
  pinMode(buttonPin, INPUT);
  lcd.begin(16, 2);
  lcd.setBacklight(1);  
  lcd.setCursor(0,0);  
  lcd.print("Battery"); 
  lcd.setCursor(0,1);  
  lcd.print("Protection v.1.0"); 
  delay(3000);
}

void loop() {
  value1 = analogRead(analogInput1);
  vout1 = (value1 * 5.0) / 1024;
  vSource = vout1 / (pot1/(R1a+pot1));
  value2 = analogRead(analogInput2);
  vout2 = (value2 * 5.0) / 1024;
  vBat = vout2 / (pot2/(R2a+pot2)); 

buttonOnOff();
//Serial.println(buttonState);  
temp= dht.readTemperature();
unsigned long currentTime = millis();
if(temp >= 50.0) {
  digitalWrite(ledPin3,HIGH);
  digitalWrite(relay1Pin,HIGH);   //Stop charge the battery1
}
if(temp<49.0) {  
if(currentTime - previousTimeTemp >= 9000){
  previousTimeTemp = currentTime;  //get the current time
  digitalWrite(relay1Pin,LOW);   //Charge the battery1
  //digitalWrite(ledPin1,LOW);
}
}

lcdOnOff();

if (vSource<=sourceCutoff) {
   //digitalWrite(ledPin1,HIGH);  //Change the state of the relay1
   digitalWrite(relay1Pin, HIGH);
   lcd.setBacklight(1);
   Serial.println("Source cutoffvoltage relay1Pin is ON");
}
if (vSource>=sourceOvervoltage){
Serial.println("sourceOvervoltage");
digitalWrite(ledPin1, HIGH);
}
if (vBat<batCutoff){
Serial.println("batCutoff");
digitalWrite(ledPin2, HIGH);
}  
if (vSource<=sourceOvervoltage){
if (vSource>sourceCutoff){
  digitalWrite(ledPin1,LOW);
if (vBat<batOvervoltage){
if (vBat>=batCutoff) {
  digitalWrite(ledPin2,LOW);
if (pin1State==false){
if (lastpin1State==false){  
if (pin2State==false){
if (lastpin2State==false){  
if (temp<45.0) { 
   ledFlipFlopState = LOW;
  Normal();
  Serial.println("Running Normal");
}
}
}
}
}
}
}
}
}
if (vBat>=batOvervoltage) {
   //digitalWrite(ledPin2,HIGH);  //Change the state of the relay1
   digitalWrite(relay2Pin, HIGH);
   lcd.setBacklight(1);
   //Serial.println("Battery Overvoltage relay2Pin is ON"); 
}

 pin1State =digitalRead(relay1Pin);//Check pin state
 if (lastpin1State==false){//if it is changed
   //Then the pinState went from false to true
   if (pin1State == true){//if it is true
    lastpin1State=true;
    chronoA.restart(0); //Starts timer countdown
    Serial.println("chronoA.start");
    //digitalWrite(ledPin1, HIGH);
   }
 }
    else if (chronoA.elapsed() < target1){
      Serial.println("chronoA.running");
    //If timer running, send to display data
    long test1 = target1 - chronoA.elapsed();
    int testSecs1 = round(test1 / 1000);
    if (round(testSecs1/60) != mins1){
      mins1 = round(testSecs1/60);
    }
    if (round(testSecs1%60)!= secs1) {
      secs1 = round(testSecs1%60);
      }
      sourceVolAlarm();
      displayLedFlipflop();
  } 
  else if (chronoA.elapsed() >= target1 && pin1State == true) {
  chronoA.restart(0); //Restarts timer at 0 
  Serial.println("chronoA.restart");
  //If timer running, send to display here
    long test1 = target1 - chronoA.elapsed();
    int testSecs1 = round(test1 / 1000);
    if (round(testSecs1/60) != mins1){
      mins1 = round(testSecs1/60);
    }
    if (round(testSecs1%60)!= secs1) {
      secs1 = round(testSecs1%60);
  }
   sourceVolAlarm();
   Serial.println("running sourceVolAlarm");
  
  }
else if (chronoA.elapsed() >= target1 ){ 
//if timer has stopped, reset here and trigger alarm
     lastpin1State=false;
    //digitalWrite(ledPin1,LOW);
    digitalWrite(relay1Pin, LOW);
    stopA();
    Serial.println("stopA");
    Serial.println("chronoA.elapsed >= target1");
}

  pin2State =digitalRead(relay2Pin);//Check pin state
 if (lastpin2State==false){//if it is changed
   //Then the pinState went from false to true
   if (pin2State == true){//if it is true
    lastpin2State=true;
    chronoB.restart(0); //Starts timer at 0 
    Serial.println("chronoB.start");
   }
 }
  else if (chronoB.elapsed() < target2){
    //If timer running, send to display here
    long test2 = target2 - chronoB.elapsed();
    int testSecs2 = round(test2 / 1000);
    if (round(testSecs2/60) != mins2){
      mins2 = round(testSecs2/60);
    }
    if (round(testSecs2%60)!= secs2) {
      secs2 = round(testSecs2%60);
  }
      batVolAlarm();
      Serial.println("running batVolAlarm");
      //displayLedFlipflop();
  }
  else if (chronoB.elapsed() >= target2 && pin2State == true) {
  chronoB.restart(0); //Restarts timer at 0 
  //If timer running, send to display here
    long test2 = target2 - chronoB.elapsed();
    int testSecs2 = round(test2 / 1000);
    if (round(testSecs2/60) != mins2){
      mins2 = round(testSecs2/60);
    }
    if (round(testSecs2%60)!= secs2) {
      secs2 = round(testSecs2%60);
  }
   batVolAlarm();
  Serial.println("chronoB.restart");
  }
  else if (chronoB.elapsed() >= target2 ){ 
//if timer has stopped, reset here and trigger alarm
     lastpin2State=false;
    Serial.println("stopB");
    //digitalWrite(ledPin2,LOW);
    digitalWrite(relay2Pin, LOW);
    stopB();
    Serial.println("chronoB.elapsed >= target2");
}
}

void displayLedFlipflop(){
  unsigned long currentTime = millis();
if (currentTime - previousTimeLedFlipFlop >= 1000) {
// save the last time you blinked the LED
 if (ledFlipFlopState ==HIGH){
    ledFlipFlopState = LOW;
    } else {
    ledFlipFlopState = HIGH;
// set the LED with the ledState of the variable:
  }
digitalWrite(ledFlipflopPin, ledFlipFlopState);
}
}

void Normal(){
unsigned long currentTime = millis();
if (currentTime - previousTimeNormal >= interval2) {
previousTimeNormal = currentTime;
count++;
//Serial.println(count);

if (count == 1){
firstScreenFlag = true;
lcd.setCursor(0,0);
lcd.print("Battery ");
lcd.setCursor(8,0);
lcd.print("Charging");
}
if (count == 2){
secondScreenFlag = true;
lcd.setCursor(0,0);
lcd.print("Temp Batt:  ");
lcd.setCursor(11,0);
lcd.print(temp);  
lcd.setCursor(15,0);
lcd.print("C");
}
if (count == 3){
thirdScreenFlag = true;
lcd.setCursor(0,1);  
  lcd.print("Vsource:");
  lcd.setCursor(8,1);  
  lcd.print(vSource);
  lcd.setCursor(12,1);  
  lcd.print("V   ");
}
if (count == 4){
fourthScreenFlag = true;
lcd.setCursor(0,1);  
  lcd.print("Vbattery:");
  lcd.setCursor(9,1);  
  lcd.print(vBat,1);
  lcd.setCursor(13,1);  
  lcd.print("V   ");
count = 0;
}
}
}
void batVolAlarm(){
unsigned long currentTime = millis();
if (currentTime-previousTimebatVolAlarm>=interval3) {
previousTimebatVolAlarm = currentTime;
count++;
if (count == 1){
lcd.setCursor(0,0);
lcd.print("Alarm       ");
    } 
if (count == 2){
lcd.setCursor(0,0);
lcd.print("OverVoltage  ");
lcd.setCursor(0,1);  
  lcd.print("Vbattery:");
  lcd.setCursor(9,1);  
  lcd.print(vBat,1);
  lcd.setCursor(13,1);  
  lcd.print("V   ");
   count = 0;
}
lcd.setCursor(12,0);
  lcd.print(mins2);
  lcd.setCursor(13,0);
  lcd.print(":");
  lcd.setCursor(14,0);
  lcd.print(secs2);
  if (secs2<=10){
  //lcd.setCursor(15,0);  
  lcd.print(" ");
}
}
}

void sourceVolAlarm(){
unsigned long currentTime = millis();
if (currentTime - previousTimeSourceVolAlarm >= interval2) {
previousTimeSourceVolAlarm = currentTime;
count++;
if (count == 1){
lcd.setCursor(0,0);
lcd.print("Alarm      ");
    } 
if (count == 2){
lcd.setCursor(0,0);
lcd.print("Low Voltage ");
lcd.setCursor(0,1);  
  lcd.print("Vsource:");
  lcd.setCursor(8,1);  
  lcd.print(vSource,1);
  lcd.setCursor(12,1);  
  lcd.print("V   ");
  count = 0;
}
lcd.setCursor(12,0);
  lcd.print(mins1);
  lcd.setCursor(13,0);
  lcd.print(":");
  lcd.setCursor(14,0);
  lcd.print(secs1);
  if (secs1<=10){
  //lcd.setCursor(15,0);  
  lcd.print(" ");
}
}
}

void stopA (){
chronoA.stop();
}
void stopB (){
chronoB.stop();
}

void lcdOnOff(){
  unsigned long currentTime = millis();
  if (currentTime - previousTimeLcdOnOff>=lcdOn){  
  lcd.setBacklight(0);
  previousTimeLcdOnOff=currentTime; 
  //digitalWrite(ledPin,LOW); 
}
}
void buttonOnOff(){
    
 buttonState = digitalRead(buttonPin); 
 // read the pushbutton input pin
 if (buttonState != lastbuttonState){ 
// compare the buttonState to its previous state
 if (buttonState == HIGH){ 
// if the current state is HIGH then the button went 
//from off to on 
 lcd.setBacklight(1);

}
lastbuttonState = buttonState;
//save the current state as the last state,for next time through the loop
Serial.println(buttonState);
}
delay(50);
}