esp32 jemuran pintar
This commit is contained in:
216
ESP32_JemuranPintar.ino
Normal file
216
ESP32_JemuranPintar.ino
Normal file
@ -0,0 +1,216 @@
|
||||
#include <WiFi.h>
|
||||
#include <Firebase_ESP_Client.h>
|
||||
#include <NTPClient.h>
|
||||
#include <WiFiUdp.h>
|
||||
#include <ESP32Servo.h>
|
||||
#include <LiquidCrystal_I2C.h>
|
||||
|
||||
// LCD configuration
|
||||
int lcdColumns = 16;
|
||||
int lcdRows = 2;
|
||||
LiquidCrystal_I2C lcd(0x27, lcdColumns, lcdRows);
|
||||
|
||||
// WiFi configuration
|
||||
#define WIFI_SSID "Nofal"
|
||||
#define WIFI_PASSWORD "123456789"
|
||||
|
||||
// Firebase configuration
|
||||
#define API_KEY "AIzaSyCncK2P7cCxBlwIikX-cxcQ8lneUalADVw"
|
||||
#define DATABASE_URL "https://esp32-86fe1-default-rtdb.asia-southeast1.firebasedatabase.app/"
|
||||
#define USER_EMAIL "lutfi@gmail.com"
|
||||
#define USER_PASSWORD "1234567"
|
||||
|
||||
// Pin configuration
|
||||
#define LDR_PIN 13
|
||||
#define RD_PIN 35
|
||||
static const int servoPin = 14;
|
||||
|
||||
Servo myServo;
|
||||
|
||||
// Firebase & NTP objects
|
||||
FirebaseData fbdo;
|
||||
FirebaseAuth auth;
|
||||
FirebaseConfig config;
|
||||
WiFiUDP ntpUDP;
|
||||
NTPClient timeClient(ntpUDP, "pool.ntp.org", 25200, 60000); // GMT+7
|
||||
|
||||
unsigned long sendDataPrevMillis = 0;
|
||||
int lastRainState = -1;
|
||||
int lastLightValue = -1;
|
||||
int lastPositionValue = -1;
|
||||
|
||||
// LCD scroll text variables
|
||||
String scrollText = "";
|
||||
int scrollIndex = 0;
|
||||
unsigned long lastScrollTime = 0;
|
||||
const int scrollDelay = 300;
|
||||
|
||||
String getFormattedDate() {
|
||||
time_t rawTime = timeClient.getEpochTime();
|
||||
struct tm *timeInfo = localtime(&rawTime);
|
||||
char buffer[11];
|
||||
strftime(buffer, sizeof(buffer), "%Y-%m-%d", timeInfo);
|
||||
return String(buffer);
|
||||
}
|
||||
|
||||
// Update LCD scroll text
|
||||
void updateScrollText(int posValue, int rain, int light) {
|
||||
String posText = (posValue == 0) ? "Jemuran di luar. " : "Jemuran di dalam. ";
|
||||
String lightText, weatherText;
|
||||
|
||||
if (rain == 1 && light == 1) {
|
||||
lightText = "Light: overcast. ";
|
||||
weatherText = "Weather: Cloudy. ";
|
||||
} else if (rain == 0 && light == 0) {
|
||||
lightText = "Light: Good. ";
|
||||
weatherText = "Weather: Rainy. ";
|
||||
} else if (rain == 0 && light == 1) {
|
||||
lightText = "Light: Overcast. ";
|
||||
weatherText = "Weather: Rainy. ";
|
||||
} else {
|
||||
lightText = "Light: Good. ";
|
||||
weatherText = "Weather: Sunny. ";
|
||||
}
|
||||
|
||||
scrollText = posText + lightText + weatherText;
|
||||
}
|
||||
|
||||
// Display scroll text + WiFi status
|
||||
void scrollTextToLCD(bool isOnline) {
|
||||
if (millis() - lastScrollTime >= scrollDelay) {
|
||||
lastScrollTime = millis();
|
||||
lcd.clear();
|
||||
lcd.setCursor(0, 0);
|
||||
int len = scrollText.length();
|
||||
String toPrint = scrollText.substring(scrollIndex, scrollIndex + lcdColumns);
|
||||
lcd.print(toPrint);
|
||||
|
||||
lcd.setCursor(0, 1);
|
||||
lcd.print(isOnline ? "Status: Online " : "Status:Offline");
|
||||
|
||||
scrollIndex++;
|
||||
if (scrollIndex > len) scrollIndex = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void setup() {
|
||||
pinMode(LDR_PIN, INPUT);
|
||||
pinMode(RD_PIN, INPUT);
|
||||
myServo.attach(servoPin);
|
||||
Serial.begin(9600);
|
||||
|
||||
WiFi.begin(WIFI_SSID, WIFI_PASSWORD);
|
||||
Serial.print("Connecting to Wi-Fi");
|
||||
while (WiFi.status() != WL_CONNECTED) {
|
||||
Serial.print(".");
|
||||
delay(300);
|
||||
}
|
||||
Serial.println("\nConnected with IP: " + WiFi.localIP().toString());
|
||||
|
||||
config.api_key = API_KEY;
|
||||
auth.user.email = USER_EMAIL;
|
||||
auth.user.password = USER_PASSWORD;
|
||||
config.database_url = DATABASE_URL;
|
||||
|
||||
Firebase.reconnectNetwork(true);
|
||||
fbdo.setBSSLBufferSize(4096, 1024);
|
||||
fbdo.setResponseSize(2048);
|
||||
Firebase.begin(&config, &auth);
|
||||
Firebase.setDoubleDigits(5);
|
||||
config.timeout.serverResponse = 10 * 1000;
|
||||
|
||||
lcd.init();
|
||||
lcd.backlight();
|
||||
|
||||
timeClient.begin();
|
||||
}
|
||||
|
||||
void loop() {
|
||||
timeClient.update();
|
||||
|
||||
// Baca sensor
|
||||
int rainStateNow = digitalRead(RD_PIN);
|
||||
int lightValueNow = digitalRead(LDR_PIN);
|
||||
int currentPosition = lastPositionValue;
|
||||
|
||||
// Update LCD lokal
|
||||
updateScrollText(currentPosition, rainStateNow, lightValueNow);
|
||||
bool isOnline = WiFi.status() == WL_CONNECTED;
|
||||
scrollTextToLCD(isOnline);
|
||||
|
||||
// Jika Wi-Fi dan Firebase ready
|
||||
if (isOnline && Firebase.ready() && (millis() - sendDataPrevMillis > 1000 || sendDataPrevMillis == 0)) {
|
||||
sendDataPrevMillis = millis();
|
||||
|
||||
String status;
|
||||
if (Firebase.RTDB.getString(&fbdo, "/status/value")) {
|
||||
status = fbdo.stringData();
|
||||
Serial.println("Status: " + status);
|
||||
} else {
|
||||
Serial.print("Error fetching status: ");
|
||||
Serial.println(fbdo.errorReason().c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
if (status == "Off") {
|
||||
int positionValue = -1;
|
||||
if (Firebase.RTDB.getInt(&fbdo, "/position/value")) {
|
||||
positionValue = fbdo.intData();
|
||||
}
|
||||
|
||||
if (positionValue == 1) {
|
||||
lastPositionValue = 1;
|
||||
return;
|
||||
}
|
||||
|
||||
myServo.write(55);
|
||||
Firebase.RTDB.setInt(&fbdo, "/position/value", 1);
|
||||
lastPositionValue = 1;
|
||||
return;
|
||||
}
|
||||
|
||||
// Logika otomatis saat online
|
||||
int newPositionValue = (rainStateNow == 1 && lightValueNow == 0) ? 0 : 1;
|
||||
|
||||
if (rainStateNow != lastRainState || lightValueNow != lastLightValue) {
|
||||
if (Firebase.RTDB.setInt(&fbdo, "/sensor/ldr", lightValueNow) && Firebase.RTDB.setInt(&fbdo, "/sensor/rd", rainStateNow)) {
|
||||
Serial.println("Sensor updated.");
|
||||
}
|
||||
|
||||
lastRainState = rainStateNow;
|
||||
lastLightValue = lightValueNow;
|
||||
|
||||
FirebaseJson json;
|
||||
json.set("tanggal", getFormattedDate());
|
||||
json.set("jam", timeClient.getFormattedTime());
|
||||
json.set("ldr", lightValueNow);
|
||||
json.set("rd", rainStateNow);
|
||||
|
||||
Firebase.RTDB.pushJSON(&fbdo, "/weather", &json);
|
||||
}
|
||||
|
||||
if (newPositionValue != lastPositionValue) {
|
||||
if (Firebase.RTDB.setInt(&fbdo, "/position/value", newPositionValue)) {
|
||||
if (newPositionValue == 0) {
|
||||
myServo.write(110);
|
||||
} else {
|
||||
myServo.write(55);
|
||||
}
|
||||
}
|
||||
lastPositionValue = newPositionValue;
|
||||
}
|
||||
} else {
|
||||
// Mode offline: kontrol lokal
|
||||
Serial.println("Firebase not ready or Wi-Fi lost. Running offline mode.");
|
||||
int newPositionValue = (rainStateNow == 1 && lightValueNow == 0) ? 0 : 1;
|
||||
|
||||
if (newPositionValue != lastPositionValue) {
|
||||
if (newPositionValue == 0) {
|
||||
myServo.write(110); // Jemuran masuk
|
||||
} else {
|
||||
myServo.write(55); // Jemuran keluar
|
||||
}
|
||||
lastPositionValue = newPositionValue;
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user