285 lines
7.2 KiB
C++
285 lines
7.2 KiB
C++
#include <DHT.h>
|
|
#include <ThingerESP32.h>
|
|
#include <HX711.h>
|
|
#include <ESP32Servo.h>
|
|
#include <Ultrasonic.h>
|
|
#include <time.h>
|
|
|
|
#define DOUT_PIN 25
|
|
#define CLK_PIN 27
|
|
#define RELAY_PIN_2 18
|
|
#define RELAY_PIN_1 19
|
|
#define TRIGGER_PIN 12
|
|
#define ECHO_PIN 14
|
|
#define DHTPIN 23
|
|
#define DHTTYPE DHT11
|
|
#define USERNAME "btwnty"
|
|
#define DEVICE_ID "esp32"
|
|
#define DEVICE_CREDENTIAL "AfUm_FeJ@Zr@pIN?"
|
|
|
|
#define SSID "arya"
|
|
#define SSID_PASSWORD "12345678"
|
|
|
|
const char* ntpServer = "0.pool.ntp.org";
|
|
const long gmtOffset_sec = 6L * 60L * 60L;
|
|
const int daylightOffset_sec = 3600;
|
|
const long interval = 5000;
|
|
|
|
DHT dht(DHTPIN, DHTTYPE);
|
|
ThingerESP32 thing(USERNAME, DEVICE_ID, DEVICE_CREDENTIAL);
|
|
Servo myServo;
|
|
HX711 scale;
|
|
Ultrasonic ultrasonic(TRIGGER_PIN, ECHO_PIN);
|
|
|
|
unsigned long notifikasiterakhir = 0;
|
|
unsigned long conditionStartTime = 0;
|
|
bool relayActive1 = true;
|
|
bool relayActive2 = false;
|
|
unsigned long relay1StartTime = 0;
|
|
unsigned long relay2StartTime = 0;
|
|
|
|
const float bebanmax = 30.0;
|
|
const unsigned long durasiRelayAktif = 2500;
|
|
|
|
const float suhumin = 30;
|
|
const float suhumax = 35;
|
|
|
|
const int tinggiWadah = 20;
|
|
|
|
unsigned long bacaSensorTerakhir = 0;
|
|
const unsigned long bacaSensorInterval = 1000;
|
|
|
|
enum WiFiState { DISCONNECTED, CONNECTING, CONNECTED };
|
|
WiFiState wifiState = DISCONNECTED;
|
|
unsigned long wifiConnectStartTime = 0;
|
|
const unsigned long wifiReconectInterval = 5000;
|
|
|
|
void setup() {
|
|
Serial.begin(9600);
|
|
|
|
thing.add_wifi(SSID, SSID_PASSWORD);
|
|
|
|
myServo.attach(5);
|
|
myServo.write(0);
|
|
|
|
dht.begin();
|
|
|
|
pinMode(RELAY_PIN_2, OUTPUT);
|
|
pinMode(RELAY_PIN_1, OUTPUT);
|
|
|
|
digitalWrite(RELAY_PIN_2, HIGH);
|
|
digitalWrite(RELAY_PIN_1, HIGH);
|
|
|
|
scale.begin(DOUT_PIN, CLK_PIN);
|
|
scale.set_scale(-1057.89);
|
|
scale.tare(0);
|
|
|
|
configTime(gmtOffset_sec, daylightOffset_sec, ntpServer);
|
|
|
|
thing["servoControl"] << [](pson& in) {
|
|
if (in.is_empty()) {
|
|
return;
|
|
}
|
|
myServo.write(75);
|
|
delay(1000);
|
|
myServo.write(0);
|
|
};
|
|
|
|
thing["sensorData"] >> [](pson& out) {
|
|
float temperature = dht.readTemperature();
|
|
float weight = getWeight();
|
|
float distance = ultrasonic.read();
|
|
|
|
int ketinggianPakan = tinggiWadah - distance;
|
|
|
|
struct tm timeinfo;
|
|
if (getLocalTime(&timeinfo)) {
|
|
char timeStr[30];
|
|
strftime(timeStr, sizeof(timeStr), "%d %B %Y %H:%M:%S", &timeinfo);
|
|
String timeString = String(timeStr);
|
|
out["Waktu"] = timeString;
|
|
} else {
|
|
out["Waktu"] = "Failed to obtain time";
|
|
}
|
|
|
|
out["Suhu"] = temperature;
|
|
out["Beban Kotoran"] = weight;
|
|
out["Ketinggian Pakan"] = ketinggianPakan;
|
|
};
|
|
|
|
wifiState = DISCONNECTED;
|
|
}
|
|
|
|
void loop() {
|
|
unsigned long currentTime = millis();
|
|
|
|
koneksiwifi();
|
|
|
|
thing.handle();
|
|
|
|
if (currentTime - bacaSensorTerakhir >= bacaSensorInterval) {
|
|
bacaSensorTerakhir = currentTime;
|
|
|
|
float temperature = dht.readTemperature();
|
|
float weight = getWeight();
|
|
unsigned int distance = ultrasonic.read();
|
|
|
|
int ketinggianPakan = tinggiWadah - distance;
|
|
|
|
handleNotifications(ketinggianPakan, currentTime);
|
|
handleRelayControls(temperature, weight, currentTime);
|
|
handleServoSchedule();
|
|
|
|
struct tm timeinfo;
|
|
if (getLocalTime(&timeinfo)) {
|
|
Serial.print(&timeinfo, "%d %B %Y %H:%M:%S\t");
|
|
} else {
|
|
Serial.print("Failed to obtain time");
|
|
}
|
|
|
|
Serial.print("Weight: ");
|
|
Serial.print(weight);
|
|
Serial.print(" g\t");
|
|
|
|
Serial.print("Ketinggian Pakan: ");
|
|
Serial.print(ketinggianPakan);
|
|
Serial.print(" cm\t");
|
|
|
|
Serial.print("Suhu: ");
|
|
Serial.print(temperature);
|
|
Serial.println(" °C");
|
|
}
|
|
}
|
|
|
|
void koneksiwifi() {
|
|
unsigned long currentTime = millis();
|
|
|
|
switch (wifiState) {
|
|
case DISCONNECTED:
|
|
WiFi.begin(SSID, SSID_PASSWORD);
|
|
wifiState = CONNECTING;
|
|
wifiConnectStartTime = currentTime;
|
|
Serial.println("Connecting to WiFi...");
|
|
break;
|
|
|
|
case CONNECTING:
|
|
if (WiFi.status() == WL_CONNECTED) {
|
|
Serial.println("WiFi connected.");
|
|
wifiState = CONNECTED;
|
|
} else if (currentTime - wifiConnectStartTime >= wifiReconectInterval) {
|
|
wifiState = DISCONNECTED;
|
|
Serial.println("Retrying WiFi connection...");
|
|
}
|
|
break;
|
|
|
|
case CONNECTED:
|
|
if (WiFi.status() != WL_CONNECTED) {
|
|
Serial.println("WiFi disconnected.");
|
|
wifiState = DISCONNECTED;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
float getWeight() {
|
|
float weight = scale.get_units(10);
|
|
if (weight >= -2.0 && weight <= 2.0) {
|
|
return 0.0;
|
|
}
|
|
return weight;
|
|
}
|
|
|
|
void moveServo() {
|
|
myServo.write(75);
|
|
delay(1000);
|
|
myServo.write(0);
|
|
|
|
pson data;
|
|
data["action"] = "servo_moved";
|
|
thing.write_bucket("Servo", data);
|
|
}
|
|
|
|
void handleNotifications(int ketinggianPakan, unsigned long currentTime) {
|
|
if (ketinggianPakan <= 2) { // Notifikasi "habis"
|
|
if (conditionStartTime == 0) {
|
|
conditionStartTime = currentTime;
|
|
} else if (currentTime - conditionStartTime >= 5 * 1000) {
|
|
if (currentTime - notifikasiterakhir >= 60 * 1000 && wifiState == CONNECTED) {
|
|
Serial.println("Mengirim Notifikasi Habis...");
|
|
bool result = thing.call_endpoint("notifikasi_habis");
|
|
if (result) {
|
|
Serial.println("Notifikasi Habis Sukses Terkirim.");
|
|
} else {
|
|
Serial.println("Gagal Mengirim Notifikasi Habis.");
|
|
}
|
|
notifikasiterakhir = currentTime;
|
|
}
|
|
}
|
|
} else if (ketinggianPakan < 5) { // Notifikasi "hampir habis"
|
|
if (conditionStartTime == 0) {
|
|
conditionStartTime = currentTime;
|
|
} else if (currentTime - conditionStartTime >= 5 * 1000) {
|
|
if (currentTime - notifikasiterakhir >= 60 * 1000 && wifiState == CONNECTED) {
|
|
Serial.println("Mengirim Notifikasi Hampir Habis");
|
|
bool result = thing.call_endpoint("notifikasi_hampir_habis");
|
|
if (result) {
|
|
Serial.println("Berhasil Mengirim Notifikasi Hampir Habis.");
|
|
} else {
|
|
Serial.println("Gagal Mengirim Notifikasi Hampir Habis.");
|
|
}
|
|
notifikasiterakhir = currentTime;
|
|
}
|
|
}
|
|
} else {
|
|
conditionStartTime = 0;
|
|
}
|
|
}
|
|
|
|
void handleRelayControls(float temperature, float weight, unsigned long currentTime) {
|
|
if (!isnan(temperature)) {
|
|
if (temperature > suhumax && !relayActive1) {
|
|
digitalWrite(RELAY_PIN_2, HIGH);
|
|
relayActive1 = true;
|
|
} else if (temperature <= suhumin && relayActive1) {
|
|
digitalWrite(RELAY_PIN_2, LOW);
|
|
relayActive1 = false;
|
|
}
|
|
}
|
|
|
|
if (weight > bebanmax && !relayActive2) {
|
|
digitalWrite(RELAY_PIN_1, LOW);
|
|
relayActive2 = true;
|
|
relay2StartTime = currentTime;
|
|
}
|
|
|
|
if (relayActive2 && (currentTime - relay2StartTime >= durasiRelayAktif)) {
|
|
digitalWrite(RELAY_PIN_1, HIGH);
|
|
relayActive2 = false;
|
|
scale.tare();
|
|
}
|
|
}
|
|
|
|
void handleServoSchedule() {
|
|
struct tm timeinfo;
|
|
if (!getLocalTime(&timeinfo)) {
|
|
return;
|
|
}
|
|
|
|
int currentHour = timeinfo.tm_hour;
|
|
int currentMinute = timeinfo.tm_min;
|
|
int currentSecond = timeinfo.tm_sec;
|
|
|
|
if (currentHour == 6 && currentMinute == 0 && currentSecond == 1) {
|
|
moveServo();
|
|
}
|
|
if (currentHour == 11 && currentMinute == 0 && currentSecond == 1) {
|
|
moveServo();
|
|
}
|
|
if (currentHour == 16 && currentMinute == 0 && currentSecond == 1) {
|
|
moveServo();
|
|
}
|
|
if (currentHour == 21 && currentMinute == 0 && currentSecond == 1) {
|
|
moveServo();
|
|
}
|
|
}
|