#include <SimpleTimer.h>
SimpleTimer timer;
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <DHT.h>
// Uncomment whatever type you're using!
//#define DHTTYPE DHT11     // DHT 11
#define DHTTYPE DHT22   // DHT 22, AM2302, AM2321
//#define DHTTYPE DHT21   // DHT 21, AM2301

#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 64 // OLED display height, in pixels
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, -1);

#define Rvin A0 //Voltage read pins
#define Yvin A1
#define Bvin A2
const int CTR = A3; //CT read pins
const int CTY = A4;
const int CTB = A5;
#define VDelaySetpin A8
#define UVSetpin A9
#define OVSetpin A10
#define IDelaySetPin A11
#define OCSetPin A12

#define IRK 26
#define IYK 28
#define IBK 30

bool IRKState = 0;
bool IYKState = 0;
bool IBKState = 0;
float PF = 0.95; // Aprox Power factor value

#define CTRange 20; //set Non-invasive AC Current Sensor range (5A,10A,20A)
int OCS; //Over current setting
int Idelaytime;
int ITimeloopR1 = 0;
int ITimeloopY1 = 0;
int ITimeloopB1 = 0;

#define IRtimeloopOut 22
#define IYtimeloopOut 23
#define IBtimeloopOut 24

unsigned long Ir1currenttime = 0;
unsigned long Ir1previoustime = 0;
unsigned long Iy1currenttime = 0;
unsigned long Iy1previoustime = 0;
unsigned long Ib1currenttime = 0;
unsigned long Ib1previoustime = 0;

int IsecR1 = 0;
int IsecY1 = 0;
int IsecB1 = 0;

// VREF: Analog reference
// For Arduino UNO, Leonardo and mega2560, etc. change VREF to 5
// For Arduino Zero, Due, MKR Family, ESP32, etc. 3V3 controllers, change VREF to 3.3
#define VREF 5

int Vdelaytime;
int UnderVolt; //Under Voltage set at 180V phase voltage
int OverVolt; //Over Voltage set at 250V phase voltage

int VTimeloopR1 = 0;
int VTimeloopR2 = 0;
int VTimeloopY1 = 0;
int VTimeloopY2 = 0;
int VTimeloopB1 = 0;
int VTimeloopB2 = 0;

unsigned long vr1currenttime = 0;
unsigned long vr2currenttime = 0;
unsigned long vr1previoustime = 0;
unsigned long vr2previoustime = 0;

unsigned long vy1currenttime = 0;
unsigned long vy2currenttime = 0;
unsigned long vy1previoustime = 0;
unsigned long vy2previoustime = 0;

unsigned long vb1currenttime = 0;
unsigned long vb2currenttime = 0;
unsigned long vb1previoustime = 0;
unsigned long vb2previoustime = 0;

unsigned long blinkcurrentmillis = 0;
unsigned long blinkpreoviousmillis = 0;
long interval = 5000;

int VsecR1 = 0;
int VsecR2 = 0;
int VsecY1 = 0;
int VsecY2 = 0;
int VsecB1 = 0;
int VsecB2 = 0;

#define Bypass 52
#define KBypass 53
bool BypassState = LOW;
bool KBypassState = LOW;


#define VRtimeloopOut 8
#define VYtimeloopOut 9
#define VBtimeloopOut 10
#define VRK1 4
bool VRK1State = LOW;
#define VYK2 5
bool VYK2State = LOW;
#define VBK3 6
bool VBK3State = LOW;
#define VYK4 7
bool VYK4State = LOW;
#define Allokled 32
#define Faultled 34

#define Buzzer 36
#define Fan 38
bool FanState = LOW;

#define DHTPIN 15
int Temperature = 0;
int Humidity   = 0;
DHT dht(DHTPIN, DHTTYPE);

