#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <DHT.h>
// -------------------------- 硬件引脚配置(严格匹配官方接线)--------------------------
// OLED屏幕参数(0.96寸128x64,I2C通信)
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, -1);
bool oled_available = false; // 标记OLED是否初始化成功
// 气体传感器(Wokwi官方4引脚型号:AO=模拟输出,DO=数字报警)
#define GAS_AO_PIN 35 // AO接ADC引脚,无需额外电阻(官方推荐)
#define GAS_DO_PIN 15 // DO接数字引脚,用于阈值报警
// DHT22温湿度传感器
#define DHT_PIN 14
#define DHT_TYPE DHT22
DHT dht(DHT_PIN, DHT_TYPE);
// 气体监测参数(参考官方示例,可按需调整)
#define GAS_SAFE_PERCENT 50 // 安全浓度阈值(0-100%)
bool gas_alarm_state = false; // 气体报警状态(true=异常,false=正常)
void setup() {
// 初始化串口(调试用,波特率115200)
Serial.begin(115200);
delay(1000); // 等待Wokwi仿真环境稳定(官方示例推荐延时)
// 1. 初始化气体传感器(DO引脚设为输入模式)
pinMode(GAS_DO_PIN, INPUT);
Serial.println("✅ 气体传感器就绪(AO=35, DO=15)");
// 2. 初始化DHT22温湿度传感器
dht.begin();
Serial.println("✅ DHT22温湿度传感器就绪(引脚14)");
// 3. 初始化OLED显示屏(I2C引脚SDA=18, SCL=19)
Wire.begin(18, 19);
if (display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) { // 0x3C是OLED默认I2C地址
oled_available = true;
display.clearDisplay();
display.setTextColor(SSD1306_WHITE); // OLED单色反显,白色字体可见
display.setTextSize(1);
display.setCursor(0, 0);
display.print("Wokwi官方气体监测");
display.setCursor(0, 16);
display.print("系统初始化中...");
display.display();
Serial.println("✅ OLED显示屏就绪(SDA=18, SCL=19)");
} else {
Serial.println("❌ OLED初始化失败,检查I2C接线");
}
// 打印操作指南(官方特性说明)
Serial.println("\n📌 操作说明:");
Serial.println("1. 点击气体传感器 → 拖「Gas Level」调浓度(0-100%)");
Serial.println("2. 拖「Potentiometer」调DO报警阈值(逆时降低,顺时升高)");
Serial.println("3. 点击DHT22 → 直接修改温湿度值");
delay(2000); // 停留2秒让用户看清指南
}
void loop() {
// -------------------------- 1. 读取气体传感器数据(遵循官方特性)--------------------------
// AO引脚:读取模拟浓度(0-4095),映射为0-100%(官方推荐显示格式)
int gas_ao_raw = analogRead(GAS_AO_PIN);
int gas_concentration = map(gas_ao_raw, 0, 4095, 0, 100);
gas_concentration = constrain(gas_concentration, 0, 100); // 限制范围,避免异常值
// DO引脚:读取数字报警状态(官方规则:低电平=浓度超标,高电平=正常)
gas_alarm_state = (digitalRead(GAS_DO_PIN) == LOW) ? true : false;
// -------------------------- 2. 读取DHT22温湿度数据--------------------------
float temp = dht.readTemperature(); // 温度(℃)
float hum = dht.readHumidity(); // 湿度(%)
// 处理DHT22读取失败的情况(返回NaN时标记为错误)
if (isnan(temp) || isnan(hum)) {
temp = NAN;
hum = NAN;
}
// -------------------------- 3. 串口打印实时数据(调试用)--------------------------
Serial.println("\n===== 实时监测数据 =====");
Serial.print("🔬 气体浓度:");
Serial.print(gas_concentration);
Serial.println(" %");
Serial.print("⚠️ 报警状态:");
Serial.println(gas_alarm_state ? "异常(浓度超标)" : "正常");
Serial.print("🌡️ 环境温度:");
Serial.println(isnan(temp) ? "读取失败" : String(temp, 1) + " °C");
Serial.print("💧 环境湿度:");
Serial.println(isnan(hum) ? "读取失败" : String(hum, 1) + " %");
// -------------------------- 4. OLED显示数据(直观可视化)--------------------------
if (oled_available) {
display.clearDisplay(); // 清空屏幕,避免重影
// 第1行:标题
display.setCursor(0, 0);
display.setTextSize(1);
display.print("气体+温湿度监测");
// 第2行:气体浓度
display.setCursor(0, 16);
display.print("气体:");
display.print(gas_concentration);
display.print("%");
// 第3行:报警状态(异常标⚠️,正常标✅,直观区分)
display.setCursor(0, 32);
display.print("状态:");
if (gas_alarm_state) {
display.print("⚠️ 异常");
} else {
display.print("✅ 正常");
}
// 第4行:温湿度(失败显示Err)
display.setCursor(0, 48);
display.print("温:");
display.print(isnan(temp) ? "Err" : String(temp, 1) + "C");
display.print(" 湿:");
display.print(isnan(hum) ? "Err" : String(hum, 1) + "%");
display.display(); // 刷新屏幕,显示最新数据
}
delay(1500); // 1.5秒刷新一次,平衡实时性和系统稳定性
}