#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <Keypad.h>
#include <OneWire.h>
#include <DallasTemperature.h>
#define RELAY_PIN 12 // Pin relay untuk pemanas air
#define ONE_WIRE_BUS 10 // Pin sensor suhu
#define LED_KEYPAD 13 // Pin LED yang menyala saat keypad ditekan
LiquidCrystal_I2C lcd(0x27, 16, 2);
const byte numRows = 4;
const byte numCols = 4;
char keymap[numRows][numCols] = {
{'1', '2', '3', 'A'},
{'4', '5', '6', 'B'},
{'7', '8', '9', 'C'},
{'*', '0', '#', 'D'}
};
byte rowPins[numRows] = {9, 8, 7, 6};
byte colPins[numCols] = {5, 4, 3, 2};
Keypad myKeypad = Keypad(makeKeymap(keymap), rowPins, colPins, numRows, numCols);
String inputBuffer = "";
OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature sensors(&oneWire);
// Fungsi keanggotaan suhu
double suhuRendah(double x) {
if (x >= 20 && x <= 50) return 1.0;
else if (x > 50 && x <= 60) return (60 - x) / 10.0;
else return 0.0;
}
double suhuSedang(double x) {
if (x >= 50 && x <= 65) return (x - 50) / 15.0;
else if (x > 65 && x <= 80) return (80 - x) / 15.0;
else return 0.0;
}
double suhuTinggi(double x) {
if (x >= 70 && x <= 80) return (x - 70) / 10.0;
else if (x > 80 && x <= 100) return 1.0;
else return 0.0;
}
// Fungsi keanggotaan berat telur
double beratRingan(double x) {
if (x >= 30 && x <= 40) return 1.0;
else if (x > 40 && x <= 50) return (50 - x) / 10.0;
else return 0.0;
}
double beratSedang(double x) {
if (x >= 40 && x <= 55) return (x - 40) / 15.0;
else if (x > 55 && x <= 70) return (70 - x) / 15.0;
else return 0.0;
}
double beratBerat(double x) {
if (x >= 60 && x <= 70) return (x - 60) / 10.0;
else if (x > 70 && x <= 80) return 1.0;
else return 0.0;
}
// Fungsi inferensi fuzzy
double inferensi(double suhu, double berat) {
double r1 = fmin(suhuRendah(suhu), beratRingan(berat)); // Cepat
double r2 = fmin(suhuRendah(suhu), beratSedang(berat)); // Sedang
double r3 = fmin(suhuRendah(suhu), beratBerat(berat)); // Lama
double r4 = fmin(suhuSedang(suhu), beratRingan(berat)); // Cepat
double r5 = fmin(suhuSedang(suhu), beratSedang(berat)); // Sedang
double r6 = fmin(suhuSedang(suhu), beratBerat(berat)); // Lama
double r7 = fmin(suhuTinggi(suhu), beratRingan(berat)); // Cepat
double r8 = fmin(suhuTinggi(suhu), beratSedang(berat)); // Sedang
double r9 = fmin(suhuTinggi(suhu), beratBerat(berat)); // Lama
double cepat = fmax(fmax(r1, r4), r7) * 240; // 4 menit
double sedang = fmax(fmax(r2, r5), r8) * 540; // 9 menit
double lama = fmax(fmax(r3, r6), r9) * 660; // 11 menit
double totalBobot = (r1 + r4 + r7) + (r2 + r5 + r8) + (r3 + r6 + r9);
if (totalBobot == 0) return 660; // Default waktu jika tidak ada aturan aktif (11 menit)
return (cepat + sedang + lama) / totalBobot;
}
void setup() {
Serial.begin(115200);
pinMode(LED_KEYPAD, OUTPUT);
pinMode(RELAY_PIN, OUTPUT);
lcd.init();
lcd.backlight();
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Masukkan Berat:");
sensors.begin();
digitalWrite(RELAY_PIN, LOW);
}
void loop() {
char keypressed = myKeypad.getKey();
if (keypressed != NO_KEY) {
digitalWrite(LED_KEYPAD, HIGH);
delay(100);
digitalWrite(LED_KEYPAD, LOW);
if (keypressed == '#') {
inputBuffer = "";
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Masukkan Berat:");
}
else if (keypressed == '*') {
float beratTelur = inputBuffer.toFloat();
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Berat: ");
lcd.print(beratTelur);
lcd.print("g");
inputBuffer = "";
sensors.requestTemperatures();
float suhuAir = sensors.getTempCByIndex(0);
int waktuRebus = inferensi(suhuAir, beratTelur);
lcd.setCursor(0, 1);
lcd.print("Rebus: ");
lcd.print(waktuRebus);
lcd.print(" dtk");
digitalWrite(RELAY_PIN, HIGH);
for (int i = waktuRebus; i >= 0; i--) {
lcd.setCursor(0, 1);
lcd.print("Sisa: ");
lcd.print(i);
lcd.print(" dtk ");
delay(1000);
}
digitalWrite(RELAY_PIN, LOW);
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Rebusan Selesai");
lcd.setCursor(0, 1);
lcd.print("Ambil Telur!");
}
else {
inputBuffer += keypressed;
lcd.setCursor(0, 1);
lcd.print(inputBuffer);
}
}
}