Tambahkan file baru
This commit is contained in:
parent
28edb0fe1b
commit
cc8fe8d30f
|
@ -0,0 +1,14 @@
|
|||
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||
#
|
||||
# Example OpenOCD configuration file for ESP32-WROVER-KIT board.
|
||||
#
|
||||
# For example, OpenOCD can be started for ESP32 debugging on
|
||||
#
|
||||
# openocd -f board/esp32-wrover-kit-3.3v.cfg
|
||||
#
|
||||
|
||||
# Source the JTAG interface configuration file
|
||||
source [find interface/ftdi/esp32_devkitj_v1.cfg]
|
||||
set ESP32_FLASH_VOLTAGE 3.3
|
||||
# Source the ESP32 configuration file
|
||||
source [find target/esp32.cfg]
|
|
@ -0,0 +1,19 @@
|
|||
{
|
||||
"name":"Arduino on ESP32",
|
||||
"toolchainPrefix":"xtensa-esp32-elf",
|
||||
"svdFile":"esp32.svd",
|
||||
"request":"attach",
|
||||
"postAttachCommands":[
|
||||
"set remote hardware-watchpoint-limit 2",
|
||||
"monitor reset halt",
|
||||
"monitor gdb_sync",
|
||||
"thb setup",
|
||||
"c"
|
||||
],
|
||||
"overrideRestartCommands":[
|
||||
"monitor reset halt",
|
||||
"monitor gdb_sync",
|
||||
"thb setup",
|
||||
"c"
|
||||
]
|
||||
}
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,325 @@
|
|||
#include <WiFi.h>
|
||||
#include <Wire.h>
|
||||
#include <Adafruit_AMG88xx.h>
|
||||
#include <Firebase_ESP_Client.h>
|
||||
#include <ESP32Servo.h>
|
||||
#include <HTTPClient.h>
|
||||
#include <ArduinoJson.h>
|
||||
#include <time.h>
|
||||
|
||||
// ====== WiFi ======
|
||||
#define WIFI_SSID "POCO F4"
|
||||
#define WIFI_PASSWORD "87654321"
|
||||
|
||||
// ====== Firebase RTDB ======
|
||||
#define API_KEY "AIzaSyDgtq_bU0aNjKwErdns50EldaRRSdd5Sg0"
|
||||
#define DATABASE_URL "https://hamaguard-e911d-default-rtdb.firebaseio.com"
|
||||
#define USER_EMAIL "test@gmail.com"
|
||||
#define USER_PASSWORD "123456"
|
||||
|
||||
// ====== REST API Endpoint ======
|
||||
const char* apiEndpoint = "https://service-hama-guard.vercel.app/api/notifikasi";
|
||||
|
||||
// ====== Pin ======
|
||||
#define PIR_PIN 33
|
||||
#define TRIG_PIN 25
|
||||
#define ECHO_PIN 26
|
||||
#define BUZZER_PIN 13
|
||||
#define SERVO_PIN 32
|
||||
|
||||
// ====== Firebase Objects ======
|
||||
FirebaseData fbdo;
|
||||
FirebaseAuth auth;
|
||||
FirebaseConfig config;
|
||||
|
||||
// ====== Sensor & Servo ======
|
||||
Adafruit_AMG88xx amg;
|
||||
float pixels[AMG88xx_PIXEL_ARRAY_SIZE];
|
||||
Servo servo;
|
||||
|
||||
// ====== Kalibrasi AMG8833 ======
|
||||
const float amgOffset = 2,94 ;
|
||||
|
||||
// ====== Control Flags ======
|
||||
bool isAutoMode = true;
|
||||
bool isRepellerOn = false;
|
||||
String prevMode = "";
|
||||
|
||||
// ====== Timing Control ======
|
||||
unsigned long lastSensorSend = 0;
|
||||
unsigned long lastNotifSend = 0;
|
||||
unsigned long humanBuzzEndTime = 0;
|
||||
const unsigned long SENSOR_INTERVAL = 1000;
|
||||
const unsigned long NOTIF_INTERVAL = 5000;
|
||||
|
||||
// ====== Repeller Task Control ======
|
||||
TaskHandle_t repellerTaskHandle = NULL;
|
||||
bool repellerActive = false;
|
||||
unsigned long repellerEndTime = 0;
|
||||
|
||||
// ====== FreeRTOS Servo Task ======
|
||||
void repellerTask(void* parameter) {
|
||||
static int pos = 0;
|
||||
static bool forward = true;
|
||||
const int step = 6;
|
||||
const int delayMs = 10;
|
||||
|
||||
while (true) {
|
||||
if (repellerActive) {
|
||||
digitalWrite(BUZZER_PIN, HIGH);
|
||||
servo.write(pos);
|
||||
if (forward) {
|
||||
pos += step;
|
||||
if (pos >= 180) {
|
||||
pos = 180;
|
||||
forward = false;
|
||||
}
|
||||
} else {
|
||||
pos -= step;
|
||||
if (pos <= 0) {
|
||||
pos = 0;
|
||||
forward = true;
|
||||
}
|
||||
}
|
||||
vTaskDelay(delayMs / portTICK_PERIOD_MS);
|
||||
} else {
|
||||
digitalWrite(BUZZER_PIN, LOW);
|
||||
servo.write(90);
|
||||
vTaskDelay(10 / portTICK_PERIOD_MS);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void setupTime() {
|
||||
configTime(7 * 3600, 0, "pool.ntp.org", "time.nist.gov");
|
||||
Serial.print("Sinkronisasi waktu NTP");
|
||||
while (time(nullptr) < 8 * 3600 * 2) {
|
||||
delay(500);
|
||||
Serial.print(".");
|
||||
}
|
||||
Serial.println(" ✓");
|
||||
}
|
||||
|
||||
String getISO8601Timestamp() {
|
||||
time_t now = time(nullptr);
|
||||
struct tm timeinfo;
|
||||
localtime_r(&now, &timeinfo);
|
||||
char buf[30];
|
||||
strftime(buf, sizeof(buf), "%Y-%m-%dT%H:%M:%S%z", &timeinfo);
|
||||
return String(buf);
|
||||
}
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
delay(500);
|
||||
Serial.print("Menghubungkan ke WiFi");
|
||||
|
||||
WiFi.mode(WIFI_STA);
|
||||
WiFi.begin(WIFI_SSID, WIFI_PASSWORD);
|
||||
|
||||
int retry = 0;
|
||||
while (WiFi.status() != WL_CONNECTED && retry < 20) {
|
||||
delay(500);
|
||||
Serial.print(".");
|
||||
retry++;
|
||||
}
|
||||
|
||||
if (WiFi.status() == WL_CONNECTED) {
|
||||
Serial.println(" ✓");
|
||||
Serial.println("WiFi terhubung ke: " + String(WiFi.SSID()));
|
||||
Serial.println("IP Address: " + WiFi.localIP().toString());
|
||||
} else {
|
||||
Serial.println(" ✗");
|
||||
Serial.println("Gagal terhubung ke WiFi. Periksa SSID/Password.");
|
||||
}
|
||||
|
||||
setupTime();
|
||||
|
||||
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);
|
||||
|
||||
delay(1000);
|
||||
if (Firebase.ready()) {
|
||||
Serial.println("Firebase terhubung ✓");
|
||||
} else {
|
||||
Serial.println("Firebase tidak terhubung ✗");
|
||||
}
|
||||
|
||||
pinMode(PIR_PIN, INPUT);
|
||||
pinMode(TRIG_PIN, OUTPUT);
|
||||
pinMode(ECHO_PIN, INPUT);
|
||||
pinMode(BUZZER_PIN, OUTPUT);
|
||||
digitalWrite(BUZZER_PIN, LOW);
|
||||
|
||||
servo.attach(SERVO_PIN);
|
||||
servo.write(90);
|
||||
|
||||
if (!amg.begin()) {
|
||||
Serial.println("Sensor AMG8833 tidak ditemukan!");
|
||||
while (1) delay(10);
|
||||
} else {
|
||||
Serial.println("Sensor AMG8833 berhasil diinisialisasi.");
|
||||
}
|
||||
|
||||
xTaskCreatePinnedToCore(repellerTask, "RepellerTask", 2048, NULL, 1, &repellerTaskHandle, 1);
|
||||
Serial.println("Setup selesai. Sistem siap berjalan.");
|
||||
}
|
||||
|
||||
String classifyObject(float distance, float maxTemp, int hotGridCount) {
|
||||
if ((distance <= 5 && maxTemp >= 41 && hotGridCount >= 9 && hotGridCount <= 14) ||
|
||||
(distance <= 10 && maxTemp >= 37-39 && hotGridCount >= 3 && hotGridCount <= 4)) {
|
||||
return "burung";
|
||||
}
|
||||
if ((distance <= 5 && maxTemp >= 36 && maxTemp <= 37 && hotGridCount >= 64) ||
|
||||
((distance >= 10 && distance <= 35) && maxTemp >= 36 && maxTemp <= 28 && hotGridCount >= 12 && hotGridCount <= 30) ||
|
||||
(distance <= 30 && maxTemp == 35 && hotGridCount >= 15 && hotGridCount <= 20)) {
|
||||
return "manusia";
|
||||
}
|
||||
if (maxTemp >= 36.0) {
|
||||
return "hama_unknown";
|
||||
}
|
||||
return "tidak_terdeteksi";
|
||||
}
|
||||
|
||||
void loop() {
|
||||
if (WiFi.status() != WL_CONNECTED) {
|
||||
Serial.println("WiFi terputus. Mencoba reconnect...");
|
||||
WiFi.disconnect();
|
||||
WiFi.reconnect();
|
||||
unsigned long startAttemptTime = millis();
|
||||
while (WiFi.status() != WL_CONNECTED && millis() - startAttemptTime < 10000) {
|
||||
delay(500);
|
||||
Serial.print(".");
|
||||
}
|
||||
if (WiFi.status() == WL_CONNECTED) {
|
||||
Serial.println("\nWiFi berhasil terhubung kembali!");
|
||||
} else {
|
||||
Serial.println("\nGagal reconnect ke WiFi.");
|
||||
}
|
||||
}
|
||||
|
||||
unsigned long now = millis();
|
||||
|
||||
if (Firebase.RTDB.getString(&fbdo, "/control/mode")) {
|
||||
String mode = fbdo.stringData();
|
||||
isAutoMode = (mode == "auto");
|
||||
if (mode != prevMode) {
|
||||
sendModeChangeNotification(isAutoMode ? "Otomatis" : "Manual");
|
||||
prevMode = mode;
|
||||
}
|
||||
}
|
||||
|
||||
if (Firebase.RTDB.getBool(&fbdo, "/control/repeller")) {
|
||||
isRepellerOn = fbdo.boolData();
|
||||
}
|
||||
|
||||
if (!isAutoMode) {
|
||||
repellerActive = isRepellerOn;
|
||||
return;
|
||||
}
|
||||
|
||||
amg.readPixels(pixels);
|
||||
float maxTemp = -100;
|
||||
int hotGridCount = 0;
|
||||
for (int i = 0; i < AMG88xx_PIXEL_ARRAY_SIZE; i++) {
|
||||
pixels[i] += amgOffset;
|
||||
if (pixels[i] > maxTemp) maxTemp = pixels[i];
|
||||
if (pixels[i] > 23.0) hotGridCount++;
|
||||
}
|
||||
|
||||
bool pirDetected = digitalRead(PIR_PIN) == HIGH;
|
||||
|
||||
digitalWrite(TRIG_PIN, LOW); delayMicroseconds(2);
|
||||
digitalWrite(TRIG_PIN, HIGH); delayMicroseconds(10);
|
||||
digitalWrite(TRIG_PIN, LOW);
|
||||
long duration = pulseIn(ECHO_PIN, HIGH);
|
||||
float distance_cm = duration * 0.034 / 2.0;
|
||||
|
||||
String jenis = classifyObject(distance_cm, maxTemp, hotGridCount);
|
||||
bool classified = (jenis != "tidak_terdeteksi");
|
||||
|
||||
// === Logika pengusir berdasarkan klasifikasi ===
|
||||
if (pirDetected || jenis == "burung" || jenis == "ayam" || jenis == "hama_unknown") {
|
||||
repellerActive = true;
|
||||
repellerEndTime = millis() + 10000;
|
||||
} else if (jenis == "manusia") {
|
||||
repellerActive = false;
|
||||
digitalWrite(BUZZER_PIN, HIGH);
|
||||
humanBuzzEndTime = millis() + 10000;
|
||||
}
|
||||
|
||||
if (repellerActive && millis() > repellerEndTime) {
|
||||
repellerActive = false;
|
||||
}
|
||||
|
||||
if (jenis == "manusia" && millis() > humanBuzzEndTime) {
|
||||
digitalWrite(BUZZER_PIN, LOW);
|
||||
}
|
||||
|
||||
if (now - lastSensorSend >= SENSOR_INTERVAL) {
|
||||
sendSensorData(pirDetected, distance_cm, jenis, maxTemp);
|
||||
lastSensorSend = now;
|
||||
}
|
||||
|
||||
if ((now - lastNotifSend >= NOTIF_INTERVAL) && classified) {
|
||||
sendNotification(jenis, distance_cm, maxTemp);
|
||||
lastNotifSend = now;
|
||||
}
|
||||
}
|
||||
|
||||
void sendSensorData(bool pir, float dist, String jenis, float maxTemp) {
|
||||
if (!Firebase.ready()) return;
|
||||
FirebaseJson sensorJson;
|
||||
sensorJson.set("pir", pir);
|
||||
sensorJson.set("ultrasonik", dist);
|
||||
sensorJson.set("jenis_deteksi", jenis);
|
||||
sensorJson.set("pengusir", (jenis != "tidak_terdeteksi"));
|
||||
sensorJson.set("timestamp", millis());
|
||||
|
||||
FirebaseJson thermalJson;
|
||||
FirebaseJsonArray arr;
|
||||
for (int i = 0; i < AMG88xx_PIXEL_ARRAY_SIZE; i++) arr.add(pixels[i]);
|
||||
thermalJson.set("temperatures", arr);
|
||||
thermalJson.set("timestamp", millis());
|
||||
|
||||
Firebase.RTDB.setJSON(&fbdo, "/sensor", &sensorJson);
|
||||
Firebase.RTDB.setJSON(&fbdo, "/thermal_data", &thermalJson);
|
||||
}
|
||||
|
||||
void sendNotification(String jenis, float distance, float suhu) {
|
||||
HTTPClient http;
|
||||
http.begin(apiEndpoint);
|
||||
http.addHeader("Content-Type", "application/json");
|
||||
|
||||
DynamicJsonDocument json(512);
|
||||
json["type"] = "warning";
|
||||
json["title"] = "Deteksi " + jenis;
|
||||
json["message"] = "Terdeteksi " + jenis + " pada jarak " + String(distance, 1) + " cm dan suhu maksimum " + String(suhu, 1) + "°C";
|
||||
json["timestamp"] = getISO8601Timestamp();
|
||||
|
||||
String requestBody;
|
||||
serializeJson(json, requestBody);
|
||||
http.POST(requestBody);
|
||||
http.end();
|
||||
}
|
||||
|
||||
void sendModeChangeNotification(String mode) {
|
||||
HTTPClient http;
|
||||
http.begin(apiEndpoint);
|
||||
http.addHeader("Content-Type", "application/json");
|
||||
|
||||
DynamicJsonDocument json(512);
|
||||
json["type"] = "success";
|
||||
json["title"] = "Mode Diganti";
|
||||
json["message"] = "Mode sistem diganti menjadi " + mode;
|
||||
json["timestamp"] = getISO8601Timestamp();
|
||||
|
||||
String body;
|
||||
serializeJson(json, body);
|
||||
http.POST(body);
|
||||
http.end();
|
||||
}
|
Loading…
Reference in New Issue