#define BLYNK_TEMPLATE_ID "TMPL6W1zyw7GY"
#define BLYNK_TEMPLATE_NAME "SISTEM KEAMANAN MOTOR "
#define BLYNK_AUTH_TOKEN "VH5qe_y-w07rLJDMlg7LsLaO39x9Pj_l"

#define BLYNK_PRINT Serial

#include <ESP32Servo.h>
#include <LiquidCrystal_I2C.h>
#include <BlynkSimpleEsp32.h>

const char* ssid = "Wokwi-GUEST";
const char* password = "";

const int encoderPinA = 5;     // Pin A pada rotary encoder
const int encoderPinB = 4;     // Pin B pada rotary encoder
const int servoPin = 18;       // Pin untuk servo
const int ledPin = 19;         // Pin untuk LED
const int buzzerPin = 12;      // Pin untuk buzzer
const int switchPin = 27;      // Pin untuk switch
const int pirPin = 15;         // Pin untuk sensor PIR

Servo servo;

LiquidCrystal_I2C lcd(0x27, 20, 4);

WidgetLCD lcd1(V2);

int lastEncoded = 0;
int encoderValue = 0;
int previousEncoderValue = 0;
int resetCount = 0;
bool servoLocked = false;

BLYNK_WRITE(V1) {  // Mendapatkan nilai dari button switch di Blynk
  int switchValue = param.asInt();
  
  if (switchValue == 1) {
          lcd.setCursor(0, 1);
      lcd.print("Ada Maling");
      lcd1.print(0,1, "Ada Maling");
      Blynk.logEvent("maling", "Ada Maling");
      
      // Menyalakan buzzer
      tone(buzzerPin, 1000);
      
      // Menyalakan LED merah
      digitalWrite(ledPin, HIGH);
      
      // Mengunci servo
      servoLocked = true;
      
      delay(5000); // Tunggu selama 5 detik
      
      // Mematikan buzzer
      noTone(buzzerPin);
  } else {
        digitalWrite(ledPin, LOW);
      lcd.setCursor(0,1);
      lcd.print("           " );
      lcd1.print(0,1,"           ");
      // Membuka kunci servo
      servoLocked = false;
  }
}

void setup() {
  lcd.init();
  lcd.backlight();

  Blynk.begin(BLYNK_AUTH_TOKEN, ssid, password);

  pinMode(switchPin, INPUT_PULLUP);
  pinMode(encoderPinA, INPUT_PULLUP);
  pinMode(encoderPinB, INPUT_PULLUP);
  pinMode(ledPin, OUTPUT);
  pinMode(buzzerPin, OUTPUT);
  pinMode(pirPin, INPUT);

  servo.attach(servoPin);     // Menghubungkan servo ke pin yang ditentukan

  // Mengatur posisi awal servo ke 0 derajat
  servo.write(0);

  // Mengatur interrupt untuk membaca perubahan nilai encoder
  attachInterrupt(digitalPinToInterrupt(encoderPinA), readEncoder, CHANGE);
  attachInterrupt(digitalPinToInterrupt(encoderPinB), readEncoder, CHANGE);
}

void loop() {
  int switchState = digitalRead(switchPin);
  bool pirState = digitalRead(pirPin);
  Blynk.run();
  
  if (switchState == HIGH) {
    lcd.setCursor(0, 0);
    lcd.print("Mesin Hidup");
    lcd.setCursor(0, 0);
    lcd.print("           ");
    lcd1.print(0,0, "Mesin Hidup");
    Blynk.logEvent("mesin", "Mesin Hidup");
    
    if (pirState == HIGH) {
      lcd.setCursor(0, 1);
      lcd.print("Ada Maling");
      lcd1.print(0,1, "Ada Maling");
      Blynk.logEvent("maling", "Ada Maling");
      
      // Menyalakan buzzer
      tone(buzzerPin, 1000);
      
      // Menyalakan LED merah
      digitalWrite(ledPin, HIGH);
      
      // Mengunci servo
      servoLocked = true;
      
      delay(5000); // Tunggu selama 5 detik
      
      // Mematikan buzzer
      noTone(buzzerPin);
    } else {
      // Mematikan LED merah
      digitalWrite(ledPin, LOW);
      lcd.setCursor(0,1);
      lcd.print("           " );
      lcd1.print(0,1,"           ");
      // Membuka kunci servo
      servoLocked = false;
    }
    
    if (servoLocked) {
      // Menghubungkan kembali servo jika terkunci
      servo.attach(servoPin);
    } else {
      if (encoderValue != previousEncoderValue) {
        // Menggerakkan servo hanya jika encoder berputar searah jarum jam
        if (encoderValue > previousEncoderValue) {
          int servoPosition = map(encoderValue, 0, 180, 0, 180);
          servo.write(servoPosition);

          // Memeriksa jika servo mencapai posisi 180 derajat
          if (servoPosition >= 180) {
            // Kembali ke posisi awal servo
            servo.write(0);

            // Mengatur nilai encoder kembali ke 0
            encoderValue = 0;
            previousEncoderValue = 0;

            // Meningkatkan hitungan reset
            resetCount++;

            // Memeriksa jika servo telah kembali ke posisi awal sebanyak 4 kali
            if (resetCount >= 4) {
              // Mengunci servo
              servoLocked = true;

              // Menyalakan LED
              digitalWrite(ledPin, HIGH);

              // Menghidupkan buzzer
              tone(buzzerPin, 250);
            }
          }
        } else {
          // Memeriksa jika servo bergerak searah berlawanan jarum jam
          int servoPosition = map(encoderValue, 0, 180, 0, 180);
          servo.write(servoPosition);

          // Memeriksa jika servo mencapai posisi 0 derajat
          if (servoPosition <= 0) {
            // Kembali ke posisi maksimal servo
            servo.write(180);

            // Mengatur nilai encoder kembali ke 0
            encoderValue = 0;
            previousEncoderValue = 0;

            // Meningkatkan hitungan reset
            resetCount++;

            // Memeriksa jika servo telah kembali ke posisi awal sebanyak 4 kali
            if (resetCount >= 4) {
              // Mengunci servo
              servoLocked = true;

              // Menyalakan LED
              digitalWrite(ledPin, HIGH);

              // Menghidupkan buzzer
              tone(buzzerPin, 250);
            }
          }
        }
      }
      
      // Menyimpan nilai encoder sebelumnya
      previousEncoderValue = encoderValue;
    }
  } else {
    lcd.setCursor(0, 0);
    lcd.print("Mesin Mati");
    lcd.setCursor(0, 1);
    lcd.print("           ");
    lcd1.print(0,0, "Mesin Mati");
    Blynk.logEvent("mesin", "Mesin Mati");

    // Mematikan buzzer
    noTone(buzzerPin);

    // Mematikan LED merah
    digitalWrite(ledPin, LOW);

    // Membuka kunci servo
    servoLocked = false;

    // Reset semua nilai jika sistem dimatikan
    encoderValue = 0;
    previousEncoderValue = 0;
    resetCount = 0;
    servo.detach();
  }
}

void readEncoder() {
  int MSB = digitalRead(encoderPinA);
  int LSB = digitalRead(encoderPinB);

  int encoded = (MSB << 1) | LSB;
  int sum = (lastEncoded << 2) | encoded;

  if (sum == 0b1101 || sum == 0b0100 || sum == 0b0010 || sum == 0b1011) {
    encoderValue++;
  } else if (sum == 0b1110 || sum == 0b0111 || sum == 0b0001 || sum == 0b1000) {
    encoderValue--;
  }

  lastEncoded = encoded;
}
$abcdeabcde151015202530354045505560fghijfghij