#define BLYNK_TEMPLATE_ID "TMPL6WQS1OD6n"
#define BLYNK_TEMPLATE_NAME "PROJECT SENSOR GISTRIN"
#include <Arduino.h>
#include <ESP32Servo.h>
#include <DHT.h>
#include <Wire.h>
#include <WiFi.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <BlynkSimpleEsp32.h>
// Token Blynk
char auth[] = "hU3WGPLkQ7sJ234suofZjWsYB5MeZ7QV";
// WiFi
char ssid[] = "Wokwi-GUEST";
char pass[] = "";
// Pin Sensor dan Komponen
#define TRIGGER_PIN 5
#define ECHO_PIN 18
#define DHT_PIN 12
#define PIR_PIN 34
#define SERVO_PIN 13
#define LED_STATUS 16
#define LED_MOTION 17
// OLED
#define OLED_SDA 21
#define OLED_SCL 22
#define OLED_RESET -1
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
#define OLED_ADDR 0x3C
// Batasan dan waktu
#define JARAK_THRESHOLD 30
#define DEBOUNCE_TIME 200
// Objek
DHT dht(DHT_PIN, DHT22);
Servo servo;
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
BlynkTimer timer;
// Variabel
float suhu = 0, kelembaban = 0;
long jarak = 0;
bool gerakanDeteksi = false;
bool kucingTerdeteksi = false;
unsigned long waktuTerakhirDeteksi = 0;
unsigned long lastPirDetection = 0;
String statusSistem = "Normal";
BLYNK_WRITE(V0) {
int posisiServo = param.asInt();
servo.write(posisiServo);
}
// Kirim data ke Blynk
void kirimDataKeBlynk() {
Blynk.virtualWrite(V1, suhu);
Blynk.virtualWrite(V2, kelembaban);
Blynk.virtualWrite(V3, jarak);
Blynk.virtualWrite(V4, gerakanDeteksi ? 1 : 0);
Blynk.virtualWrite(V5, kucingTerdeteksi ? 1 : 0);
}
// Baca sensor jarak
void bacaSensorJarak() {
digitalWrite(TRIGGER_PIN, LOW);
delayMicroseconds(2);
digitalWrite(TRIGGER_PIN, HIGH);
delayMicroseconds(10);
digitalWrite(TRIGGER_PIN, LOW);
long durasi = pulseIn(ECHO_PIN, HIGH);
jarak = durasi * 0.034 / 2;
}
// Baca suhu & kelembaban
void bacaSensorDHT() {
float newTemp = dht.readTemperature();
float newHum = dht.readHumidity();
if (!isnan(newTemp)) suhu = newTemp;
if (!isnan(newHum)) kelembaban = newHum;
}
// Cek gerakan dengan debounce
bool cekGerakan() {
static bool lastState = false;
static unsigned long lastDebounceTime = 0;
bool currentState = digitalRead(PIR_PIN) == HIGH;
if (currentState != lastState) {
lastDebounceTime = millis();
}
if ((millis() - lastDebounceTime) > DEBOUNCE_TIME) {
if (currentState != gerakanDeteksi) {
gerakanDeteksi = currentState;
if (gerakanDeteksi) {
lastPirDetection = millis();
}
}
}
lastState = currentState;
return gerakanDeteksi;
}
// OLED
void updateDisplay() {
display.clearDisplay();
display.setCursor(0, 0);
display.print("Suhu: ");
display.print(suhu, 1);
display.println("°C");
display.print("Kelembaban: ");
display.print(kelembaban, 1);
display.println("%");
display.print("Jarak: ");
display.print(jarak);
display.println("cm");
display.print("Gerakan: ");
display.println(gerakanDeteksi ? "Ya" : "Tidak");
display.setCursor(0, 50);
display.print("Status: ");
display.println(statusSistem);
display.display();
}
void setup() {
Serial.begin(115200);
// GPIO
pinMode(TRIGGER_PIN, OUTPUT);
pinMode(ECHO_PIN, INPUT);
pinMode(LED_STATUS, OUTPUT);
pinMode(LED_MOTION, OUTPUT);
pinMode(PIR_PIN, INPUT);
// Inisialisasi
dht.begin();
servo.attach(SERVO_PIN);
// OLED
Wire.begin(OLED_SDA, OLED_SCL);
if (!display.begin(SSD1306_SWITCHCAPVCC, OLED_ADDR)) {
Serial.println("OLED Gagal");
while (1);
}
display.clearDisplay();
display.setTextSize(1);
display.setTextColor(WHITE);
display.setCursor(0, 0);
display.println("Feeder Kucing Siap");
display.display();
delay(2000);
// Blynk
Blynk.begin(auth, ssid, pass);
timer.setInterval(3000L, kirimDataKeBlynk);
}
void loop() {
Blynk.run();
timer.run();
// Sensor
bacaSensorJarak();
bacaSensorDHT();
cekGerakan();
// LED gerakan
digitalWrite(LED_MOTION, gerakanDeteksi ? HIGH : LOW);
// Deteksi kucing
if (jarak < JARAK_THRESHOLD && gerakanDeteksi) {
if (!kucingTerdeteksi) {
kucingTerdeteksi = true;
waktuTerakhirDeteksi = millis();
statusSistem = "Kucing Terdeteksi!";
servo.write(90);
digitalWrite(LED_STATUS, HIGH);
Blynk.logEvent("kucing_datang", "Kucing sedang makan!");
}
} else {
if (kucingTerdeteksi && (millis() - waktuTerakhirDeteksi > 5000)) {
kucingTerdeteksi = false;
servo.write(0);
digitalWrite(LED_STATUS, LOW);
statusSistem = "Normal";
}
}
updateDisplay();
}