void setup()
{
  // Debug console
  Serial.begin(9600);

  display.begin(SSD1306_SWITCHCAPVCC, 0x3C);
  dht.begin();
  // Clear the buffer
  display.clearDisplay();
  // Display Text
  display.setTextSize(1);
  display.setTextColor(WHITE);
  display.setCursor(0, 28);
  display.println("Hello... Hashva!");
  display.display();
  display.clearDisplay();

  //During Starting all Relays should TURN OFF
  digitalWrite(VRK1, LOW);
  digitalWrite(VYK2, LOW);
  digitalWrite(VBK3, LOW);
  digitalWrite(VYK4, LOW);
  digitalWrite(IRK, LOW);
  digitalWrite(IYK, LOW);
  digitalWrite(IBK, LOW);

  pinMode(CTR, INPUT);
  pinMode(CTY, INPUT);
  pinMode(CTB, INPUT);

  pinMode(IRtimeloopOut, OUTPUT);
  pinMode(IYtimeloopOut, OUTPUT);
  pinMode(IBtimeloopOut, OUTPUT);
  pinMode(IRK, OUTPUT);
  pinMode(IYK, OUTPUT);
  pinMode(IBK, OUTPUT);

  pinMode(VDelaySetpin, INPUT);
  pinMode(UVSetpin, INPUT);
  pinMode(OVSetpin, INPUT);

  pinMode(Rvin, INPUT);
  pinMode(VRtimeloopOut, OUTPUT);
  //pinMode(RtimeloopIn, INPUT);
  pinMode(VRK1, OUTPUT);

  pinMode(Yvin, INPUT);
  pinMode(VYtimeloopOut, OUTPUT);
  //pinMode(YtimeloopIn, INPUT);
  pinMode(VYK2, OUTPUT);
  pinMode(VYK4, OUTPUT);

  pinMode(Bvin, INPUT);
  pinMode(VBtimeloopOut, OUTPUT);
  //pinMode(BtimeloopIn, INPUT);
  pinMode(VBK3, OUTPUT);

  pinMode(DHTPIN, INPUT);
  pinMode(Bypass, INPUT_PULLUP);
  pinMode(KBypass, OUTPUT);
  pinMode(Faultled, OUTPUT);
  pinMode(Allokled, OUTPUT);
  pinMode(Buzzer, OUTPUT);
  pinMode(Fan, OUTPUT);
  
  // Setup a function to be called every 0.6 & 2 seconds
  timer.setInterval(400L, VRphasecheck);
  timer.setInterval(400L, VYphasecheck);
  timer.setInterval(400L, VBphasecheck);
  timer.setInterval(400L, VYK4Control);
  timer.setInterval(200L, BypassControl);
  timer.setInterval(300, RPhaseCT);
  timer.setInterval(300, YPhaseCT);
  timer.setInterval(300, BPhaseCT);
  timer.setInterval(2000L, TempControl);
  delay(1000);
}
// get maximum reading value R Phase
int Rmax() {
  int maxR = 0;
  for (int R = 0; R < 100; R++) {
    int Rphase = analogRead(Rvin);  // read from analog channel 0 (A0)
    if (maxR < Rphase) maxR = Rphase;
    delayMicroseconds(100);
  }
  return maxR;
}
// get maximum reading value Y Phase
int Ymax() {
  int maxY = 0;
  for (int Y = 0; Y < 100; Y++) {
    int Yphase = analogRead(Yvin);  // read from analog channel 1 (A1)
    if (maxY < Yphase) maxY = Yphase;
    delayMicroseconds(100);
  }
  return maxY;
}
// get maximum reading value B Phase
int Bmax() {
  int maxB = 0;
  for (int B = 0; B < 100; B++) {
    int Bphase = analogRead(Bvin);  // read from analog channel 2 (A2)
    if (maxB < Bphase) maxB = Bphase;
    delayMicroseconds(100);
  }
  return maxB;
}

