#include <EEPROM.h>

#include <Wire.h>
#include <LiquidCrystal_I2C.h>

//LiquidCrystal_I2C lcd(34, 16, 2); // set the LCD address to 0x27 for a 16 chars and 2 line display
LiquidCrystal_I2C lcd(0x27, 16, 2);
// set the LCD address to 0x27 for a 16 chars and 2 line display

//HC-SR04
const int trigPin = 13;
const int echoPin = 12;

long duration;
int distance;
int tankDepth;
int percentage;

//OTHER
int buzzer = 7;
int led = 8; // to indicate pump is ON
int relay = 2;
int mode = 11; // spst switch
int measureTankSize = 6; // push-pull
int startStop = 4;  //push-pull
int dryRun = 5; //float switch
//bool state;
bool pump, isDry;
//-------------------------------------------------

void setup()
{
  //Serial.begin(9600);
  lcd.init();         // initialize the lcd
  lcd.backlight();    // Turn on the LCD screen backlight

  pinMode(trigPin, OUTPUT); //HC-SR04
  pinMode(echoPin, INPUT);

  pinMode(buzzer, OUTPUT);
  pinMode(led, OUTPUT);
  pinMode(relay, OUTPUT);
  pinMode(mode, INPUT_PULLUP);
  pinMode(measureTankSize, INPUT_PULLUP);
  pinMode(startStop, INPUT_PULLUP);
  pinMode(dryRun, INPUT_PULLUP);


  tankDepth = EEPROM.read(0);
  if (tankDepth > 150) {
    tankDepth = 150;
  }

}

void loop()
{
  //default print
  lcd.setCursor(0, 0);
  lcd.print("WATER LEVEL:");
  lcd.setCursor(0, 1);
  lcd.print("PUMP:");

  //HC-SR04
  digitalWrite(trigPin, LOW); // Clears the trigPin
  delayMicroseconds(2);
  digitalWrite(trigPin, HIGH); // Sets the trigPin on HIGH state for 10 micro seconds
  delayMicroseconds(10);
  digitalWrite(trigPin, LOW);

  duration = pulseIn(echoPin, HIGH); //measures the time until the ECHO pin goes LOW (in micro Sec)
  distance = duration * 0.034 / 2; // cm
  percentage = ((tankDepth - distance) * 100) / tankDepth; // filled water = tankDepth - distance(surface)
  if (percentage < 0) {
    percentage = 0;
  }

  //measure Tank Size
  if (!digitalRead(mode) & !digitalRead(measureTankSize)) {
    tankDepth = distance;
    EEPROM.write(0, distance);

    lcd.setCursor(0, 0);
    lcd.print("Level Scanning..");
    delay(3000);
  }

  //Print
  lcd.setCursor(12, 0);
  lcd.print(percentage);
  lcd.print("%   ");

  //AUTO
  if (digitalRead(mode) & percentage < 25) {
    pump = 1;
  }
  if (percentage > 90) {
    pump = 0;
  }

  //MANUAL
  if (!digitalRead(mode) & !digitalRead(startStop)) {
    pump = !pump;
  }
  while (!digitalRead(startStop)) { // to make toggle perfect
    delay(50);
  }

  //(*)Dry Run protection
  if ((pump == 1) & digitalRead(dryRun)) {
    pump = 0;
    isDry = !isDry; // step 1 to run motor only once till next digitalRead(!dryRun) and avoid repeated ON/OFF;

    lcd.setCursor(0, 1);
    lcd.print("PUMP     DRY !!");
    delay(60000);
  } else {
    isDry = 0;
  }

  //(*)control point (isDry case)
  if (isDry) {
    if (!digitalRead(dryRun)) {
      pump = 1;
    }
    isDry = 1; // step 2 to run motor only once till next digitalRead(!dryRun) and avoid repeated ON/OFF;
  } else {
    isDry = 1; // step 2 to run motor only once till next digitalRead(!dryRun) and avoid repeated ON/OFF;
  }

  //control point
  digitalWrite(relay, pump);
  digitalWrite(led, pump);
  delay(1000);
  digitalWrite(led, 0);

  //print
  lcd.setCursor(5, 1);
  if (pump) {
    lcd.print("ON ");
  } else {
    lcd.print("OFF");
  }
  lcd.setCursor(9, 1);
  if (!digitalRead(mode)) {
    lcd.print("Manual");
  } else {
    lcd.print("Auto  ");
  }

  // delay(500);
}

//NOTE:: (*) do Dry-run the code for "dryRun" and "isDry" cases.
NOCOMNCVCCGNDINLED1PWRRelay Module