硬件准备: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;
}

代码运行效果概览
上传并运行这份代码后,你的火焰报警器将不再是一个简单的 “有火就叫” 的设备,而是一个智能、稳健且功能丰富的安防小助手。
它主要展现出以下几个方面的效果:

  1. 智能分级警报,体验升级
    效果:当火焰较远或较小时,警报是慢速、间歇的 “滴… 滴… 滴…” 声,LED 灯也随之同步慢闪。当火焰靠近或变大时,警报会立刻升级为连续、急促的长鸣声,LED 灯常亮。
    亮点:这种分级响应不仅能提示你火灾的严重程度,也避免了在非紧急情况下因单一、刺耳的警报声造成的恐慌和困扰。
  2. 防误报与自动复位,更加可靠
    效果:系统内置了 “确认延时”。如果你用打火机快速晃过传感器,它不会立即报警,而是会等待一小段时间(例如 0.8 秒)确认火焰确实存在。同样,当火焰消失后,警报也不会马上停止,会持续一小段时间(例如 2 秒)以防火焰复燃。
    亮点:这极大地增强了系统的稳定性和抗干扰能力,有效防止了因传感器抖动或短暂干扰而产生的 “狼来了” 式误报警,让报警信息更具可信度。
  3. 串口指令控制,玩法多样
    效果:通过电脑连接 Arduino 的串口监视器,你可以像操作一个小型设备一样,用简单的字母指令来控制它:
    输入 A 并回车:立即触发手动报警,模拟火灾场景进行测试。
    输入 S 并回车:停止当前的警报。
    输入 C 并回车:取消手动模式,让系统恢复到自动监控火焰的状态。
    亮点:这为项目增加了很高的互动性和灵活性。你可以方便地进行功能测试,或者将其集成到更复杂的系统中,通过上位机软件进行远程控制。
  4. 实时状态反馈,一目了然
    效果:在串口监视器中,系统会实时打印出当前的工作状态,例如:“检测到疑似火焰,进入确认延时…”、“警报确认!”、“火焰消失,进入复位延时…” 等。
    亮点:这种可视化的反馈让你能清晰地了解系统内部的运行逻辑,不仅方便了调试,也让整个项目看起来非常专业和透明。
    总结
    总的来说,这段代码让一个基础的硬件项目实现了 ** 从 “能用” 到 “好用”** 的飞跃。它通过软件逻辑的优化,赋予了硬件更多的智能,非常适合作为一个教学案例或课程设计来展示,体现了 “硬件是骨架,软件是灵魂” 的嵌入式开发思想。
Logo

智能硬件社区聚焦AI智能硬件技术生态,汇聚嵌入式AI、物联网硬件开发者,打造交流分享平台,同步全国赛事资讯、开展 OPC 核心人才招募,助力技术落地与开发者成长。

更多推荐