//R Phase CT
float ReadCTRValue()
{
  float CTRVal = 0;
  float RpeakVoltage = 0;
  float RvoltageVirtualValue = 0;  //Vrms
  for (int i = 0; i < 5; i++)
  {
    RpeakVoltage += analogRead(CTR);   //read peak voltage
    delay(1);
  }
  RpeakVoltage = RpeakVoltage / 5;
  RvoltageVirtualValue = RpeakVoltage * 0.707;    //change the peak voltage to the Virtual Value of voltage

  /*The circuit is amplified by 2 times, so it is divided by 2.*/
  RvoltageVirtualValue = (RvoltageVirtualValue / 1023 * VREF ) / 2;

  CTRVal = RvoltageVirtualValue * CTRange;

  return CTRVal;
}
//Y Phase CT
float ReadCTYValue()
{
  float CTYVal = 0;
  float YpeakVoltage = 0;
  float YvoltageVirtualValue = 0;  //Vrms
  for (int i = 0; i < 5; i++)
  {
    YpeakVoltage += analogRead(CTY);   //read peak voltage
    delay(1);
  }
  YpeakVoltage = YpeakVoltage / 5;
  YvoltageVirtualValue = YpeakVoltage * 0.707;    //change the peak voltage to the Virtual Value of voltage

  /*The circuit is amplified by 2 times, so it is divided by 2.*/
  YvoltageVirtualValue = (YvoltageVirtualValue / 1023 * VREF ) / 2;

  CTYVal = YvoltageVirtualValue * CTRange;

  return CTYVal;
}
//B Phase CT
float ReadCTBValue()
{
  float CTBVal = 0;
  float BpeakVoltage = 0;
  float BvoltageVirtualValue = 0;  //Vrms
  for (int i = 0; i < 5; i++)
  {
    BpeakVoltage += analogRead(CTB);   //read peak voltage
    delay(1);
  }
  BpeakVoltage = BpeakVoltage / 5;
  BvoltageVirtualValue = BpeakVoltage * 0.707;    //change the peak voltage to the Virtual Value of voltage

  /*The circuit is amplified by 2 times, so it is divided by 2.*/
  BvoltageVirtualValue = (BvoltageVirtualValue / 1023 * VREF ) / 2;

  CTBVal = BvoltageVirtualValue * CTRange;

  return CTBVal;
}

