《Arduino & C 实战 | 实验 —— 10 行代码实现火焰探测器》
本文围绕基于 Arduino 的火焰报警器项目展开,通过纯代码优化实现了基础硬件的功能升级:在不新增器材的前提下,整合分级警报、防误报自动复位、串口指令控制三大核心功能,让传统 “有火即报警” 的简易装置升级为智能安防工具。系统可根据火焰强度输出不同频次的声光警报,内置延时确认和复位机制降低误报率,同时支持串口指令手动控制报警状态,并通过串口实时反馈运行状态;整个优化过程仅依托软件逻辑迭代,体现了
·
文章目录
硬件准备:6样小东西,新手随手凑齐
Arduino Uno控制器
1个LED
1个220 欧姆电阻
1个面包版
1个火焰传感器
导线若干
电路接线:颜色对一对,3 分钟接好不翻车

核心代码:10 行代码直接抄,粘贴就能用
/*
* 火焰传感器检测程序
* 传感器引脚:13
* 功能:检测火焰并输出数值,当检测到火焰时触发警报
*/
#define NOTE_ALARM 1047 // 警报音频率 (C6)
#define FLAME_DETECTED 0 // 定义检测到火焰时的传感器值
// 定义引脚
const int FlameSensorPin = 13; // 火焰传感器连接引脚 13
const int buzzerPin = 3; // 蜂鸣器模块连接引脚 3
const int LED_PIN = 8; // LED 指示灯连接引脚 8
// 函数声明
void playNote(int frequency, int duration);
void FlameAlarm();
void NoAlarm();
void LED(int pin, int state);
void setup() {
// 初始化串口通信
Serial.begin(9600);
// 设置引脚模式
pinMode(FlameSensorPin, INPUT);
pinMode(buzzerPin, OUTPUT);
pinMode(LED_PIN, OUTPUT);
// 初始化状态:关闭蜂鸣器和LED
digitalWrite(buzzerPin, HIGH); // 假设是高电平关闭
LED(LED_PIN, LOW);
Serial.println("火焰传感器初始化完成!");
Serial.println("---------------------");
}
void loop() {
// 读取传感器值
int sensorValue = digitalRead(FlameSensorPin); // 将变量定义在内部,更规范
if (sensorValue == FLAME_DETECTED) {
// 检测到火焰
FlameAlarm();
LED(LED_PIN, HIGH);
} else {
// **【核心修改】**
// 没有检测到火焰时,才执行关闭操作
NoAlarm();
LED(LED_PIN, LOW);
}
// 短暂延时,稳定检测
delay(100); // 延时可以适当缩短,让响应更快
}
// LED控制函数
void LED(int pin, int state) {
digitalWrite(pin, state);
}
/*
* 没有检测到火灾时的调用
*/
void NoAlarm() {
digitalWrite(buzzerPin, HIGH); // 关闭蜂鸣器
// Serial.println("没有检测到火灾"); // 注释掉,避免串口输出过多信息
}
/*
* 检测到火灾时的调用,进行蜂鸣器报警
*/
void FlameAlarm() {
Serial.println("检测到火焰!");
playNote(NOTE_ALARM, 300);
playNote(NOTE_ALARM, 300);
// noTone(buzzerPin); // 在循环报警中,这个可以省略
}
// 基础工具函数:播放指定音符
// 参数:frequency - 频率,duration - 持续时间(毫秒)
void playNote(int frequency, int duration) {
tone(buzzerPin, frequency);
delay(duration);
noTone(buzzerPin); // 在每个音符后停止,产生“滴滴”声
delay(50); // 音符之间的间隔
}
代码解读:逐句唠明白,新手也能懂逻辑
/*
* 火焰检测报警系统
* 功能:通过数字火焰传感器检测火焰,触发时蜂鸣器报警,LED点亮
* 核心逻辑:主循环持续检测传感器状态,检测到火焰后调用报警函数
*/
// 警报音频率定义 (C6音符)
#define NOTE_ALARM 1047
// 定义传感器检测到火焰时的返回值
#define FLAME_DETECTED 0
// 引脚定义
const int FlameSensorPin = 13; // 火焰传感器信号引脚
const int buzzerPin = 3; // 蜂鸣器控制引脚
const int LED_PIN = 8; // LED指示灯引脚
// 函数声明
void playNote(int frequency, int duration); // 播放指定频率和时长的音符
void FlameAlarm(); // 火焰报警处理函数
void NoAlarm(); // 无火焰状态处理函数
void LED(int pin, int state); // LED状态控制函数
void setup() {
// 初始化串口通信,用于调试输出
Serial.begin(9600);
// 设置引脚模式
pinMode(FlameSensorPin, INPUT); // 火焰传感器为输入模式
pinMode(buzzerPin, OUTPUT); // 蜂鸣器为输出模式
pinMode(LED_PIN, OUTPUT); // LED为输出模式
// 初始化设备状态:关闭蜂鸣器和LED
digitalWrite(buzzerPin, HIGH);
LED(LED_PIN, LOW);
Serial.println("系统初始化完成,开始监控...");
}
void loop() {
// 读取火焰传感器的数字信号
int sensorValue = digitalRead(FlameSensorPin);
// 判断是否检测到火焰
if (sensorValue == FLAME_DETECTED) {
// 检测到火焰:执行报警操作
FlameAlarm();
LED(LED_PIN, HIGH); // 点亮LED
} else {
// 未检测到火焰:执行正常状态操作
NoAlarm();
LED(LED_PIN, LOW); // 熄灭LED
}
// 短暂延时,稳定检测状态,降低CPU占用率
delay(100);
}
/**
* @brief LED状态控制函数
* @param pin: LED连接的引脚
* @param state: LED的状态,HIGH为点亮,LOW为熄灭
*/
void LED(int pin, int state) {
digitalWrite(pin, state);
}
/**
* @brief 无火焰状态处理函数
* 关闭蜂鸣器,并通过串口打印正常信息
*/
void NoAlarm() {
digitalWrite(buzzerPin, HIGH); // 关闭蜂鸣器
// Serial.println("未检测到火焰"); // 调试用,可根据需要开启
}
/**
* @brief 火焰报警处理函数
* 通过串口打印报警信息,并调用playNote函数发出警报声
*/
void FlameAlarm() {
Serial.println("!!! 检测到火焰,启动警报 !!!");
// 连续播放两次警报音
playNote(NOTE_ALARM, 300);
playNote(NOTE_ALARM, 300);
}
/**
* @brief 播放指定频率和时长的音符
* @param frequency: 音符的频率
* @param duration: 音符的持续时间(毫秒)
*/
void playNote(int frequency, int duration) {
tone(buzzerPin, frequency); // 发出指定频率的声音
delay(duration); // 保持声音
noTone(buzzerPin); // 停止发声
delay(50); // 音符之间的短暂间隔
}
玩法扩展:改 2 行代码,解锁更多实用功能
/*
* 高级火焰检测报警系统
* 功能整合:
* 1. 分级警报:根据火焰强度(模拟值)发出不同频率的声光警报
* 2. 防误报与自动复位:检测到火焰后延时确认,火焰消失后延时复位
* 3. 串口指令控制:通过串口输入指令手动控制警报
*/
// 引脚定义
const int FLAME_SENSOR_DIGITAL = 13; // 火焰传感器数字输出引脚
const int FLAME_SENSOR_ANALOG = A0; // 火焰传感器模拟输出引脚
const int BUZZER_PIN = 3; // 蜂鸣器控制引脚
const int LED_PIN = 8; // LED指示灯引脚
// --- 功能1: 分级警报参数 ---
// 火焰强度阈值 (需要根据实际传感器和环境进行校准)
// 数值越小,代表火焰越强或距离越近
const int HIGH_ALARM_THRESHOLD = 400; // 强火焰/近距离阈值
const int LOW_ALARM_THRESHOLD = 700; // 弱火焰/远距离阈值
// --- 功能2: 延时与复位参数 ---
const unsigned long ALARM_CONFIRM_DELAY = 800; // 警报确认延时 (毫秒)
const unsigned long ALARM_RESET_DELAY = 2000; // 警报复位延时 (毫秒)
// --- 系统状态变量 ---
bool isAlarming = false;
bool isManualAlarm = false;
// 计时器变量
unsigned long flameDetectedStartTime = 0;
unsigned long flameExtinguishedStartTime = 0;
void setup() {
Serial.begin(9600);
// 初始化引脚模式
pinMode(FLAME_SENSOR_DIGITAL, INPUT);
pinMode(BUZZER_PIN, OUTPUT);
pinMode(LED_PIN, OUTPUT);
// 初始状态:关闭蜂鸣器和LED
digitalWrite(BUZZER_PIN, HIGH);
digitalWrite(LED_PIN, LOW);
Serial.println("=== 高级火焰报警系统就绪 ===");
Serial.println("功能: 分级警报、防误报、串口控制");
Serial.println("串口指令: 'A'=手动报警, 'S'=停止报警, 'C'=清除手动模式");
}
void loop() {
// --- 功能3: 串口指令控制 ---
checkSerialCommands();
// 如果当前是手动报警模式,则忽略传感器输入
if (isManualAlarm) {
// 持续发出高级警报
triggerAlarm(HIGH_ALARM);
return;
}
// --- 核心逻辑:传感器检测与状态机 ---
int sensorDigitalState = digitalRead(FLAME_SENSOR_DIGITAL);
unsigned long currentTime = millis();
// 状态1: 检测到火焰 (数字引脚被触发)
if (sensorDigitalState == LOW) {
// 如果尚未处于报警状态,则启动确认延时
if (!isAlarming) {
if (flameDetectedStartTime == 0) {
flameDetectedStartTime = currentTime;
Serial.println("检测到疑似火焰,进入确认延时...");
}
// 如果确认延时已过,则正式触发警报
else if (currentTime - flameDetectedStartTime >= ALARM_CONFIRM_DELAY) {
isAlarming = true;
Serial.println("警报确认!火焰已持续超过 " + String(ALARM_CONFIRM_DELAY) + "ms。");
// 首次触发时打印强度信息
int sensorAnalogValue = analogRead(FLAME_SENSOR_ANALOG);
Serial.print("初始火焰强度: ");
Serial.println(sensorAnalogValue);
}
}
// 如果已经在报警状态,则根据火焰强度更新警报级别
else {
int sensorAnalogValue = analogRead(FLAME_SENSOR_ANALOG);
if (sensorAnalogValue < HIGH_ALARM_THRESHOLD) {
triggerAlarm(HIGH_ALARM);
} else if (sensorAnalogValue < LOW_ALARM_THRESHOLD) {
triggerAlarm(LOW_ALARM);
}
}
// 重置火焰熄灭计时器
flameExtinguishedStartTime = 0;
}
// 状态2: 未检测到火焰 (数字引脚未被触发)
else {
// 如果当前正在报警,则启动复位延时
if (isAlarming) {
if (flameExtinguishedStartTime == 0) {
flameExtinguishedStartTime = currentTime;
Serial.println("火焰消失,进入复位延时...");
}
// 如果复位延时已过,则关闭警报
else if (currentTime - flameExtinguishedStartTime >= ALARM_RESET_DELAY) {
stopAlarm();
Serial.println("警报已复位。");
}
}
// 如果不在报警状态,保持系统静默
else {
digitalWrite(LED_PIN, LOW);
digitalWrite(BUZZER_PIN, HIGH);
}
// 重置火焰检测计时器
flameDetectedStartTime = 0;
}
// 小延时,稳定系统
delay(50);
}
// --- 功能函数 ---
// 检查并执行串口指令
void checkSerialCommands() {
if (Serial.available() > 0) {
char cmd = Serial.read();
switch(cmd) {
case 'A':
case 'a':
isManualAlarm = true;
isAlarming = true;
Serial.println("已进入手动报警模式。");
break;
case 'S':
case 's':
stopAlarm();
Serial.println("已手动停止警报。");
break;
case 'C':
case 'c':
isManualAlarm = false;
stopAlarm();
Serial.println("已清除手动模式,系统恢复自动监控。");
break;
}
}
}
// 定义警报级别枚举
enum AlarmLevel { NO_ALARM, LOW_ALARM, HIGH_ALARM };
// 根据警报级别触发警报
void triggerAlarm(AlarmLevel level) {
static unsigned long lastBlinkTime = 0;
static bool ledState = false;
unsigned long currentTime = millis();
switch(level) {
case HIGH_ALARM:
// 高级警报:LED常亮,蜂鸣器长鸣
digitalWrite(LED_PIN, HIGH);
digitalWrite(BUZZER_PIN, LOW);
break;
case LOW_ALARM:
// 低级警报:LED慢速闪烁,蜂鸣器间歇鸣响
if (currentTime - lastBlinkTime > 300) { // 闪烁周期 600ms
ledState = !ledState;
digitalWrite(LED_PIN, ledState);
digitalWrite(BUZZER_PIN, ledState ? LOW : HIGH);
lastBlinkTime = currentTime;
}
break;
case NO_ALARM:
default:
stopAlarm();
break;
}
}
// 停止所有警报
void stopAlarm() {
isAlarming = false;
digitalWrite(LED_PIN, LOW);
digitalWrite(BUZZER_PIN, HIGH);
flameDetectedStartTime = 0;
flameExtinguishedStartTime = 0;
}
代码运行效果概览
上传并运行这份代码后,你的火焰报警器将不再是一个简单的 “有火就叫” 的设备,而是一个智能、稳健且功能丰富的安防小助手。
它主要展现出以下几个方面的效果:
- 智能分级警报,体验升级
效果:当火焰较远或较小时,警报是慢速、间歇的 “滴… 滴… 滴…” 声,LED 灯也随之同步慢闪。当火焰靠近或变大时,警报会立刻升级为连续、急促的长鸣声,LED 灯常亮。
亮点:这种分级响应不仅能提示你火灾的严重程度,也避免了在非紧急情况下因单一、刺耳的警报声造成的恐慌和困扰。 - 防误报与自动复位,更加可靠
效果:系统内置了 “确认延时”。如果你用打火机快速晃过传感器,它不会立即报警,而是会等待一小段时间(例如 0.8 秒)确认火焰确实存在。同样,当火焰消失后,警报也不会马上停止,会持续一小段时间(例如 2 秒)以防火焰复燃。
亮点:这极大地增强了系统的稳定性和抗干扰能力,有效防止了因传感器抖动或短暂干扰而产生的 “狼来了” 式误报警,让报警信息更具可信度。 - 串口指令控制,玩法多样
效果:通过电脑连接 Arduino 的串口监视器,你可以像操作一个小型设备一样,用简单的字母指令来控制它:
输入 A 并回车:立即触发手动报警,模拟火灾场景进行测试。
输入 S 并回车:停止当前的警报。
输入 C 并回车:取消手动模式,让系统恢复到自动监控火焰的状态。
亮点:这为项目增加了很高的互动性和灵活性。你可以方便地进行功能测试,或者将其集成到更复杂的系统中,通过上位机软件进行远程控制。 - 实时状态反馈,一目了然
效果:在串口监视器中,系统会实时打印出当前的工作状态,例如:“检测到疑似火焰,进入确认延时…”、“警报确认!”、“火焰消失,进入复位延时…” 等。
亮点:这种可视化的反馈让你能清晰地了解系统内部的运行逻辑,不仅方便了调试,也让整个项目看起来非常专业和透明。
总结
总的来说,这段代码让一个基础的硬件项目实现了 ** 从 “能用” 到 “好用”** 的飞跃。它通过软件逻辑的优化,赋予了硬件更多的智能,非常适合作为一个教学案例或课程设计来展示,体现了 “硬件是骨架,软件是灵魂” 的嵌入式开发思想。
更多推荐



所有评论(0)