Pengusir-Hama-Burung-Otomatis/codingan projek TA/sketch_feb24a/sketch_feb24a.ino

846 lines
16 KiB
C++

// ======================================================
// LIBRARY
// ======================================================
#include <WiFi.h>
#include <Firebase_ESP_Client.h>
#include <ESP32Servo.h>
#include "time.h"
// ======================================================
// WIFI
// ======================================================
#define WIFI_SSID "siip"
#define WIFI_PASSWORD "mbayardulu"
// ======================================================
// FIREBASE
// ======================================================
#define API_KEY "AIzaSyDwXyctX6eQSoUNBsMbD2CzbeVekdOuBdI"
#define DATABASE_URL "https://tugas-akhir-9947b-default-rtdb.asia-southeast1.firebasedatabase.app/"
#define USER_EMAIL "chika@gmail.com"
#define USER_PASSWORD "chika123"
FirebaseData fbdo;
FirebaseAuth auth;
FirebaseConfig config;
// ======================================================
// PIN
// ======================================================
const int pirPin1 = 32;
const int pirPin2 = 21;
const int trigPin = 4;
const int echoPin = 18;
const int buzzerPin = 14;
const int servoPin1 = 25;
const int servoPin2 = 26;
const int servoPin3 = 27;
const int soundPin = 33;
// ======================================================
// SERVO
// ======================================================
Servo servo1;
Servo servo2;
Servo servo3;
// ======================================================
// VARIABLE
// ======================================================
unsigned long lastTrigger = 0;
unsigned long lastFirebase = 0;
unsigned long lastMotionTime = 0;
unsigned long lastAIRead = 0;
unsigned long lastHistoryTime = 0;
const unsigned long cooldown = 8000;
const unsigned long pirHoldTime = 700;
const unsigned long historyCooldown = 12000;
String hasilAI = "tidak dikenal";
String lastStatus = "Aman";
int validCounter = 0;
long lastDistance = 0;
float lastSoundDB = 35;
String lastDeteksi = "tidak dikenal";
long savedDistance = 0;
float savedSoundDB = 0;
String savedDeteksi = "tidak dikenal";
// ======================================================
// UPDATE STATUS
// ======================================================
void updateStatus(String statusBaru) {
if (!Firebase.ready()) return;
if (statusBaru != lastStatus) {
Firebase.RTDB.setString(
&fbdo,
"/Kebun/Status",
statusBaru
);
lastStatus = statusBaru;
}
}
// ======================================================
// FORMAT WAKTU
// ======================================================
String getFormattedTime() {
struct tm timeinfo;
if (!getLocalTime(&timeinfo)) {
return "Waktu Error";
}
char buffer[30];
strftime(
buffer,
sizeof(buffer),
"%d-%m-%Y %H:%M:%S",
&timeinfo
);
return String(buffer);
}
// ======================================================
// SIMPAN HISTORY
// ======================================================
void simpanRiwayatDeteksi() {
if (
lastSoundDB <= 0 ||
lastDistance <= 2 ||
lastDistance > 60
) {
return;
}
FirebaseJson json;
// ==========================
// SENSOR PEMICU
// ==========================
String sensorPemicu = "-";
if (digitalRead(pirPin1) == HIGH &&
digitalRead(pirPin2) == HIGH) {
sensorPemicu = "PIR 1 & PIR 2";
}
else if (digitalRead(pirPin1) == HIGH) {
sensorPemicu = "PIR 1";
}
else if (digitalRead(pirPin2) == HIGH) {
sensorPemicu = "PIR 2";
}
json.set("sensor_pemicu", sensorPemicu);
// ==========================
// DATA RIWAYAT
// ==========================
json.set("jarak", lastDistance);
json.set("db", lastSoundDB);
json.set("deteksi", "burung");
json.set("pir1", digitalRead(pirPin1));
json.set("pir2", digitalRead(pirPin2));
json.set("waktu", getFormattedTime());
Firebase.RTDB.pushJSON(
&fbdo,
"/Kebun/Riwayat",
&json
);
}
// ======================================================
// SETUP
// ======================================================
void setup() {
Serial.begin(115200);
delay(2000);
// WARMUP PIR
delay(5000);
analogReadResolution(12);
analogSetPinAttenuation(
soundPin,
ADC_11db
);
// ====================================================
// PINMODE
// ====================================================
pinMode(pirPin1, INPUT_PULLDOWN); // Mengaktifkan pull-down internal
pinMode(pirPin2, INPUT_PULLDOWN); // Mengaktifkan pull-down internal
pinMode(soundPin, INPUT);
pinMode(buzzerPin, OUTPUT);
pinMode(trigPin, OUTPUT);
pinMode(echoPin, INPUT);
digitalWrite(buzzerPin, LOW);
// ====================================================
// SERVO DETACH
// ====================================================
servo1.detach();
servo2.detach();
servo3.detach();
// ====================================================
// WIFI
// ====================================================
WiFi.begin(WIFI_SSID, WIFI_PASSWORD);
WiFi.setSleep(false);
Serial.print("Menghubungkan WiFi");
while (WiFi.status() != WL_CONNECTED) {
Serial.print(".");
delay(300);
}
Serial.println();
Serial.println("WiFi Connected");
// ====================================================
// INTERNET TIME
// ====================================================
configTime(
7 * 3600,
0,
"pool.ntp.org"
);
// ====================================================
// FIREBASE
// ====================================================
config.api_key = API_KEY;
config.database_url = DATABASE_URL;
auth.user.email = USER_EMAIL;
auth.user.password = USER_PASSWORD;
Firebase.begin(&config, &auth);
Firebase.reconnectWiFi(true);
Serial.println("Firebase Connected");
updateStatus("Aman");
}
// ======================================================
// LOOP
// ======================================================
void loop() {
// ====================================================
// WIFI CHECK
// ====================================================
if (WiFi.status() != WL_CONNECTED) {
WiFi.disconnect();
WiFi.reconnect();
delay(1000);
return;
}
// ====================================================
// FIREBASE READY
// ====================================================
if (!Firebase.ready()) {
return;
}
// ====================================================
// PIR
// ====================================================
int pir1 = digitalRead(pirPin1);
int pir2 = digitalRead(pirPin2);
bool gerakan = false;
if (
pir1 == HIGH ||
pir2 == HIGH
) {
delay(80);
if (
digitalRead(pirPin1) == HIGH ||
digitalRead(pirPin2) == HIGH
) {
gerakan = true;
lastMotionTime = millis();
}
}
// ====================================================
// HOLD PIR
// ====================================================
if (
millis() - lastMotionTime
< pirHoldTime
) {
gerakan = true;
}
// ====================================================
// SENSOR
// ====================================================
long distance = getDistanceAverage();
float soundDB = getSoundDB();
lastDistance = distance;
lastSoundDB = soundDB;
// ====================================================
// VALIDASI
// ====================================================
bool jarakValid = false;
bool aiValid = false;
if (
distance > 2 &&
distance <= 60 // Batas maksimal sekarang 60 cm
) {
jarakValid = true;
}
// ====================================================
// AI
// ====================================================
if (millis() - lastAIRead > 1000) {
lastAIRead = millis();
if (
Firebase.RTDB.getString(
&fbdo,
"/Kebun/AI/Klasifikasi"
)
) {
hasilAI = fbdo.stringData();
hasilAI.trim();
hasilAI.toLowerCase();
if (gerakan) {
lastDeteksi = hasilAI;
} else {
lastDeteksi = "tidak dikenal";
}
}
}
if (hasilAI == "burung")
{
aiValid = true;
}
if (hasilAI == "burung" ||
hasilAI == "manusia")
{
savedDeteksi = hasilAI;
savedDistance = distance;
savedSoundDB = soundDB;
}
// ====================================================
// VALID COUNTER
// ====================================================
if (
gerakan &&
jarakValid &&
aiValid
) {
validCounter++;
} else {
validCounter = 0;
}
// ====================================================
// FIREBASE
// ====================================================
if (millis() - lastFirebase > 3000) {
lastFirebase = millis();
Firebase.RTDB.setInt(
&fbdo,
"/Kebun/Sensor/Jarak",
lastDistance
);
Firebase.RTDB.setFloat(
&fbdo,
"/Kebun/Sensor/Suara_dB",
lastSoundDB
);
// SIMPAN DETEKSI TERAKHIR YANG VALID
if (gerakan && hasilAI == "burung") {
savedDeteksi = "burung";
}
else if (gerakan && hasilAI == "manusia") {
savedDeteksi = "manusia";
}
String deteksiFirebase = savedDeteksi;
Serial.println("===== DEBUG FIREBASE =====");
Serial.print("Gerakan = ");
Serial.println(gerakan);
Serial.print("AI = ");
Serial.println(hasilAI);
Serial.print("deteksiFirebase = ");
Serial.println(deteksiFirebase);
Serial.println("==========================");
Firebase.RTDB.setString(
&fbdo,
"/Kebun/Sensor/Deteksi",
deteksiFirebase
);
// ==========================
// PIR 1
// ==========================
Firebase.RTDB.setInt(
&fbdo,
"/Kebun/Sensor/PIR1",
pir1
);
// ==========================
// PIR 2
// ==========================
Firebase.RTDB.setInt(
&fbdo,
"/Kebun/Sensor/PIR2",
pir2
);
Firebase.RTDB.setString(
&fbdo,
"/Kebun/Sensor/UpdateTerakhir",
getFormattedTime()
);
}
// ====================================================
// MODE
// ====================================================
int mode = 0;
if (
Firebase.RTDB.getInt(
&fbdo,
"/kontrol/mode"
)
) {
mode = fbdo.intData();
}
// ====================================================
// MODE OTOMATIS
// ====================================================
if (mode == 0) {
updateStatus("Otomatis");
if (
validCounter >= 1 &&
millis() - lastTrigger > cooldown &&
millis() - lastHistoryTime > historyCooldown
) {
lastTrigger = millis();
lastHistoryTime = millis();
updateStatus("Bahaya");
simpanRiwayatDeteksi();
aksiPengusiran();
validCounter = 0;
}
}
// ====================================================
// MODE MANUAL
// ====================================================
else {
updateStatus("Manual");
int buzzerManual = 0;
int servoManual = 0;
Firebase.RTDB.getInt(
&fbdo,
"/kontrol/buzzer"
);
buzzerManual = fbdo.intData();
Firebase.RTDB.getInt(
&fbdo,
"/kontrol/servo"
);
servoManual = fbdo.intData();
// ==================================================
// BUZZER MANUAL
// ==================================================
if (buzzerManual == 1) {
digitalWrite(buzzerPin, HIGH);
delay(5000);
digitalWrite(buzzerPin, LOW);
Firebase.RTDB.setInt(
&fbdo,
"/kontrol/buzzer",
0
);
}
// ==================================================
// SERVO MANUAL
// ==================================================
if (servoManual == 1) {
aksiServoOnly();
Firebase.RTDB.setInt(
&fbdo,
"/kontrol/servo",
0
);
}
}
// ====================================================
// SERIAL MONITOR
// ====================================================
Serial.println("========================");
Serial.print("PIR1: ");
Serial.println(pir1);
Serial.print("PIR2: ");
Serial.println(pir2);
Serial.print("Gerakan: ");
Serial.println(gerakan);
Serial.print("Jarak: ");
Serial.print(distance);
Serial.println(" cm");
Serial.print("dB: ");
Serial.println(soundDB);
Serial.print("AI: ");
Serial.println(hasilAI);
Serial.println("========================");
delay(100);
}
// ======================================================
// ULTRASONIK
// ======================================================
long getDistanceRaw() {
digitalWrite(trigPin, LOW);
delayMicroseconds(5);
digitalWrite(trigPin, HIGH);
delayMicroseconds(10);
digitalWrite(trigPin, LOW);
long duration =
pulseIn(echoPin, HIGH, 20000);
if (duration == 0) {
return -1;
}
long distance =
duration * 0.0343 / 2;
if (
distance < 2 ||
distance > 400
) {
return -1;
}
return distance;
}
// ======================================================
// ULTRASONIK FILTER
// ======================================================
long getDistanceAverage() {
long d1 = getDistanceRaw();
if (
d1 == -1 &&
lastDistance > 0
) {
d1 = lastDistance;
}
delay(3);
long d2 = getDistanceRaw();
if (
d2 == -1 &&
lastDistance > 0
) {
d2 = lastDistance;
}
delay(3);
long d3 = getDistanceRaw();
if (
d3 == -1 &&
lastDistance > 0
) {
d3 = lastDistance;
}
long values[3] = {d1, d2, d3};
for (int i = 0; i < 2; i++) {
for (int j = i + 1; j < 3; j++) {
if (values[j] < values[i]) {
long temp = values[i];
values[i] = values[j];
values[j] = temp;
}
}
}
return values[1];
}
// ======================================================
// SOUND SENSOR
// ======================================================
float getSoundDB() {
long total = 0;
const int samples = 50;
for (int i = 0; i < samples; i++) {
total += analogRead(soundPin);
delayMicroseconds(200);
}
float average = total / samples;
float noise = abs(average - 2048);
if (noise < 15) {
noise = 0;
}
float db =
25 + (noise / 18.0);
if (db > 75)
db = 75;
static float smoothDb = 35;
smoothDb =
(smoothDb * 0.75) +
(db * 0.25);
return smoothDb;
}
// ======================================================
// SERVO ONLY MANUAL
// ======================================================
void aksiServoOnly() {
servo1.attach(servoPin1);
servo2.attach(servoPin2);
servo3.attach(servoPin3);
unsigned long startTime = millis();
while (millis() - startTime < 30000) {
// ======================
// SERVO 1
// ======================
servo1.write(90);
delay(700);
servo1.write(0);
delay(300);
// ======================
// SERVO 2
// ======================
servo2.write(90);
delay(700);
servo2.write(0);
delay(300);
// ======================
// SERVO 3
// ======================
servo3.write(90);
delay(700);
servo3.write(0);
delay(300);
}
servo1.detach();
servo2.detach();
servo3.detach();
}
// ======================================================
// AKSI PENGUSIRAN OTOMATIS
// ======================================================
void aksiPengusiran() {
// =========================
// BUZZER DULU
// =========================
digitalWrite(buzzerPin, HIGH);
delay(3000);
digitalWrite(buzzerPin, LOW);
delay(300);
// =========================
// SERVO
// =========================
servo1.attach(servoPin1);
servo2.attach(servoPin2);
servo3.attach(servoPin3);
unsigned long startTime = millis();
while (millis() - startTime < 30000) {
// ======================
// SERVO 1
// ======================
servo1.write(90);
delay(700);
servo1.write(0);
delay(300);
// ======================
// SERVO 2
// ======================
servo2.write(90);
delay(700);
servo2.write(0);
delay(300);
// ======================
// SERVO 3
// ======================
servo3.write(90);
delay(700);
servo3.write(0);
delay(300);
}
servo1.detach();
servo2.detach();
servo3.detach();
}