void loop()
{
  timer.run();

  //R phase output
  char RVolt[10];
  // get amplitude (maximum - or peak value)
  uint32_t vrout = Rmax();
  // get actual voltage (ADC voltage reference = 1.1V)
  vrout = vrout * 1100 / 1023;
  // calculate the RMS value ( = peak/√2 )
  vrout /= sqrt(2);

  //Y phase output
  char YVolt[10];
  uint32_t vyout = Ymax();
  vyout = vyout * 1100 / 1023;
  vyout /= sqrt(2);

  //B phase output
  char BVolt[10];
  uint32_t vbout = Bmax();
  vbout = vbout * 1100 / 1023;
  vbout /= sqrt(2);

  int delaytimeval = analogRead(VDelaySetpin);
  Vdelaytime = map(delaytimeval, 0, 1023, 1, 10);
  Serial.println("DelayTimeSet= ");
  Serial.println(Vdelaytime);

  int UnderVoltval = analogRead(UVSetpin);
  UnderVolt = map(UnderVoltval, 0, 1023, 100, 180);
  Serial.println("UV Set= ");
  Serial.println(UnderVolt);

  int OverVoltval = analogRead(OVSetpin);
  OverVolt = map(OverVoltval, 0, 1023, 240, 270);
  Serial.println("OV Set= ");
  Serial.println(OverVolt);

  int Idelaytimeval = analogRead(IDelaySetPin);
  Idelaytime = map(Idelaytimeval, 0, 1023, 0, 10);
  Serial.print("IDelayTime=");
  Serial.println(Idelaytime);

  int CTMax = CTRange;
  int OCSval = analogRead(OCSetPin);
  OCS = map(OCSval, 0, 1023, 0, CTMax);
  Serial.print("OCS=");
  Serial.println(OCS);

  // All OK LED2
  if (vrout > UnderVolt && vrout < OverVolt && vyout > UnderVolt && vyout < OverVolt && vbout > UnderVolt && vbout < OverVolt && IRKState==0 && IYKState==0 && IBKState==0)
  {
    digitalWrite(Allokled, HIGH);

  }
  else if (vrout < UnderVolt || vrout > OverVolt || vyout < UnderVolt || vyout > OverVolt || vbout < UnderVolt || vbout > OverVolt || IRKState==1 || IYKState==1 || IBKState==1)
  {
    digitalWrite(Allokled, LOW);
    digitalWrite(Faultled, HIGH);
    delay(250);
    digitalWrite(Faultled, LOW);
    delay(250);
  }

  //Buzzer
  unsigned long blinkcurrentmillis = millis();
  if (blinkcurrentmillis - blinkpreoviousmillis > interval)
  {
    blinkpreoviousmillis = blinkcurrentmillis;
    if (vrout < UnderVolt || vrout > OverVolt || vyout < UnderVolt || vyout > OverVolt || vbout < UnderVolt || vbout > OverVolt)
    {
      digitalWrite(Buzzer, HIGH);
      delay(600);
      digitalWrite(Buzzer, LOW);
      delay(500);
    }
  }

  //OLED Display Details
  display.clearDisplay();
  display.setTextSize(1);
  display.setTextColor(WHITE);
  display.drawCircle(8, 15, 8, WHITE);
  display.setCursor(6, 12);
  display.println("V");
  display.setCursor(0, 0);
  display.println("      R     Y     B");
  display.setCursor(29, 12);
  display.println(vrout);
  display.setCursor(65, 12);
  display.println(vyout);
  display.setCursor(101, 12);
  display.println(vbout);
  display.setCursor(0, 30);
  display.println("It:");
  display.setCursor(20, 30);
  display.println(Idelaytime);
  display.setCursor(35, 30);
  display.println("OCS:");
  display.setCursor(58, 30);
  display.println(OCS);
  display.setCursor(78, 30);
  display.println("T:   *C");
  display.setCursor(90, 30);
  display.println(Temperature);
  display.setCursor(0, 44);
  display.println("Vt:");
  display.setCursor(20, 44);
  display.println(Vdelaytime);
  display.setCursor(35, 44);
  display.println("UV:");
  display.setCursor(52, 44);
  display.println(UnderVolt);
  display.setCursor(82, 44);
  display.println("OV:");
  display.setCursor(100, 44);
  display.println(OverVolt);
  display.setCursor(0, 55);
  display.println("STS:");
  display.display();

  if (vrout < UnderVolt)
  {
    display.setTextColor(WHITE, BLACK); //Its clear part of line
    display.setCursor(25, 55);
    display.println("* R Under Voltage");
    display.display();
    delay(100);
  }
  if (vrout > OverVolt)
  {
    display.setTextColor(WHITE, BLACK);
    display.setCursor(25, 55);
    display.println("* R Over Voltage");
    display.display();
    delay(100);
  }
  if (vyout < UnderVolt)
  {
    display.setTextColor(WHITE, BLACK);
    display.setCursor(25, 55);
    display.println("* Y Under Voltage");
    display.display();
    delay(100);
  }
  if (vyout > OverVolt)
  {
    display.setTextColor(WHITE, BLACK);
    display.setCursor(25, 55);
    display.println("* Y Over Voltage");
    display.display();
    delay(100);
  }
  if (vbout < UnderVolt)
  {
    display.setTextColor(WHITE, BLACK);
    display.setCursor(25, 55);
    display.println("* B Under Voltage");
    display.display();
    delay(100);
  }
  if (vbout > OverVolt)
  {
    display.setTextColor(WHITE, BLACK);
    display.setCursor(25, 55);
    display.println("* B Over Voltage");
    display.display();
    delay(100);
  }
  if ( ((vrout >= UnderVolt) && (vrout <= OverVolt)) && ((vyout >= UnderVolt) && (vyout <= OverVolt)) && ((vbout >= UnderVolt) && (vbout <= OverVolt)))
  {
    display.setTextColor(WHITE, BLACK);
    display.setCursor(40, 55);
    display.println("~~Normal~~");
    display.display();
    delay(100);
  }
  if (digitalRead(KBypass) == HIGH)
  {
    display.setTextColor(WHITE, BLACK);
    display.setCursor(37, 55);
    display.println("~~Bypass ON~~ ");
    display.display();
    delay(100);
  }
  

}
void VRphasecheck()
{
  //R phase output
  char RVolt[10];
  // get amplitude (maximum - or peak value)
  uint32_t vrout = Rmax();
  // get actual voltage (ADC voltage reference = 1.1V)
  vrout = vrout * 1100 / 1023;
  // calculate the RMS value ( = peak/√2 )
  vrout /= sqrt(2);

  Serial.print("R= ");
  Serial.println(vrout);
  //R Phase Voltage Condition Checks
  vr1currenttime = millis();
  if (((vrout < UnderVolt) || (vrout > OverVolt)) && digitalRead(KBypass) == LOW)
  {
    digitalWrite(VRtimeloopOut, HIGH);
  }
  vr2currenttime = millis();
  if (((vrout >= UnderVolt)  &&  (vrout <= OverVolt)) || digitalRead(KBypass) == HIGH)
  {
    digitalWrite(VRtimeloopOut, LOW);
    VTimeloopR1 = LOW;
  }
  // R Phase Ondelay Timer for K1 Relay ON
  if (digitalRead(VRtimeloopOut) == HIGH && VTimeloopR1 == 0 && digitalRead(VRK1) == LOW)
  {
    VTimeloopR1 = 1;
    VsecR1 = Vdelaytime;
  }
  if (VTimeloopR1 == 1)
  {
    if ((vr1currenttime - vr1previoustime) > 1000)
    {
      VsecR1--;
      vr1previoustime = vr1currenttime;
      if (VsecR1 <= 0)
      {
        VTimeloopR1 = 0;
        digitalWrite(VRK1, HIGH);
        VRK1State = HIGH;
        Serial.print("K1 ON");
        VsecR1 = 0;
      }
    }
  }
  // R Phase Ondelay Timer for K1 Relay OFF
  else if (digitalRead(VRtimeloopOut) == LOW && VTimeloopR2 == 0 && digitalRead(VRK1) == HIGH)
  {
    VTimeloopR2 = 1;
    VsecR2 = Vdelaytime;
  }
  if (VTimeloopR2 == 1)
  {
    if ((vr2currenttime - vr2previoustime) > 1000)
    {
      VsecR2--;
      vr2previoustime = vr2currenttime;
      if (VsecR2 <= 0)
      {
        VTimeloopR2 = 0;
        digitalWrite(VRK1, LOW);
        VRK1State = LOW;
        Serial.print("VK1 OFF");
        VsecR2 = 0;
      }
    }
  }
}

