430 lines
11 KiB
C++
430 lines
11 KiB
C++
#include <Wire.h>
|
|
#include "RtcDayLapse.h"
|
|
#include <DHT.h>
|
|
#include "RBDdimmer.h"
|
|
#include <ESP8266WiFi.h>
|
|
#include <ESP8266WebServer.h>
|
|
#include <ArduinoJson.h>
|
|
#include "SWHandler.h"
|
|
#include <LiquidCrystal_I2C.h>
|
|
|
|
uint32_t tickDisplay = 0;
|
|
byte displayMode = 0;
|
|
float temperature = 0;
|
|
float humidity = 0;
|
|
String ip = "NOT FOUND";
|
|
|
|
#define DHTPIN 2 // Pin data DHT22 terhubung ke pin D4 pada ESP8266
|
|
#define DHTTYPE DHT22 // Tipe sensor DHT
|
|
|
|
const char* ssid1 = "12";
|
|
const char* password1 = "rachman12";
|
|
const char* ssid2 = "Rachman Tio";
|
|
const char* password2 = "tiomaulan99";
|
|
const char* ssid3 = "wifi_ps";
|
|
const char* password3 = "00000099";
|
|
|
|
// Parameters
|
|
DHT dht(DHTPIN, DHTTYPE);
|
|
RTC_DS3231 rtc;
|
|
const int zeroCrossPin = 13;
|
|
const int acdPin = 15;
|
|
int MIN_POWER = 0;
|
|
int MAX_POWER = 99;
|
|
int power = 0;
|
|
bool globalPowerStatus = true; // Variable to keep track of overall power status
|
|
bool controlMode = false;
|
|
|
|
// Kelembaban target berdasarkan hari inkubasi
|
|
const int humidityDay1to18 = 55;
|
|
const int humidityDay19to21 = 68;
|
|
|
|
// Egg turning
|
|
const int EGG_TURN_INTERVAL = 4 * 60 * 60 * 1000; // 4 hours in milliseconds
|
|
const int LOCKDOWN_START_DAY = 18;
|
|
unsigned long lastEggTurnTime = 0;
|
|
|
|
// Objects
|
|
dimmerLamp acd(acdPin, zeroCrossPin);
|
|
ESP8266WebServer server(80);
|
|
LiquidCrystal_I2C lcd(0x27, 16, 2);
|
|
|
|
// Variables for timing
|
|
unsigned long lastSetPowerTime = 0;
|
|
bool setPowerCalled = false;
|
|
int oldPower = -1;
|
|
|
|
void setup() {
|
|
Serial.begin(115200);
|
|
delay(10);
|
|
RtcDayLapseInit();
|
|
dht.begin();
|
|
lcd.begin();
|
|
lcd.backlight();
|
|
|
|
// Initialize relays
|
|
SetupSwitch();
|
|
|
|
// Initialize dimmer
|
|
acd.begin(NORMAL_MODE, ON);
|
|
power = 0;
|
|
acd.setPower(power);
|
|
|
|
// Connect to Wi-Fi
|
|
connectToWiFi();
|
|
|
|
displayIPAddress(WiFi.localIP());
|
|
|
|
Wire.begin();
|
|
|
|
Serial.print("Memory flag: ");
|
|
uint8_t v = RtcGetMemoryFlag();
|
|
Serial.println(v);
|
|
|
|
Serial.print("Set new flag to ");
|
|
v++;
|
|
Serial.print(v);
|
|
if (RtcSetMemoryFlag(v)) {
|
|
Serial.println(" : OK");
|
|
} else {
|
|
Serial.println(" : FAILED");
|
|
}
|
|
|
|
server.on("/", HTTP_GET, handleGetTime);
|
|
server.on("/", HTTP_POST, handlePostTime);
|
|
server.on("/dht", HTTP_GET, handleDht);
|
|
server.on("/inkubator", HTTP_POST, handleInkubator); // Updated endpoint for handleInkubator
|
|
|
|
server.begin();
|
|
Serial.println("HTTP server started");
|
|
}
|
|
|
|
void loop() {
|
|
server.handleClient();
|
|
RtcElapsedRefresh();
|
|
unsigned long currentTime = millis();
|
|
|
|
if (globalPowerStatus) {
|
|
// Kembali ke logika kontrol suhu setelah 10 detik hanya jika setPowerCalled adalah true
|
|
if (setPowerCalled && (currentTime - lastSetPowerTime >= 10000)) {
|
|
setPowerCalled = false; // Reset flag
|
|
}
|
|
|
|
// Menjalankan kontrol suhu dan kelembaban hanya jika setPowerCalled adalah false
|
|
if (!setPowerCalled) {
|
|
handleTemperatureAndHumidityControl();
|
|
}
|
|
|
|
// Handle egg turning if before lockdown period
|
|
if (lapseDay <= LOCKDOWN_START_DAY) {
|
|
turnEggs();
|
|
}
|
|
} else {
|
|
power = 0;
|
|
}
|
|
|
|
Serial.print("Current power: ");
|
|
Serial.println(power);
|
|
if (oldPower!=power){
|
|
oldPower = power;
|
|
acd.setPower(power);
|
|
if (power==0){
|
|
acd.setState(OFF);
|
|
}else{
|
|
acd.setState(ON);
|
|
}
|
|
}
|
|
|
|
HandleLCD();
|
|
|
|
delay(100);
|
|
}
|
|
|
|
void handleGetTime() {
|
|
RtcElapsedRefresh();
|
|
|
|
StaticJsonDocument<200> doc;
|
|
doc["day"] = lapseDay;
|
|
doc["hours"] = lapseHours;
|
|
doc["minutes"] = lapseMinutes;
|
|
doc["seconds"] = lapseSeconds;
|
|
|
|
String response;
|
|
serializeJson(doc, response);
|
|
server.send(200, "application/json", response);
|
|
|
|
}
|
|
|
|
void HandleLCD(){
|
|
if ((millis()-tickDisplay)>=3000){
|
|
tickDisplay = millis();
|
|
|
|
if (displayMode==0){
|
|
lcd.clear();
|
|
lcd.setCursor(0, 0);
|
|
lcd.print("IP Address:");
|
|
lcd.setCursor(0, 1);
|
|
lcd.print(ip);
|
|
}else if(displayMode==1){
|
|
lcd.clear();
|
|
lcd.setCursor(0, 0);
|
|
lcd.print("Hari Ke -");
|
|
lcd.print(lapseDay);
|
|
lcd.print(" ");
|
|
lcd.setCursor(0, 1);
|
|
lcd.print(lapseHours);
|
|
lcd.print(":");
|
|
lcd.print(lapseMinutes);
|
|
lcd.print(":");
|
|
lcd.print(lapseSeconds);
|
|
}else{
|
|
lcd.clear();
|
|
lcd.setCursor(0, 0);
|
|
lcd.print("S: ");
|
|
lcd.print(temperature);
|
|
lcd.print(" C");
|
|
|
|
lcd.setCursor(11, 0);
|
|
lcd.print("P: ");
|
|
lcd.print(power);
|
|
|
|
lcd.setCursor(0, 1);
|
|
lcd.print("K: ");
|
|
lcd.print(humidity);
|
|
lcd.print(" %");
|
|
}
|
|
displayMode++;
|
|
if (displayMode>2) displayMode = 0;
|
|
}
|
|
}
|
|
|
|
void handlePostTime() {
|
|
if (server.hasArg("plain") == false) {
|
|
server.send(400, "text/plain", "Bad Request");
|
|
return;
|
|
}
|
|
|
|
String body = server.arg("plain");
|
|
StaticJsonDocument<200> doc;
|
|
DeserializationError error = deserializeJson(doc, body);
|
|
|
|
if (error) {
|
|
server.send(400, "text/plain", "Bad Request");
|
|
return;
|
|
}
|
|
|
|
int day = doc["day"];
|
|
if (day<0) day = 0;
|
|
if (day>21) day = 21;
|
|
RtcElapseSet(day);
|
|
server.send(200, "text/plain", "Time updated");
|
|
}
|
|
|
|
void handleDht() {
|
|
float humidity = dht.readHumidity();
|
|
float temperature = dht.readTemperature();
|
|
|
|
if (isnan(humidity) || isnan(temperature)) {
|
|
Serial.println("Failed to read from DHT sensor");
|
|
server.send(500, "text/plain", "Failed to read from DHT sensor");
|
|
return;
|
|
}
|
|
|
|
StaticJsonDocument<200> doc;
|
|
doc["temperature"] = temperature;
|
|
doc["humidity"] = humidity;
|
|
|
|
String response;
|
|
serializeJson(doc, response);
|
|
|
|
Serial.print("Response: ");
|
|
Serial.println(response);
|
|
|
|
server.send(200, "application/json", response);
|
|
}
|
|
|
|
void handleInkubator() { // Renamed from handlePower to handleInkubator
|
|
if (server.hasArg("plain") == false) {
|
|
server.send(400, "text/plain", "Bad Request");
|
|
return;
|
|
}
|
|
|
|
String body = server.arg("plain");
|
|
StaticJsonDocument<200> doc;
|
|
DeserializationError error = deserializeJson(doc, body);
|
|
|
|
if (error) {
|
|
server.send(400, "text/plain", "Bad Request");
|
|
return;
|
|
}
|
|
|
|
String powerStatus = doc["inkubator"];
|
|
|
|
if (powerStatus == "on") {
|
|
globalPowerStatus = true;
|
|
server.send(200, "text/plain", "All devices are ON");
|
|
Serial.println("All devices ON");
|
|
} else if (powerStatus == "off") {
|
|
globalPowerStatus = false;
|
|
SetSwitchState(SWITCH_TRAY, false);
|
|
SetSwitchState(SWITCH_MIST, false);
|
|
SetSwitchState(SWITCH_FAN, false);
|
|
power = 0;
|
|
acd.setPower(0);
|
|
server.send(200, "text/plain", "All devices are OFF");
|
|
Serial.println("All devices OFF");
|
|
} else {
|
|
server.send(400, "text/plain", "Invalid power status");
|
|
}
|
|
}
|
|
|
|
void handleTemperatureAndHumidityControl() {
|
|
temperature = dht.readTemperature();
|
|
humidity = dht.readHumidity();
|
|
|
|
if (isnan(temperature) || isnan(humidity)) {
|
|
Serial.println("Failed to read from DHT sensor");
|
|
return;
|
|
}
|
|
|
|
bool terlaluPanas = false;
|
|
|
|
//versi feedback
|
|
float deltaSuhu = 37.5 - temperature;
|
|
int pw = abs(deltaSuhu);
|
|
if (deltaSuhu>0.1){
|
|
//lebih dingin:
|
|
//kipas mati
|
|
if (pw<=0) pw = 1;
|
|
power+=pw;
|
|
}else if (deltaSuhu<-0.1){
|
|
//lebih panas:
|
|
//dkipas hidup
|
|
terlaluPanas = true;
|
|
if (pw<=0) pw = 1;
|
|
power-= pw;
|
|
}
|
|
if (power<MIN_POWER) power = MIN_POWER;
|
|
if (power>MAX_POWER) power = MAX_POWER;
|
|
|
|
// Kontrol kelembaban
|
|
bool terlaluLembab = humidity > (getTargetHumidity() + 1);
|
|
bool mistAktif = false;
|
|
int targetHumidity = getTargetHumidity();
|
|
if (humidity < targetHumidity) {
|
|
mistAktif = true;
|
|
SetSwitchState(SWITCH_MIST, true); // Menyalakan mist maker jika kelembaban di bawah target
|
|
//SetSwitchState(SWITCH_FAN, false); // Mematikan kipas
|
|
} else {
|
|
SetSwitchState(SWITCH_MIST, false); // Mematikan mist maker
|
|
//SetSwitchState(SWITCH_FAN, true); // Menyalakan kipas
|
|
}
|
|
|
|
//fungsi kipas
|
|
bool kipasOn = terlaluPanas || terlaluLembab || mistAktif;
|
|
SetSwitchState(SWITCH_FAN, kipasOn); // Menyalakan kipas
|
|
}
|
|
|
|
int getTargetHumidity() {
|
|
if (lapseDay <= LOCKDOWN_START_DAY
|
|
) {
|
|
return humidityDay1to18;
|
|
} else if (lapseDay <= 21) {
|
|
return humidityDay19to21;
|
|
} else {
|
|
return 0; // Inkubasi selesai, lakukan sesuatu jika perlu
|
|
}
|
|
}
|
|
|
|
void displayIPAddress(IPAddress ipAddress) {
|
|
lcd.clear();
|
|
lcd.setCursor(0, 0);
|
|
lcd.print("IP Address:");
|
|
lcd.setCursor(0, 1);
|
|
ip = ipAddress.toString();
|
|
lcd.print(ipAddress);
|
|
}
|
|
|
|
void clearIPAddress() {
|
|
lcd.clear();
|
|
}
|
|
|
|
void turnEggs() {
|
|
static bool isTurning = false; // Untuk melacak apakah kita sedang dalam proses turning
|
|
static unsigned long turnStartTime = 0; // Waktu saat kita mulai turning
|
|
unsigned long currentTime = millis();
|
|
|
|
if (!isTurning) {
|
|
// Memulai turning jika interval telah berlalu
|
|
if (currentTime - lastEggTurnTime >= EGG_TURN_INTERVAL) {
|
|
SetSwitchState(SWITCH_TRAY, true); // Mulai turning
|
|
isTurning = true; // Tandai bahwa kita sedang turning
|
|
turnStartTime = currentTime;
|
|
// Simpan waktu saat kita mulai turning
|
|
}
|
|
} else {
|
|
// Mematikan turning setelah 30 detik
|
|
if (currentTime - turnStartTime >= 14000) { // 30 detik dalam milidetik
|
|
SetSwitchState(SWITCH_TRAY, false); // Matikan turning
|
|
isTurning = false; // Tandai bahwa turning telah selesai
|
|
lastEggTurnTime = currentTime; // Perbarui waktu terakhir kita melakukan turning
|
|
}
|
|
}
|
|
}
|
|
|
|
void connectToWiFi() {
|
|
WiFi.begin(ssid1, password1);
|
|
unsigned long startAttemptTime = millis();
|
|
|
|
// Tunggu koneksi selama 10 detik (10000 milidetik)
|
|
while (WiFi.status() != WL_CONNECTED && millis() - startAttemptTime < 10000) {
|
|
delay(500);
|
|
Serial.print(".");
|
|
}
|
|
|
|
// Jika percobaan pertama gagal, coba jaringan WiFi kedua
|
|
if (WiFi.status() != WL_CONNECTED) {
|
|
Serial.println();
|
|
Serial.println("Gagal terhubung ke jaringan pertama.");
|
|
Serial.print("Menghubungkan ke ");
|
|
Serial.println(ssid2);
|
|
|
|
WiFi.begin(ssid2, password2);
|
|
startAttemptTime = millis();
|
|
|
|
// Tunggu koneksi selama 10 detik lagi
|
|
while (WiFi.status() != WL_CONNECTED && millis() - startAttemptTime < 10000) {
|
|
delay(500);
|
|
Serial.print(".");
|
|
}
|
|
}
|
|
|
|
// Jika percobaan kedua gagal, coba jaringan WiFi ketiga
|
|
if (WiFi.status() != WL_CONNECTED) {
|
|
Serial.println();
|
|
Serial.println("Gagal terhubung ke jaringan kedua.");
|
|
Serial.print("Menghubungkan ke ");
|
|
Serial.println(ssid3);
|
|
|
|
WiFi.begin(ssid3, password3);
|
|
startAttemptTime = millis();
|
|
|
|
// Tunggu koneksi selama 10 detik lagi
|
|
while (WiFi.status() != WL_CONNECTED && millis() - startAttemptTime < 10000) {
|
|
delay(500);
|
|
Serial.print(".");
|
|
}
|
|
}
|
|
|
|
// Periksa status koneksi akhir
|
|
if (WiFi.status() == WL_CONNECTED) {
|
|
Serial.println();
|
|
Serial.println("WiFi terhubung");
|
|
Serial.println("Alamat IP: ");
|
|
Serial.println(WiFi.localIP());
|
|
} else {
|
|
Serial.println();
|
|
Serial.println("Gagal terhubung ke jaringan manapun.");
|
|
}
|
|
}
|