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

#define jarakSensor 12
#define echoSensor 14
#define trigerSensor 27
LiquidCrystal_I2C lcd(0x27, 16, 2);

float jarakDekat(float x) {
  if (x <= 50) return 1.0;
  else if (x > 50 && x <= 100) return (100 - x) / 50;
  else return 0.0;
}

float jarakSedang(float x) {
  if (x <= 50) return 0.0;
  else if (x > 50 && x <= 100) return (x-50) / 50;
  else if (x > 100 && x <= 150) return (150-x) / 50;
  else return 0.0;
}

float jarakJauh(float x) {
  if (x <= 100) return 0.0;
  if (x > 100 && x <= 150) return (x-100) / 50;
  else return 1.0;
}

float kecepatanLambat(float x) {
  if (x <= 30) return 1.0;
  else if (x > 30 && x <= 50) return (50 - x) / 10;
  else return 0.0;
}

float KecepatanStabil(float x) {
  if (x <= 30) return 0.0;
  else if (x > 50 && x <= 50) return (x - 30) / 10;
  else if (x > 50 && x <= 70) return (70 - x) / 10;
  else return 0.0;
}

float KecepatanCepat(float x) {
  if (x <= 50) return 0.0;
  if (x > 50 && x <= 70) return (x - 50) / 10;
  else return 1.0;
}

// Fungsi defuzzifikasi untuk menghitung output berdasarkan suhu dan konsentrasi gas
float defuzzifikasi(float jarak, float kecepatan) {
  float dekat = jarakDekat(jarak);
  float sedang = jarakSedang(jarak);
  float jauh = jarakJauh(jarak);
  float lambat = kecepatanLambat(kecepatan);
  float stabil = kecepatanStabil(kecepatan);
  float cepat = kecepatanCepat(kecepatan);

  // Inferensi fuzzy untuk menentukan kondisi aman atau bahaya
float buka = max(
  max(min(sedang, lambat), min(jauh, lambat),
  min(jauh, stabil))
);

float tutup = max(
  max(min(dekat, lambat), min(dekat, stabil),min(dekat, cepat)),
  max (min(sedang, stabil), min(sedang,cepat),min(jauh,cepat))
);

// tutup = aman, buka = bahaya
  float t1 = tutup * 120 + 80;
  float t2 = buka * 120 + 80;

  float m1 = (tutup * (t1 * t1 / 2)) - (tutup * (0 * 0 /2));
  float m2 = (((t2 * t2 * t2/3)-(750 * (t2 * t2))/2)/120)-(((t1 * t1 * t1/3)-(750 * (t1 * t1))/2)/120);
  float m3 = (buka * (200 * 200 / 2)) - (buka * (t2 * t2 / 2));

  float a1 = (tutup * t1)-(tutup * 0);
  float a2 = ((((t2 * t2)/2)-(750 * t2))/120)-((((t1 * t1)/2)-(750 * t1))/120);
  float a3 = (buka * 200)-(buka * t2);

  float z = (m1 + m2 + m3)/(a1 + a2 + a3);

  return z;

}

void setup() {
  // put your setup code here, to run once:
  Serial.begin(115200);
  Serial.println("Hello, ESP32!");
  lcd.init();
  lcd.backlight();
  
}

void loop() {
// Membaca nilai analog dari sensor
  int analogGas = analogRead(gasSensor);
  int analogSuhu = analogRead(suhuSensor);

  // Mengonversi nilai analog ke rentang logis
  float konsentrasi = map(analogGas, 0, 4095, 0, 2500);  // Rentang konsentrasi gas 0-2500 ppm
  float suhu = map(analogSuhu, 0, 4095, 0, 45);           // Rentang suhu 0-45 derajat C

  float nilaiDefuzzifikasi = defuzzifikasi(suhu, konsentrasi);

  lcd.setCursor(0, 0);
  lcd.print("Output Kebocoran :");
  lcd.setCursor(0, 1);
  lcd.print(nilaiDefuzzifikasi);
  lcd.print(" ppm");

  Serial.print("Suhu :");
  Serial.println(suhu);
  Serial.print("Konsentrasi Gas :");
  Serial.println(konsentrasi);
  Serial.print("Kebocoran Gas :");
  Serial.print(nilaiDefuzzifikasi);
  Serial.println(" ppm");


  delay(1000);
}