#include <DHT.h>
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
// 引脚定义
#define Sensor_AO A0 // 烟雾传感器模拟输出
#define Sensor_DO 3 // 烟雾传感器数字输出
#define Buzzer 7 // 蜂鸣器
#define RedLED 10 // 红色LED
#define GreenLED 11 // 绿色LED
#define DHTPIN 2 // DHT22 数据引脚
#define DHTTYPE DHT22 // DHT22 传感器类型
#define IR_SENSOR 4 // 红外传感器
#define FAN 6 // 风扇控制
#define RELAY 5 // 继电器控制引脚(接继电器信号端 S)
// 阈值设置
const int TEMP_THRESHOLD = 30; // 温度阈值(°C)
const int HUMIDITY_THRESHOLD = 70; // 湿度阈值(%)
const int SMOKE_THRESHOLD = 400; // 烟雾浓度阈值
// 报警类型定义
#define ALARM_TYPE_NONE 0 // 无报警
#define ALARM_TYPE_TEMP 1 // 温度报警
#define ALARM_TYPE_IR 2 // 红外报警
#define ALARM_TYPE_SMOKE 3 // 烟雾报警
// 全局变量
unsigned int sensorValue = 0; // 烟雾传感器模拟值
float temperature = 0; // 温度值
float humidity = 0; // 湿度值
bool irDetected = false; // 红外检测状态
unsigned long previousMillis = 0; // 上次执行时间
const long interval = 500; // 主循环执行间隔(毫秒)
bool alarmState = false; // 报警状态标志
int currentAlarmType = ALARM_TYPE_NONE; // 当前报警类型
bool motorRunning = false; // 电机运行状态
// 初始化DHT22传感器对象
DHT dht(DHTPIN, DHTTYPE);
// 初始化LCD对象(I2C地址通常为0x27或0x3F,需根据转接板确定)
LiquidCrystal_I2C lcd(0x27, 16, 2); // I2C地址, 列数, 行数
void setup() {
// 初始化引脚
pinMode(Sensor_DO, INPUT);
pinMode(Buzzer, OUTPUT);
pinMode(RedLED, OUTPUT);
pinMode(GreenLED, OUTPUT);
pinMode(IR_SENSOR, INPUT);
pinMode(FAN, OUTPUT);
pinMode(RELAY, OUTPUT); // 继电器引脚设为输出
// 初始化传感器与显示
Serial.begin(9600);
Wire.begin(); // 启动I2C总线
lcd.init(); // 初始化LCD
lcd.backlight(); // 打开背光
lcd.print("System Init...");
delay(2000);
lcd.clear();
// 初始化DHT22
dht.begin();
// 初始状态:继电器断开,电机停止
digitalWrite(RELAY, LOW);
}
void loop() {
unsigned long currentMillis = millis();
// 每500毫秒执行一次检测逻辑
if (currentMillis - previousMillis >= interval) {
previousMillis = currentMillis;
// 读取烟雾传感器数据
sensorValue = analogRead(Sensor_AO);
bool smokeTriggered = (sensorValue > SMOKE_THRESHOLD) || (digitalRead(Sensor_DO) == LOW);
// 读取温湿度数据
temperature = readTemperature();
humidity = readHumidity();
bool tempTriggered = (temperature > TEMP_THRESHOLD); // 温度超阈值
bool humidityTriggered = (humidity > HUMIDITY_THRESHOLD);
// 读取红外传感器数据
irDetected = (digitalRead(IR_SENSOR) == HIGH);
// 更新报警类型(优先级:温度 > 烟雾 > 红外)
if (tempTriggered) {
currentAlarmType = ALARM_TYPE_TEMP;
} else if (smokeTriggered) {
currentAlarmType = ALARM_TYPE_SMOKE;
} else if (irDetected) {
currentAlarmType = ALARM_TYPE_IR;
} else {
currentAlarmType = ALARM_TYPE_NONE;
}
// 更新报警状态
alarmState = (currentAlarmType != ALARM_TYPE_NONE);
// 控制输出设备(含继电器逻辑)
updateOutputs(tempTriggered);
// 在LCD上显示数据
displayData();
// 串口输出调试信息
printDebugInfo();
}
// 其他非阻塞任务可以在这里添加
}
// 读取温度函数
float readTemperature() {
float t = dht.readTemperature();
if (isnan(t)) {
Serial.println("Failed to read temperature from DHT22!");
return 0; // 读取失败时返回0
}
return t;
}
// 读取湿度函数
float readHumidity() {
float h = dht.readHumidity();
if (isnan(h)) {
Serial.println("Failed to read humidity from DHT22!");
return 0; // 读取失败时返回0
}
return h;
}
// 更新输出设备状态
void updateOutputs(bool tempTriggered) {
// 控制蜂鸣器(根据不同报警类型发出不同频率的声音)
if (alarmState) {
switch (currentAlarmType) {
case ALARM_TYPE_TEMP:
// 温度报警:800Hz 持续音
tone(Buzzer, 800);
break;
case ALARM_TYPE_IR:
// 红外报警:1500Hz 短促音
static bool irToneState = false;
if (irToneState) {
tone(Buzzer, 1500);
} else {
noTone(Buzzer);
}
irToneState = !irToneState;
break;
case ALARM_TYPE_SMOKE:
// 烟雾报警:1000Hz 间歇音(200ms开,200ms关)
static unsigned long smokeAlarmTime = 0;
if (millis() - smokeAlarmTime >= 400) {
smokeAlarmTime = millis();
if (digitalRead(Buzzer) == LOW) {
tone(Buzzer, 1000);
} else {
noTone(Buzzer);
}
}
break;
}
} else {
noTone(Buzzer); // 无报警时关闭蜂鸣器
}
// 控制LED状态
if (irDetected) {
digitalWrite(RedLED, HIGH);
digitalWrite(GreenLED, LOW);
} else {
digitalWrite(RedLED, LOW);
digitalWrite(GreenLED, HIGH);
}
// 控制风扇(温度过高时开启)
digitalWrite(FAN, (temperature > TEMP_THRESHOLD) ? HIGH : LOW);
// 控制继电器(温度过高时打开,启动电机)
digitalWrite(RELAY, tempTriggered ? HIGH : LOW);
motorRunning = tempTriggered;
}
// 在LCD上显示数据
void displayData() {
lcd.setCursor(0, 0);
lcd.print("T:");
lcd.print(temperature);
lcd.print("C H:");
lcd.print(humidity);
lcd.print("%");
lcd.setCursor(0, 1);
lcd.print("Smoke:");
lcd.print(sensorValue);
// 显示当前报警类型
lcd.setCursor(13, 1);
switch (currentAlarmType) {
case ALARM_TYPE_TEMP:
lcd.print("T");
break;
case ALARM_TYPE_IR:
lcd.print("I");
break;
case ALARM_TYPE_SMOKE:
lcd.print("S");
break;
default:
lcd.print(" ");
}
}
// 串口输出调试信息
void printDebugInfo() {
Serial.print("Temp: ");
Serial.print(temperature);
Serial.print("°C, Humidity: ");
Serial.print(humidity);
Serial.print("%, Smoke: ");
Serial.print(sensorValue);
Serial.print(", IR: ");
Serial.print(irDetected ? "DETECTED" : "CLEAR");
Serial.print(", Motor: ");
Serial.print(motorRunning ? "ON" : "OFF");
Serial.print(", Alarm: ");
switch (currentAlarmType) {
case ALARM_TYPE_TEMP:
Serial.print("TEMP");
break;
case ALARM_TYPE_IR:
Serial.print("IR");
break;
case ALARM_TYPE_SMOKE:
Serial.print("SMOKE");
break;
default:
Serial.print("NONE");
}
Serial.println();
}