/*
Wokwi专用 家庭火灾报警系统
移除火焰传感器适配Wokwi Arduino Uno仿真
必做功能全部保留:DS18B20温度+MQ2烟雾、两级阈值可调、LCD1602、声光报警、静音、手动火灾测试
*/
#include <OneWire.h>
#include <DallasTemperature.h>
#include <LiquidCrystal_I2C.h>
// 引脚定义(无火焰传感器,A1闲置)
#define BEEP_PIN 9
#define RED_LED_PIN 10
#define DS18B20_PIN 2
#define MQ2_AOUT A0
// 功能按键
#define KEY_UP 3
#define KEY_DOWN 4
#define KEY_MUTE 5
#define KEY_TEST 6
// LCD1602 I2C地址 Wokwi默认0x27
LiquidCrystal_I2C lcd(0x27, 16, 2);
// 温度传感器对象
OneWire oneWire(DS18B20_PIN);
DallasTemperature tempSensor(&oneWire);
// ========== 两级阈值参数 ==========
float tempWarnThresh = 40.0; // 温度预警阈值 ℃
float tempAlarmThresh = 55.0; // 温度报警阈值 ℃
int smokeWarnThresh = 300; // 烟雾预警阈值
int smokeAlarmThresh= 500; // 烟雾报警阈值
// ========== 全局状态变量 ==========
float curTemp = 0.0;
int curSmoke = 0;
bool muteFlag = false;
bool alarmFlag = false;
unsigned long lastFlashTime = 0;
const unsigned long flashInterval = 300;
void setup() {
Serial.begin(9600);
// 输出引脚初始化
pinMode(BEEP_PIN, OUTPUT);
pinMode(RED_LED_PIN, OUTPUT);
digitalWrite(BEEP_PIN, LOW);
digitalWrite(RED_LED_PIN, LOW);
// 按键开启内部上拉模式
pinMode(KEY_UP, INPUT_PULLUP);
pinMode(KEY_DOWN, INPUT_PULLUP);
pinMode(KEY_MUTE, INPUT_PULLUP);
pinMode(KEY_TEST, INPUT_PULLUP);
// 传感器 & LCD初始化
tempSensor.begin();
lcd.init();
lcd.backlight();
lcd.clear();
lcd.print("Fire Alarm Sys");
delay(2000);
}
void loop() {
readSensorData(); // 读取温、烟传感器
keyProcess(); // 按键处理:调阈值、静音、测试
judgeAlarm(); // 报警逻辑判断(仅温度+烟雾)
alarmAction(); // 声光报警执行
lcdDisplay(); // LCD屏幕刷新
delay(100);
}
// 读取温度、烟雾传感器
void readSensorData() {
tempSensor.requestTemperatures();
curTemp = tempSensor.getTempCByIndex(0);
if(curTemp < -10) curTemp = 25.0; // 断线容错
curSmoke = analogRead(MQ2_AOUT);
}
// 按键扫描:阈值调节、静音、手动模拟火灾
void keyProcess() {
// 阈值增加键
if(digitalRead(KEY_UP) == LOW) {
delay(20);
if(digitalRead(KEY_UP) == LOW) {
tempWarnThresh += 1.0;
tempAlarmThresh += 1.0;
smokeWarnThresh += 20;
smokeAlarmThresh+= 20;
while(digitalRead(KEY_UP) == LOW);
}
}
// 阈值减少(限制安全下限)
if(digitalRead(KEY_DOWN) == LOW) {
delay(20);
if(digitalRead(KEY_DOWN) == LOW) {
if(tempWarnThresh > 30) tempWarnThresh -= 1.0;
if(tempAlarmThresh > 45) tempAlarmThresh -= 1.0;
if(smokeWarnThresh > 100) smokeWarnThresh -= 20;
if(smokeAlarmThresh > 200) smokeAlarmThresh -= 20;
while(digitalRead(KEY_DOWN) == LOW);
}
}
// 解除报警静音
if(digitalRead(KEY_MUTE) == LOW) {
delay(20);
if(digitalRead(KEY_MUTE) == LOW) {
muteFlag = true;
digitalWrite(BEEP_PIN, LOW);
while(digitalRead(KEY_MUTE) == LOW);
}
}
// 手动火灾测试按键,模拟高温高烟雾
if(digitalRead(KEY_TEST) == LOW) {
delay(20);
if(digitalRead(KEY_TEST) == LOW) {
curTemp = 60.0;
curSmoke = 600;
muteFlag = false;
while(digitalRead(KEY_TEST) == LOW);
}
}
}
// 报警逻辑判断:仅温度、烟雾两级阈值
void judgeAlarm() {
alarmFlag = false;
// 任意一项达到报警阈值,触发强报警
if(curTemp >= tempAlarmThresh || curSmoke >= smokeAlarmThresh) {
alarmFlag = true;
muteFlag = false; // 严重火灾自动取消静音
}
// 环境正常清除静音标记
else {
muteFlag = false;
}
}
// 声光报警动作:红灯闪烁+蜂鸣器
void alarmAction() {
unsigned long now = millis();
if(alarmFlag) {
// LED间隔闪烁
if(now - lastFlashTime > flashInterval) {
digitalWrite(RED_LED_PIN, !digitalRead(RED_LED_PIN));
lastFlashTime = now;
}
// 静音状态关闭蜂鸣
if(!muteFlag) {
digitalWrite(BEEP_PIN, HIGH);
} else {
digitalWrite(BEEP_PIN, LOW);
}
} else {
// 无报警,全部关闭
digitalWrite(RED_LED_PIN, LOW);
digitalWrite(BEEP_PIN, LOW);
}
}
// LCD1602显示:温度、烟雾、预警/报警状态
void lcdDisplay() {
lcd.clear();
// 第一行:温度 + 烟雾数值
lcd.setCursor(0, 0);
lcd.print("T:");
lcd.print(curTemp, 1);
lcd.print("C S:");
lcd.print(curSmoke);
// 第二行:系统状态文字
lcd.setCursor(0, 1);
if(alarmFlag) {
if(muteFlag)
lcd.print("ALARM MUTED");
else
lcd.print("FIRE WARNING!");
} else if(curTemp >= tempWarnThresh || curSmoke >= smokeWarnThresh) {
lcd.print("PRE-WARNING");
} else {
lcd.print("SAFE NORMAL");
}
}