/*
  Arduino | coding-help
  Coding Help for the servo motor
  November 2, 2024

  Moong at 1:10 PM
  Hello, I am currently making a small project where im
  creating a "Coffee Maker" and I am having issues with the servo motor

  Fixes i tried to make
  Make a Seperate file do sweep on servo (Servo worked)
  Used a external power and used the project code (Servo did not work)

  Not really sure what to and getting confused on what to fix

  If youre interested the code is here
*/

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

#define DHTPIN 5
#define DHTTYPE DHT22

const int SERVO_PIN = 2;
const int CUP_SENSOR = 6;
const int PUMP_PIN = 3;
const int BUZZ_PIN = 4;

// create objects
Servo heaterServo;
DHT dht(DHTPIN, DHTTYPE);
LiquidCrystal_I2C lcd(0x27, 16, 2);

// State tracking variables
bool isCupPlaced = false;
bool isHeating = false;
bool isHeated = false;
unsigned long current, previous, interval = 1000;

// LCD message tracking
String lastMessage1;
String lastMessage2;
char* msgLine1;
char* msgLine2;

unsigned long beeperStartTime = 0;
bool beeping = false;
bool isNotified = false;
int oldSenseState = HIGH;

/*
  void updateLCD(char* msg1, char* msg2)  {

  if (!isNotified)  {
    lcd.clear();  // Clear before printing new messages
    lcd.setCursor(0, 0);
    lcd.print(msg1);
    lcd.setCursor(0, 1);
    lcd.print(msg2);
    isNotified = true;
  }
  }
*/


void updateLCD(String message1, String message2) {
  // Only update if the message has changed
  if (lastMessage1 != message1 || lastMessage2 != message2) {
    lastMessage1 = message1;
    lastMessage2 = message2;

    lcd.clear();  // Clear before printing new messages
    lcd.setCursor(0, 0);
    lcd.print(message1);
    lcd.setCursor(0, 1);
    lcd.print(message2);
  }
}


bool checkCup() {
  static bool isCup = false;

  int senseState = digitalRead(CUP_SENSOR);
  if (senseState != oldSenseState)  {
    oldSenseState = senseState;
    lcd.clear();
    lcd.setCursor(2, 0);
    lcd.print("Coffee Maker");
    if (senseState == HIGH)  {
      lcd.setCursor(3, 1);
      lcd.print("Cup placed");
      Serial.println("Cup placed");
      isCup = true;
    } else {
      lcd.setCursor(0, 1);
      lcd.print("No cup detected");
      Serial.println("No cup detected");
      isCup = false;
    }
    delay(50);
  }
  return isCup;
}

/*
  bool checkCup() {
  //static
  //if (!isNotified)  {

  if (digitalRead(CUP_SENSOR) == LOW) { // Check the actual sensor state
    isCupPlaced = true;
    updateLCD("Coffee Maker:", "Mug Is placed!");
  } else {
    isCupPlaced = false;
    updateLCD("Coffee Maker:", "Place mug");
  }
  isNotified = true;
  //}
  return isCupPlaced;
  }
*/

/*
  void checkCup() {
  if (digitalRead(CUP_SENSOR) == LOW) { // Check the actual sensor state
    isCupPlaced = true;
    updateLCD("Coffee Maker:", "Mug Is placed!");
  } else if (digitalRead(CUP_SENSOR) == HIGH) {
    isCupPlaced = false;
    current = millis();
    if (current - previous >= interval) {
      previous = current;
      updateLCD("Coffee Maker:", "Put a Mug");
    }
  }
  }
*/

void Boiling(float temperature) {

  //if (temperature <= 35.0 && !isHeated) {
  if (temperature <= 35.0) {
    Serial.println("Needs heat");
    heaterServo.write(0);
    isHeating = true;
    current = millis();
    if (current - previous >= interval) {
      previous = current;
      updateLCD("Coffee Maker:", "Heating....");
    }
  } else if (temperature > 35.0) {
    Serial.println("Is hot");
    heaterServo.write(90);
    isHeating = false;
    isHeated = true;
    current = millis();
    if (current - previous >= interval) {
      previous = current;
      updateLCD("Coffee Maker:", "Finished Heating");
    }
  }
}
//}

void PumpingWater(int waterLevel) {
  if (isCupPlaced) { // Check if the cup is present
    if (isHeated && waterLevel <= 100) { // Use '==' for comparison
      digitalWrite(PUMP_PIN, LOW); // Activate pump
      current = millis();
      if (current - previous >= interval) {
        previous = current;
        updateLCD("Coffee Maker:", "Pouring....");
      }
    } else if (waterLevel > 100) {
      digitalWrite(PUMP_PIN, HIGH); // Deactivate pump when water level is too high
      if (!beeping) { // Start beeping if not already beeping
        digitalWrite(BUZZ_PIN, HIGH);
        beeping = true;
        beeperStartTime = millis(); // Start timer for beeper
        updateLCD("Coffee Maker:", "Coffee Ready!");
      } else if (millis() - beeperStartTime >= 1000) { // Beep for 1 second
        digitalWrite(BUZZ_PIN, LOW);
        beeping = false; // Reset beeping state
      }
    }
  } else {
    digitalWrite(PUMP_PIN, HIGH); // Ensure pump is off when no cup is detected
    digitalWrite(BUZZ_PIN, LOW); // Ensure beeper is off when no cup
  }
}

void showSplash() {
  lcd.clear();
  lcd.setCursor(2, 0);
  lcd.print("Coffee Maker");
  lcd.setCursor(5, 1);
  lcd.print("v1.00");
}

// Setup function
void setup() {
  Serial.begin(9600);
  dht.begin();
  lcd.init();
  lcd.backlight();
  heaterServo.attach(SERVO_PIN);
  pinMode(CUP_SENSOR, INPUT);
  pinMode(PUMP_PIN, OUTPUT);
  pinMode(BUZZ_PIN, OUTPUT);
  // initialize
  digitalWrite(PUMP_PIN, LOW);
  heaterServo.write(90);
  showSplash();
  delay(2000);
  lcd.clear();
}

void loop() {

  isCupPlaced = checkCup();

  if (isCupPlaced) {
    int waterLevel = analogRead(A0);
    float temperature = dht.readTemperature();
    // Check if temperature reading is valid
    if (isnan(temperature)) {
      updateLCD("Coffee Maker:", "Temp Error!");
      return; // Exit if temperature is invalid
    }
    //Serial.println(temperature);

    Boiling(temperature);
    //PumpingWater(waterLevel);
    //delay(2000);
  } else  {
    // shut down
    digitalWrite(PUMP_PIN, LOW);
    heaterServo.write(90);
  }

}
$abcdeabcde151015202530fghijfghij
NOCOMNCVCCGNDINLED1PWRRelay Module
Cup sensor
Heater switch
Pump
Water level
Temp sensor