void VYphasecheck()
{
  //Y phase output
  char YVolt[10];
  uint32_t vyout = Ymax();
  vyout = vyout * 1100 / 1023;
  vyout /= sqrt(2);

  Serial.print("Y= ");
  Serial.println(vyout);
  //Y Phase Voltage Condition Checks
  vy1currenttime = millis();
  if (((vyout < UnderVolt) || (vyout > OverVolt)) && digitalRead(KBypass) == LOW)
  {
    digitalWrite(VYtimeloopOut, HIGH);
  }
  vy2currenttime = millis();
  if (((vyout >= UnderVolt)  &&  (vyout <= OverVolt)) || digitalRead(KBypass) == HIGH)
  {
    digitalWrite(VYtimeloopOut, LOW);
    VTimeloopY1 = LOW;
  }
  // Y Phase Ondelay Timer for K2 Relay ON
  if (digitalRead(VYtimeloopOut) == HIGH && VTimeloopY1 == 0 && digitalRead(VYK2) == LOW)
  {
    VTimeloopY1 = 1;
    VsecY1 = Vdelaytime;
  }
  if (VTimeloopY1 == 1)
  {
    if ((vy1currenttime - vy1previoustime) > 1000)
    {
      VsecY1--;
      vy1previoustime = vy1currenttime;
      if (VsecY1 <= 0)
      {
        VTimeloopY1 = 0;
        digitalWrite(VYK2, HIGH);
        VYK2State = HIGH;
        Serial.print("K2 ON");
        VsecY1 = 0;
      }
    }
  }
  // Y Phase Ondelay Timer for K2 Relay OFF
  else if (digitalRead(VYtimeloopOut) == LOW && VTimeloopY2 == 0 && digitalRead(VYK2) == HIGH)
  {
    VTimeloopY2 = 1;
    VsecY2 = Vdelaytime;
  }
  if (VTimeloopY2 == 1)
  {
    if ((vy2currenttime - vy2previoustime) > 1000)
    {
      VsecY2--;
      vy2previoustime = vy2currenttime;
      if (VsecY2 <= 0)
      {
        VTimeloopY2 = 0;
        digitalWrite(VYK2, LOW);
        VYK2State = LOW;
        Serial.print("K2 OFF");
        VsecY2 = 0;
      }
    }
  }
}

