#include <WiFi.h>
#include <DHT.h>
#include <Wire.h>
#include <Adafruit_SSD1306.h>
// 全局对象声明
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
#define OLED_RESET -1
#define DHT_PIN 22
#define DHT_TYPE DHT22
#define TEMP_LED_PIN 17
#define HUM_LED_PIN 16
// 初始化传感器和显示屏对象(确保在全局作用域)
DHT dht(DHT_PIN, DHT_TYPE);
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
// WiFi配置
const char* WIFI_SSID = "Wokwi-GUEST";
const char* WIFI_PASSWORD = ""; // 无需密码
// 服务器配置
const char* SERVER_URL = "192.168.1.1";
const int SERVER_PORT = 3000;
const char* SERVER_PATH = "/data";
// 阈值设置
const float TEMP_THRESHOLD = 30.0; // 温度阈值(°C)
const float HUMIDITY_THRESHOLD = 70.0; // 湿度阈值(%)
// 状态变量
bool wifiConnected = false;
unsigned long lastUpload = 0;
const unsigned long UPLOAD_INTERVAL = 1000; // 上传间隔(ms)
int humAlertCounter = 0;
void setup() {
Serial.begin(115200);
// 初始化引脚
pinMode(TEMP_LED_PIN, OUTPUT);
pinMode(HUM_LED_PIN, OUTPUT);
// 初始化DHT传感器
dht.begin();
// 初始化OLED显示屏(确保Wire库正确初始化I2C)
Wire.begin(18, 19); // 明确指定I2C引脚(SDA=18, SCL=19,根据Wokwi默认配置)
if(!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
Serial.println(F("SSD1306显示屏初始化失败"));
while(1);
}
display.clearDisplay();
display.setTextSize(1);
display.setTextColor(SSD1306_WHITE);
display.setCursor(0, 0);
display.println("Initializing...");
display.display();
// 连接WiFi
connectWiFi();
}
void loop() {
// 检查WiFi连接
if (WiFi.status() != WL_CONNECTED) {
wifiConnected = false;
connectWiFi();
} else {
wifiConnected = true;
}
// 读取传感器数据
float temperature = dht.readTemperature();
float humidity = dht.readHumidity();
// 检查读取是否成功
if (isnan(temperature) || isnan(humidity)) {
Serial.println("Failed to read sensor data!");
displaySensorError();
delay(1000);
return;
}
// 更新显示
updateDisplay(temperature, humidity, wifiConnected);
// 控制温度LED
digitalWrite(TEMP_LED_PIN, temperature >= TEMP_THRESHOLD);
// 控制湿度LED(修正闪烁逻辑,使用millis()避免阻塞)
static unsigned long lastHumBlink = 0;
if (humidity >= HUMIDITY_THRESHOLD) {
if (millis() - lastHumBlink >= 1000) { // 每秒切换一次
lastHumBlink = millis();
digitalWrite(HUM_LED_PIN, !digitalRead(HUM_LED_PIN));
}
} else {
digitalWrite(HUM_LED_PIN, LOW);
}
// 定时上传数据
if (millis() - lastUpload >= UPLOAD_INTERVAL && wifiConnected) {
uploadData(temperature, humidity);
lastUpload = millis();
}
delay(10); // 短暂延时,避免循环过快
}
void connectWiFi() {
display.clearDisplay();
display.setCursor(0, 0);
display.println("Connecting to WiFi...");
display.display();
Serial.print("Connecting to ");
Serial.println(WIFI_SSID);
WiFi.begin(WIFI_SSID, WIFI_PASSWORD);
unsigned long startAttemptTime = millis();
// 等待WiFi连接
while (WiFi.status() != WL_CONNECTED && millis() - startAttemptTime < 20000) {
delay(500);
Serial.print(".");
}
if (WiFi.status() == WL_CONNECTED) {
Serial.println();
Serial.println("WiFi connected!");
Serial.print("IP address: ");
Serial.println(WiFi.localIP());
display.clearDisplay();
display.setCursor(0, 0);
display.println("WiFi Connected");
display.display();
wifiConnected = true;
} else {
Serial.println();
Serial.println("WiFi connection failed");
display.clearDisplay();
display.setCursor(0, 0);
display.println("WiFi Failed");
display.display();
wifiConnected = false;
}
}
void uploadData(float temp, float hum) {
Serial.print("Uploading data: ");
Serial.print(temp);
Serial.print("°C, ");
Serial.print(hum);
Serial.println("%");
WiFiClient client;
if (client.connect(SERVER_URL, SERVER_PORT)) {
// 构建HTTP POST请求
String postData = "temperature=" + String(temp) + "&humidity=" + String(hum);
client.print("POST ");
client.print(SERVER_PATH);
client.print(" HTTP/1.1\r\n");
client.print("Host: ");
client.print(SERVER_URL);
client.print("\r\n");
client.print("Content-Type: application/x-www-form-urlencoded\r\n");
client.print("Content-Length: ");
client.print(postData.length());
client.print("\r\n");
client.print("Connection: close\r\n\r\n");
client.print(postData);
// 等待响应
unsigned long timeout = millis();
while (client.available() == 0) {
if (millis() - timeout > 5000) {
Serial.println(">>> Server response timed out");
client.stop();
return;
}
}
// 读取响应
while(client.available()){
String line = client.readStringUntil('\r');
Serial.print(line);
}
Serial.println();
Serial.println("Data upload complete");
client.stop();
} else {
Serial.println("Failed to connect to server");
client.stop();
}
}
void updateDisplay(float temp, float hum, bool wifiStatus) {
display.clearDisplay();
display.setCursor(0, 0);
// 显示温度和湿度
display.print("Temp: ");
display.print(temp, 1);
display.println(" °C");
display.print("Hum: ");
display.print(hum, 1);
display.println(" %");
// 显示WiFi状态
display.print("WiFi: ");
display.println(wifiStatus ? "Connected" : "Disconnected");
// 显示阈值状态(关键排版优化)
display.print("Temp Threshold:"); // 增加空格确保显示完整
display.println(temp >= TEMP_THRESHOLD ? "Over" : "Normal");
display.print("Hum Threshold:"); // 增加空格确保显示完整
display.println(hum >= HUMIDITY_THRESHOLD ? "Over" : "Normal");
display.display();
}
void displaySensorError() {
display.clearDisplay();
display.setCursor(0, 0);
display.println("Sensor Read Error!");
display.display();
}