#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include "DHT.h"
#include <RTClib.h>
// กำหนดขาพินสำหรับ DHT22
#define DHTPIN 13 // ขา DATA ของ DHT22 ต่อกับ GPIO 13
#define DHTTYPE DHT22 // ใช้เซ็นเซอร์ DHT22
// กำหนดขาพินสำหรับ Relay
#define RELAY_FAN_PIN 12 // Relay ควบคุม Fan ต่อกับ GPIO 12
#define RELAY_PUMP_PIN 14 // Relay ควบคุม Pump ต่อกับ GPIO 14
#define RELAY_LAMP_PIN 27 // Relay ควบคุม Lamp ต่อกับ GPIO 27
// กำหนดขาพินสำหรับปุ่มกด
#define BUTTON_PIN 26 // ปุ่มกดต่อกับ GPIO 26
// กำหนดที่อยู่ I2C สำหรับ LCD และ RTC
#define LCD_ADDRESS 0x27 // หรือ 0x3F ขึ้นอยู่กับโมดูลของคุณ
#define RTC_ADDRESS 0x68 // ที่อยู่ทั่วไปของ DS3231 คือ 0x68
// กำหนดสถานะ Relay ตามประเภทโมดูล (Active HIGH หรือ Active LOW)
#define RELAY_ON HIGH // ปรับเป็น LOW หากโมดูล Relay เป็น Active LOW
#define RELAY_OFF LOW // ปรับเป็น HIGH หากโมดูล Relay เป็น Active LOW
DHT dht(DHTPIN, DHTTYPE);
LiquidCrystal_I2C lcd(LCD_ADDRESS, 20, 4); // จอ LCD ขนาด 20x4
RTC_DS3231 rtc; // ใช้ DS3231 เป็นตัวอย่าง
// ตัวแปรสำหรับการควบคุมโหมดการแสดงผล
bool displayMode = false; // false = โหมดที่ 1, true = โหมดที่ 2
unsigned long lastDebounceTime = 0;
unsigned long debounceDelay = 50;
bool lastButtonState = HIGH;
bool buttonPressed = false;
void setup() {
// เริ่มต้นการเชื่อมต่อ I2C กับจอ LCD
lcd.init();
lcd.backlight();
// เริ่มต้นเซ็นเซอร์ DHT22
dht.begin();
// เริ่มต้น RTC
if (!rtc.begin()) {
lcd.setCursor(0, 0);
lcd.print("RTC not found!");
while (1); // หยุดการทำงานถ้าไม่พบ RTC
}
// ตรวจสอบถ้า RTC ไม่ได้ถูกตั้งเวลา
if (rtc.lostPower()) {
lcd.setCursor(0, 0);
lcd.print("RTC lost power");
// ตั้งค่าเวลาใหม่โดยใช้เวลาที่คอมไพเลอร์ตั้งไว้
rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
delay(2000); // รอ 2 วินาทีหลังตั้งค่าเวลา
}
// กำหนดขาพินสำหรับ Relay เป็น OUTPUT และตั้งค่าเริ่มต้นเป็น OFF
pinMode(RELAY_FAN_PIN, OUTPUT);
pinMode(RELAY_PUMP_PIN, OUTPUT);
pinMode(RELAY_LAMP_PIN, OUTPUT);
// กำหนดขาพินสำหรับปุ่มกดเป็น INPUT_PULLUP
pinMode(BUTTON_PIN, INPUT_PULLUP);
// ปิด Relay ทั้งหมดในตอนเริ่มต้น
digitalWrite(RELAY_FAN_PIN, RELAY_OFF);
digitalWrite(RELAY_PUMP_PIN, RELAY_OFF);
digitalWrite(RELAY_LAMP_PIN, RELAY_OFF);
// แสดงข้อความต้อนรับบน LCD
lcd.setCursor(0, 0);
lcd.print("DHT22 & RTC Ready");
delay(2000); // แสดงข้อความ 2 วินาที
lcd.clear();
}
void loop() {
// อ่านสถานะปุ่มกด
int reading = digitalRead(BUTTON_PIN);
// ตรวจสอบการกดปุ่มด้วย debounce
if (reading != lastButtonState) {
lastDebounceTime = millis();
}
if ((millis() - lastDebounceTime) > debounceDelay) {
if (reading != buttonPressed) {
buttonPressed = reading;
if (buttonPressed == LOW) { // ปุ่มถูกกด
displayMode = !displayMode; // สลับโหมดการแสดงผล
delay(200); // เพิ่ม delay เล็กน้อยเพื่อป้องกันการสลับโหมดหลายครั้ง
}
}
}
lastButtonState = reading;
// อ่านค่าอุณหภูมิและความชื้นจาก DHT22
float humidity = dht.readHumidity();
float temperature = dht.readTemperature();
// อ่านเวลาและวันที่จาก RTC
DateTime now = rtc.now();
// ตรวจสอบว่าค่าที่อ่านมาได้ถูกต้อง
if (isnan(humidity) || isnan(temperature)) {
lcd.setCursor(0, 0);
lcd.print("Error reading DHT22");
return;
}
// ควบคุม Relay ตามเงื่อนไข
// ควบคุม Fan: ถ้า Temp > 30°C ให้เปิด Fan
if (temperature > 30) {
digitalWrite(RELAY_FAN_PIN, RELAY_ON);
} else {
digitalWrite(RELAY_FAN_PIN, RELAY_OFF);
}
// ควบคุม Pump: ถ้า Humidity < 80% ให้เปิด Pump
if (humidity < 80) {
digitalWrite(RELAY_PUMP_PIN, RELAY_ON);
} else {
digitalWrite(RELAY_PUMP_PIN, RELAY_OFF);
}
// ควบคุม Lamp: เปิดเวลา 14:16 และปิดเวลา 14:17
if ((now.hour() == 14) && (now.minute() == 16)) {
digitalWrite(RELAY_LAMP_PIN, RELAY_ON);
} else if ((now.hour() == 14) && (now.minute() == 17)) {
digitalWrite(RELAY_LAMP_PIN, RELAY_OFF);
}
// แสดงข้อมูลบน LCD ตามโหมด
if (!displayMode) {
// โหมดที่ 1: แสดง Date, Time, Temp, Hum
// แถวที่ 1: แสดง Date ในรูปแบบ DD/MM/YYYY
lcd.setCursor(0, 0);
lcd.print("Date: ");
if (now.day() < 10) lcd.print("0");
lcd.print(now.day());
lcd.print("/");
if (now.month() < 10) lcd.print("0");
lcd.print(now.month());
lcd.print("/");
lcd.print(now.year());
// แถวที่ 2: แสดง Time ในรูปแบบ HH:MM:SS
lcd.setCursor(0, 1);
lcd.print("Time: ");
if (now.hour() < 10) lcd.print("0");
lcd.print(now.hour());
lcd.print(":");
if (now.minute() < 10) lcd.print("0");
lcd.print(now.minute());
lcd.print(":");
if (now.second() < 10) lcd.print("0");
lcd.print(now.second());
// แถวที่ 3: แสดง Temp และ Hum แบบจำนวนเต็ม
lcd.setCursor(0, 2);
lcd.print("Temp:");
lcd.print((int)temperature);
lcd.print("C Hum:");
lcd.print((int)humidity);
lcd.print("% "); // เพิ่มช่องว่างเพื่อเคลียร์ข้อมูลเก่า
// แถวที่ 4: แสดงสถานะของ Lamp
lcd.setCursor(0, 3);
lcd.print("Lamp:");
lcd.print((digitalRead(RELAY_LAMP_PIN) == RELAY_ON) ? "ON " : "OFF ");
} else {
// โหมดที่ 2: แสดงสถานะของ Fan, Pump, Lamp
// แถวที่ 1: แสดงสถานะของ Fan
lcd.setCursor(0, 0);
lcd.print("Fan:");
lcd.print((digitalRead(RELAY_FAN_PIN) == RELAY_ON) ? "ON " : "OFF ");
// แถวที่ 2: แสดงสถานะของ Pump
lcd.setCursor(0, 1);
lcd.print("Pump:");
lcd.print((digitalRead(RELAY_PUMP_PIN) == RELAY_ON) ? "ON " : "OFF ");
// แถวที่ 3: แสดงสถานะของ Lamp
lcd.setCursor(0, 2);
lcd.print("Lamp:");
lcd.print((digitalRead(RELAY_LAMP_PIN) == RELAY_ON) ? "ON " : "OFF ");
// แถวที่ 4: แสดง Date และ Time
lcd.setCursor(0, 3);
lcd.print("D:");
if (now.day() < 10) lcd.print("0");
lcd.print(now.day());
lcd.print("/");
if (now.month() < 10) lcd.print("0");
lcd.print(now.month());
lcd.print("/");
lcd.print(now.year());
lcd.print(" T:");
if (now.hour() < 10) lcd.print("0");
lcd.print(now.hour());
lcd.print(":");
if (now.minute() < 10) lcd.print("0");
lcd.print(now.minute());
lcd.print(":");
if (now.second() < 10) lcd.print("0");
lcd.print(now.second());
}
// รอ 1 วินาทีก่อนทำการอัพเดตใหม่
delay(1000);
}