void VBphasecheck()
{
  //B phase output
  char BVolt[10];
  uint32_t vbout = Bmax();
  vbout = vbout * 1100 / 1023;
  vbout /= sqrt(2);

  Serial.print("B= ");
  Serial.println(vbout);
  //B Phase Voltage Condition Checks
  vb1currenttime = millis();
  if (((vbout < UnderVolt) || (vbout > OverVolt)) && digitalRead(KBypass) == LOW)
  {
    digitalWrite(VBtimeloopOut, HIGH);
  }
  vb2currenttime = millis();
  if (((vbout >= UnderVolt)  &&  (vbout <= OverVolt)) || digitalRead(KBypass) == HIGH)
  {
    digitalWrite(VBtimeloopOut, LOW);
    VTimeloopB1 = LOW;
  }
  // Y Phase Ondelay Timer for K2 Relay ON
  if (digitalRead(VBtimeloopOut) == HIGH && VTimeloopB1 == 0 && digitalRead(VBK3) == LOW)
  {
    VTimeloopB1 = 1;
    VsecB1 = Vdelaytime;
  }
  if (VTimeloopB1 == 1)
  {
    if ((vb1currenttime - vb1previoustime) > 1000)
    {
      VsecB1--;
      vb1previoustime = vb1currenttime;
      if (VsecB1 <= 0)
      {
        VTimeloopB1 = 0;
        digitalWrite(VBK3, HIGH);
        VBK3State = HIGH;
        Serial.print("K3 ON");
        VsecB1 = 0;
      }
    }
  }
  // B Phase Ondelay Timer for K3 Relay OFF
  else if (digitalRead(VBtimeloopOut) == LOW && VTimeloopB2 == 0 && digitalRead(VBK3) == HIGH)
  {
    VTimeloopB2 = 1;
    VsecB2 = Vdelaytime;
  }
  if (VTimeloopB2 == 1)
  {
    if ((vb2currenttime - vb2previoustime) > 1000)
    {
      VsecB2--;
      vb2previoustime = vb2currenttime;
      if (VsecB2 <= 0)
      {
        VTimeloopB2 = 0;
        digitalWrite(VBK3, LOW);
        VBK3State = LOW;
        Serial.print("K3 OFF");
        VsecB2 = 0;
      }
    }
  }
}

void VYK4Control()
{
  //R&B Phase fail for K4 Pickup
  if (digitalRead(VRK1) == HIGH && digitalRead(VBK3) == HIGH && digitalRead(VYK2) == LOW)
  {
    digitalWrite(VYK4, HIGH);
    VYK4State = HIGH;
  }
  else if (digitalRead(VRK1) == LOW || digitalRead(VBK3) == LOW || digitalRead(VYK2) == HIGH)
  {
    digitalWrite(VYK4, LOW);
    VYK4State = LOW;
  }
}

void TempControl()
{
  //Panel Temperature control
  float h = dht.readHumidity();
  float t = dht.readTemperature(); // or dht.readTemperature(true) for Fahrenheit

  if (isnan(h) || isnan(t)) {
    Serial.println("Failed to read from DHT sensor!");
    return;
  }
  else {
    Humidity = h;
    Temperature = t;
    Serial.println(Temperature);
    Serial.println(Humidity);
  }

  if (Temperature > 40)
  {
    digitalWrite(Fan, HIGH); //K5 for Panel cooling fan
    FanState = HIGH;

  }
  else if (Temperature < 40)
  {
    digitalWrite(Fan, LOW);
    FanState = LOW;
  }
}

