#include <WiFi.h>
#include <WebServer.h>
#include <DHT.h>
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <RTClib.h>
// Wi-Fi 設定
const char* ssid = "your_SSID";
const char* password = "your_PASSWORD";
WebServer server(80); // 建立一個Web伺服器對象,監聽80端口
// LCD初始化
LiquidCrystal_I2C lcd(0x27, 20, 4);
DHT dht22(13, DHT22);
RTC_DS3231 rtc; // RTC初始化
// LED引脚定义
const int greenLED = 32; // 绿色LED
const int orangeLED = 33; // 橙色LED
const int redLED = 25; // 红色LED
const int blueLED = 26; // 蓝色LED
// 按钮引脚定义
const int buttonPin1 = 19; // 增加值按钮
const int buttonPin2 = 18; // 减少值按钮
const int buttonPin3 = 17; // 完成设置按钮
// 按钮状态
int buttonState1 = 0; // 增加按钮状态
int buttonState2 = 0; // 减少按钮状态
int buttonState3 = 0; // 完成按钮状态
// 设置模式状态
bool isSettingMode = false;
bool settingComplete = false;
int currentSettingIndex = 0;
// 参数定义
float in_day_setTemperatureH = 33.0;
float in_day_setTemperatureL = 26.0;
float in_day_ErrorTemperature = 1.0;
float in_night_setTemperatureH = 30.0;
float in_night_setTemperatureL = 25.0;
float in_night_ErrorTemperature = 1.0;
float setHumidityH = 70.0;
float setHumidityL = 30.0;
float ErrorHumidity = 5.0;
int dayStartHour = 8;
int dayStartMinute = 30;
int nightStartHour = 18;
int nightStartMinute = 30;
// 当前设置指针
float *currentSetting = nullptr;
int *currentSettingInt = nullptr;
// 前一次显示的温度和湿度
float prevTemperature = -999.0;
float prevHumidity = -999.0;
void setup() {
// Wi-Fi 连接设置
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(1000);
Serial.println("Connecting to WiFi...");
}
Serial.println("Connected to WiFi");
// 初始化LCD和RTC
Wire.begin(21, 22); // 設定 GPIO21 (SDA) 和 GPIO22 (SCL) 為 I2C 腳位
lcd.init();
lcd.backlight();
dht22.begin();
if (!rtc.begin()) {
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Couldn't find RTC");
while (1);
}
pinMode(buttonPin1, INPUT_PULLUP);
pinMode(buttonPin2, INPUT_PULLUP);
pinMode(buttonPin3, INPUT_PULLUP);
pinMode(greenLED, OUTPUT);
pinMode(orangeLED, OUTPUT);
pinMode(redLED, OUTPUT);
pinMode(blueLED, OUTPUT);
lcd.setCursor(0, 0);
lcd.print("System Ready");
delay(2000);
lcd.clear();
// 配置Web伺服器的路由
server.on("/", handleRoot);
server.on("/button1", handleButton1);
server.on("/button2", handleButton2);
server.on("/button3", handleButton3);
server.begin();
Serial.println("esp32 is ready!");
}
void loop() {
// Web伺服器處理
server.handleClient();
buttonState1 = digitalRead(buttonPin1);
buttonState2 = digitalRead(buttonPin2);
buttonState3 = digitalRead(buttonPin3);
DateTime now = rtc.now();
float h = dht22.readHumidity();
float t = dht22.readTemperature();
if (buttonState3 == LOW) {
delay(200); // 防抖
if (!isSettingMode) {
isSettingMode = true;
currentSettingIndex = 0;
settingComplete = false;
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Set Temp High Day:");
currentSetting = &in_day_setTemperatureH;
lcd.setCursor(0, 1);
lcd.print(*currentSetting, 1);
}
else if (!settingComplete) {
currentSettingIndex++;
if (currentSettingIndex == 13) {
isSettingMode = false;
settingComplete = true;
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Setting Done!");
delay(1000);
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Temperature: ");
lcd.print(t, 1);
lcd.setCursor(0, 1);
lcd.print("Humidity: ");
lcd.print(h, 1);
}
else {
switch (currentSettingIndex) {
case 0: currentSetting = &in_day_setTemperatureH; lcd.setCursor(0, 0); lcd.print("Set Temp High Day:"); break;
case 1: currentSetting = &in_day_setTemperatureL; lcd.setCursor(0, 0); lcd.print("Set Temp Low Day:"); break;
case 2: currentSetting = &in_day_ErrorTemperature; lcd.setCursor(0, 0); lcd.print("Set Temp Err Day:"); break;
case 3: currentSetting = &in_night_setTemperatureH; lcd.setCursor(0, 0); lcd.print("Set Temp High Night:"); break;
case 4: currentSetting = &in_night_setTemperatureL; lcd.setCursor(0, 0); lcd.print("Set Temp Low Night:"); break;
case 5: currentSetting = &in_night_ErrorTemperature; lcd.setCursor(0, 0); lcd.print("Set Temp Err Night:"); break;
case 6: currentSetting = &setHumidityH; lcd.setCursor(0, 0); lcd.print("Set Humidity High:"); break;
case 7: currentSetting = &setHumidityL; lcd.setCursor(0, 0); lcd.print("Set Humidity Low:"); break;
case 8: currentSetting = &ErrorHumidity; lcd.setCursor(0, 0); lcd.print("Set Humidity Err:"); break;
case 9: currentSettingInt = &dayStartHour; lcd.setCursor(0, 0); lcd.print("Set Day Start Hour:"); break;
case 10: currentSettingInt = &dayStartMinute; lcd.setCursor(0, 0); lcd.print("Set Day Start Min:"); break;
case 11: currentSettingInt = &nightStartHour; lcd.setCursor(0, 0); lcd.print("Set Night Start Hr:"); break;
case 12: currentSettingInt = &nightStartMinute; lcd.setCursor(0, 0); lcd.print("Set Night Start Mn:"); break;
}
lcd.setCursor(0, 1);
if (currentSettingIndex < 9) {
lcd.print(*currentSetting, 1);
} else {
lcd.print(*currentSettingInt);
}
}
}
}
if (isSettingMode && !settingComplete) {
if (buttonState1 == LOW) {
delay(200); // 防抖
if (currentSettingIndex < 9) {
if (currentSettingIndex == 8) {
(*currentSetting) += 1.0;
} else {
(*currentSetting) += (currentSettingIndex >= 6 ? 5.0 : 0.5);
}
} else {
(*currentSettingInt) += 1;
}
lcd.setCursor(0, 1);
lcd.print(" ");
lcd.setCursor(0, 1);
if (currentSettingIndex < 9) {
lcd.print(*currentSetting, 1);
} else {
lcd.print(*currentSettingInt);
}
}
if (buttonState2 == LOW) {
delay(200); // 防抖
if (currentSettingIndex < 9) {
if (currentSettingIndex == 8) {
(*currentSetting) -= 1.0;
} else {
(*currentSetting) -= (currentSettingIndex >= 6 ? 5.0 : 0.5);
}
} else {
(*currentSettingInt) -= 1;
}
lcd.setCursor(0, 1);
lcd.print(" ");
lcd.setCursor(0, 1);
if (currentSettingIndex < 9) {
lcd.print(*currentSetting, 1);
} else {
lcd.print(*currentSettingInt);
}
}
}
else if (!isSettingMode) {
if (t != prevTemperature || h != prevHumidity) {
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Temperature: ");
lcd.print(t, 1);
lcd.setCursor(0, 1);
lcd.print("Humidity: ");
lcd.print(h, 1);
prevTemperature = t;
prevHumidity = h;
}
// 白天模式
if ((now.hour() > dayStartHour || (now.hour() == dayStartHour && now.minute() >= dayStartMinute)) &&
(now.hour() < nightStartHour || (now.hour() == nightStartHour && now.minute() <= nightStartMinute))) {
// 白天温度控制
if (t > in_day_setTemperatureH) {
digitalWrite(orangeLED, LOW);
digitalWrite(greenLED, HIGH);
} else if (t < in_day_setTemperatureL) {
digitalWrite(greenLED, LOW);
digitalWrite(orangeLED, HIGH);
} else if (t >= in_day_setTemperatureL + in_day_ErrorTemperature && t <= in_day_setTemperatureH - in_day_ErrorTemperature) {
digitalWrite(greenLED, LOW);
digitalWrite(orangeLED, LOW);
}
// 白天湿度控制
if (h > setHumidityH) {
digitalWrite(redLED, HIGH);
digitalWrite(blueLED, LOW);
} else if (h < setHumidityL) {
digitalWrite(redLED, LOW);
digitalWrite(blueLED, HIGH);
} else if (h >= setHumidityL + ErrorHumidity && h <= setHumidityH - ErrorHumidity) {
digitalWrite(redLED, LOW);
digitalWrite(blueLED, LOW);
}
}
// 夜晚模式
else {
// 夜晚温度控制
if (t > in_night_setTemperatureH) {
digitalWrite(orangeLED, LOW);
digitalWrite(greenLED, HIGH);
} else if (t < in_night_setTemperatureL) {
digitalWrite(greenLED, LOW);
digitalWrite(orangeLED, HIGH);
} else if (t >= in_night_setTemperatureL + in_night_ErrorTemperature && t <= in_night_setTemperatureH - in_night_ErrorTemperature) {
digitalWrite(greenLED, LOW);
digitalWrite(orangeLED, LOW);
}
// 夜晚湿度控制
if (h > setHumidityH) {
digitalWrite(redLED, HIGH);
digitalWrite(blueLED, LOW);
} else if (h < setHumidityL) {
digitalWrite(redLED, LOW);
digitalWrite(blueLED, HIGH);
} else if (h >= setHumidityL + ErrorHumidity && h <= setHumidityH - ErrorHumidity) {
digitalWrite(redLED, LOW);
digitalWrite(blueLED, LOW);
}
}
}
}
// 處理網頁根目錄
void handleRoot() {
String html = "<html><body><h1>Temperature and Humidity Control</h1>";
html += "<p><a href=\"/button1\"><button>Increase</button></a></p>";
html += "<p><a href=\"/button2\"><button>Decrease</button></a></p>";
html += "<p><a href=\"/button3\"><button>Complete</button></a></p>";
html += "</body></html>";
server.send(200, "text/html", html);
}
// 處理網頁按鈕1,模擬增加值按钮
void handleButton1() {
// 模擬按下增加值按钮
buttonState1 = LOW;
delay(200); // 模擬防抖
buttonState1 = HIGH;
server.send(200, "text/html", "<html><body><h1>Button 1 Pressed</h1></body></html>");
}
// 處理網頁按鈕2,模擬减少值按钮
void handleButton2() {
buttonState2 = LOW;
delay(200); // 模擬防抖
buttonState2 = HIGH;
server.send(200, "text/html", "<html><body><h1>Button 2 Pressed</h1></body></html>");
}
// 處理網頁按鈕3,模擬完成设置按钮
void handleButton3() {
buttonState3 = LOW;
delay(200); // 模擬防抖
buttonState3 = HIGH;
server.send(200, "text/html", "<html><body><h1>Button 3 Pressed</h1></body></html>");
}