//Bypass Setup
void BypassControl()
{
  if (digitalRead(Bypass) == LOW && BypassState == LOW)
  {
    digitalWrite(KBypass, HIGH);
    BypassState = 1;
    KBypassState = 1;
  }
  if (digitalRead(Bypass) == HIGH && BypassState == HIGH)
  {
    digitalWrite(KBypass, LOW);
    BypassState = 0;
    KBypassState = 0;
  }
}
//R Phase CT read/control
void RPhaseCT()
{
  float CTRVal = ReadCTRValue(); //read AC Current Value of R
  Serial.print(CTRVal);
  Serial.println(" A/Rphase");


  Ir1currenttime = millis();
  if (CTRVal > OCS)
  {
    digitalWrite(IRtimeloopOut, HIGH);
  }
  if (CTRVal < OCS)
  {
    digitalWrite(IRtimeloopOut, LOW);
    ITimeloopR1 = LOW;
  }
  // R Phase Ondelay Timer for RK Relay ON/OFF
  if (digitalRead(IRtimeloopOut) == HIGH && ITimeloopR1 == 0 && IRKState == LOW)
  {
    ITimeloopR1 = 1;
    IsecR1 = Idelaytime;
  }
  if (ITimeloopR1 == 1)
  {
    if ((Ir1currenttime - Ir1previoustime) > 1000)
    {
      IsecR1--;
      Ir1previoustime = Ir1currenttime;
      if (IsecR1 <= 0)
      {
        ITimeloopR1 = 0;
        digitalWrite(IRK, HIGH);
        IRKState = HIGH;
        IsecR1 = 0;

      }
    }
  }
  if (digitalRead(IRtimeloopOut) == LOW)
  {
    digitalWrite(IRK, LOW);
    IRKState = 0;
  }
}
//Y Phase CT read/control
void YPhaseCT()
{
  float CTYVal = ReadCTYValue(); //read AC Current Value of Y
  Serial.print(CTYVal);
  Serial.println(" A/Yphase");

  Iy1currenttime = millis();
  if (CTYVal > OCS)
  {
    digitalWrite(IYtimeloopOut, HIGH);
  }
  if (CTYVal < OCS)
  {
    digitalWrite(IYtimeloopOut, LOW);
    ITimeloopY1 = LOW;
  }
  // R Phase Ondelay Timer for RK Relay ON/OFF
  if (digitalRead(IYtimeloopOut) == HIGH && ITimeloopY1 == 0 && IYKState == LOW)
  {
    ITimeloopY1 = 1;
    IsecY1 = Idelaytime;
  }
  if (ITimeloopY1 == 1)
  {
    if ((Iy1currenttime - Iy1previoustime) > 1000)
    {
      IsecY1--;
      Iy1previoustime = Iy1currenttime;
      if (IsecY1 <= 0)
      {
        ITimeloopY1 = 0;
        digitalWrite(IYK, HIGH);
        IYKState = HIGH;
        IsecY1 = 0;
      }
    }
  }
  if (digitalRead(IYtimeloopOut) == LOW)
  {
    digitalWrite(IYK, LOW);
    IYKState = 0;
  }
}
//B Phase CT read/control
void BPhaseCT()
{
  float CTBVal = ReadCTBValue(); //read AC Current Value of B
  Serial.print(CTBVal);
  Serial.println(" A/Bphase");
  Ib1currenttime = millis();
  if (CTBVal > OCS)
  {
    digitalWrite(IBtimeloopOut, HIGH);
  }
  if (CTBVal < OCS)
  {
    digitalWrite(IBtimeloopOut, LOW);
    ITimeloopB1 = LOW;
  }
  // R Phase Ondelay Timer for RK Relay ON/OFF
  if (digitalRead(IBtimeloopOut) == HIGH && ITimeloopB1 == 0 && IBKState == LOW)
  {
    ITimeloopB1 = 1;
    IsecB1 = Idelaytime;
  }
  if (ITimeloopB1 == 1)
  {
    if ((Ib1currenttime - Ib1previoustime) > 1000)
    {
      IsecB1--;
      Ib1previoustime = Ib1currenttime;
      if (IsecB1 <= 0)
      {
        ITimeloopB1 = 0;
        digitalWrite(IBK, HIGH);
        IBKState = HIGH;
        IsecB1 = 0;
      }
    }
  }

  if (digitalRead(IBtimeloopOut) == LOW)
  {
    digitalWrite(IBK, LOW);
    IBKState = 0;

  }
}