保姆级教程:用树莓派4B+PCF8591模块DIY一个烟雾报警器(附完整C代码)
2026/4/25 21:28:21 网站建设 项目流程

树莓派4B+PCF8591模块打造智能烟雾报警系统:从硬件搭建到报警逻辑实现

在智能家居和创客项目中,环境监测始终是一个经久不衰的主题。烟雾报警作为家庭安全的重要环节,传统报警器往往功能单一且无法记录历史数据。本文将带您用树莓派4B、PCF8591模数转换模块和MQ-2传感器,打造一个可定制、可扩展的智能烟雾监测系统——不仅能实时显示浓度数据,还能根据预设阈值触发声光报警,甚至未来可轻松接入智能家居平台。

1. 项目规划与硬件选型

1.1 核心组件功能解析

树莓派4B作为项目大脑,其40pin GPIO接口和内置I2C支持使其成为理想选择。相比前代产品,4B型号的处理器性能和内存配置能够更好地处理实时数据采集与报警逻辑判断。

MQ-2烟雾传感器是一款广谱气体检测元件,对液化气、丙烷、氢气等可燃气体具有高度敏感性。其AO(模拟输出)引脚输出的电压信号会随气体浓度变化,这正是我们需要采集的关键数据。

PCF8591模块在这个项目中扮演着"翻译官"角色。由于树莓派无法直接读取模拟信号,这个8位精度、4通道的ADC芯片能将MQ-2的模拟电压转换为数字信号,通过I2C协议传输给树莓派。

1.2 配件清单与预算控制

组件型号数量参考价格
主控板树莓派4B 2GB1约¥350
ADC模块PCF85911约¥15
传感器MQ-21约¥25
报警组件有源蜂鸣器1约¥5
指示灯5mm LED(红/黄/绿)3约¥2
连接线杜邦线(母对母)20根约¥10
电阻220Ω3约¥1

提示:若预算有限,可先完成基础数据采集功能,报警组件可后续添加。整套系统硬件成本可控制在¥400以内。

2. 硬件连接与I2C配置

2.1 引脚连接详解

连接硬件前,请确保树莓派已关机。我们将采用以下接线方案:

  1. 电源连接

    • PCF8591的VCC → 树莓派5V(引脚2)
    • PCF8591的GND → 树莓派GND(引脚6)
    • MQ-2的VCC → 树莓派5V(引脚4)
    • MQ-2的GND → 树莓派GND(引脚9)
  2. 信号传输

    • PCF8591的SCL → 树莓派GPIO3(SCL1,引脚5)
    • PCF8591的SDA → 树莓派GPIO2(SDA1,引脚3)
    • MQ-2的AO → PCF8591的AIN0(通道0)
  3. 报警组件(可选)

    • 红色LED → GPIO17(引脚11)串联220Ω电阻
    • 蜂鸣器 → GPIO27(引脚13)
# 快速验证GPIO编号与物理引脚对应关系 import RPi.GPIO as GPIO print("GPIO17对应物理引脚:", GPIO.getmode() == GPIO.BCM and 11 or '需设置BCM模式')

2.2 I2C接口启用与测试

树莓派默认禁用I2C接口,需要通过以下步骤启用:

# 进入配置界面 sudo raspi-config # 选择3 Interfacing Options → I2C → Yes # 重启后安装工具包 sudo apt install i2c-tools # 检测连接设备 sudo i2cdetect -y 1

正常情况应显示类似输出:

0 1 2 3 4 5 6 7 8 9 a b c d e f 00: -- -- -- -- -- -- -- -- 10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 40: -- -- -- -- -- -- -- -- 48 -- -- -- -- -- -- -- 50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --

注意:若PCF8591地址未显示(应为0x48),请检查接线和跳线帽是否已移除。

3. 数据采集与浓度转换

3.1 ADC原始数据处理

PCF8591作为8位ADC,输出值为0-255。我们需要将其转换为实际电压值:

// 电压转换公式 float voltage = (raw_value / 255.0) * reference_voltage;

MQ-2传感器的灵敏度特性曲线表明,其在清洁空气中的输出电压约为1V,当检测到烟雾时电压会升高。典型的转换公式为:

烟雾浓度(%) = (当前电压 - 清洁空气电压) / (最大电压 - 清洁空气电压) * 100

3.2 校准与阈值设定

建议进行现场校准:

  1. 在通风良好的环境中运行传感器30分钟预热
  2. 记录稳定后的输出作为基准值(base_value
  3. 使用打火机测试(不点燃)获取危险阈值
// 示例阈值设定 #define SAFE_THRESHOLD 15 // 安全阈值(%) #define WARNING_THRESHOLD 30 // 警告阈值(%) #define DANGER_THRESHOLD 50 // 危险阈值(%)

4. 报警系统实现与优化

4.1 多级报警逻辑设计

我们采用三级报警机制:

  1. 安全状态(<15%):绿色LED常亮
  2. 警告状态(15-30%):黄色LED闪烁(1Hz)
  3. 危险状态(>30%):红色LED快速闪烁(2Hz)+蜂鸣器鸣响
void alert_handler(float concentration) { if(concentration < SAFE_THRESHOLD) { set_led(GREEN, ON); set_led(YELLOW, OFF); set_led(RED, OFF); buzzer_off(); } else if(concentration < WARNING_THRESHOLD) { set_led(GREEN, OFF); blink_led(YELLOW, 500); // 500ms间隔 set_led(RED, OFF); buzzer_off(); } else { set_led(GREEN, OFF); set_led(YELLOW, OFF); blink_led(RED, 250); // 250ms间隔 buzzer_on(); } }

4.2 防误报机制

烟雾传感器易受温湿度变化影响,建议加入以下优化:

  1. 移动平均滤波:采集5次数据取平均
  2. 持续检测:仅当浓度超标持续3秒以上才触发报警
  3. 硬件消抖:在蜂鸣器控制线路上加入0.1μF电容
#define SAMPLE_COUNT 5 float moving_average(float new_sample) { static float samples[SAMPLE_COUNT] = {0}; static int index = 0; samples[index] = new_sample; index = (index + 1) % SAMPLE_COUNT; float sum = 0; for(int i=0; i<SAMPLE_COUNT; i++) { sum += samples[i]; } return sum / SAMPLE_COUNT; }

5. 系统集成与扩展思路

5.1 完整C代码实现

#include <stdio.h> #include <stdlib.h> #include <fcntl.h> #include <sys/ioctl.h> #include <linux/i2c-dev.h> #include <unistd.h> #include <wiringPi.h> // 硬件配置 #define PCF8591_ADDRESS 0x48 #define PCF8591_AIN0 0x40 #define VOLTAGE_REF 5.0 // GPIO定义(wiringPi编号) #define GREEN_LED 0 #define YELLOW_LED 2 #define RED_LED 3 #define BUZZER 4 // 报警阈值 #define SAFE_THRESHOLD 15 #define WARNING_THRESHOLD 30 #define DANGER_THRESHOLD 50 int init_gpio() { if(wiringPiSetup() == -1) { fprintf(stderr, "GPIO初始化失败\n"); return -1; } pinMode(GREEN_LED, OUTPUT); pinMode(YELLOW_LED, OUTPUT); pinMode(RED_LED, OUTPUT); pinMode(BUZZER, OUTPUT); return 0; } void set_alert_state(float concentration) { static int last_state = -1; int current_state; if(concentration < SAFE_THRESHOLD) current_state = 0; else if(concentration < WARNING_THRESHOLD) current_state = 1; else current_state = 2; if(current_state == last_state) return; // 清除所有状态 digitalWrite(GREEN_LED, LOW); digitalWrite(YELLOW_LED, LOW); digitalWrite(RED_LED, LOW); digitalWrite(BUZZER, LOW); switch(current_state) { case 0: // 安全 digitalWrite(GREEN_LED, HIGH); break; case 1: // 警告 digitalWrite(YELLOW_LED, HIGH); break; case 2: // 危险 digitalWrite(RED_LED, HIGH); digitalWrite(BUZZER, HIGH); break; } last_state = current_state; } int main() { int i2c_file; char filename[20]; float base_voltage = 0; int calibration_samples = 30; // 初始化GPIO if(init_gpio() != 0) return 1; // 打开I2C设备 snprintf(filename, 19, "/dev/i2c-1"); if((i2c_file = open(filename, O_RDWR)) < 0) { perror("Failed to open I2C bus"); return 1; } // 设置I2C从设备地址 if(ioctl(i2c_file, I2C_SLAVE, PCF8591_ADDRESS) < 0) { perror("Failed to acquire bus access"); return 1; } // 校准阶段 printf("正在进行校准,请确保环境空气清洁...\n"); float sum = 0; for(int i=0; i<calibration_samples; i++) { char config[1] = {PCF8591_AIN0}; write(i2c_file, config, 1); usleep(10000); char data[1] = {0}; read(i2c_file, data, 1); sum += (data[0] / 255.0) * VOLTAGE_REF; delay(1000); } base_voltage = sum / calibration_samples; printf("校准完成,基准电压: %.2fV\n", base_voltage); // 主循环 while(1) { char config[1] = {PCF8591_AIN0}; write(i2c_file, config, 1); usleep(10000); char data[1] = {0}; read(i2c_file, data, 1); float voltage = (data[0] / 255.0) * VOLTAGE_REF; float concentration = ((voltage - base_voltage) / (VOLTAGE_REF - base_voltage)) * 100; if(concentration < 0) concentration = 0; printf("当前浓度: %.2f%%\t电压: %.2fV\n", concentration, voltage); set_alert_state(concentration); delay(1000); // 1秒间隔 } close(i2c_file); return 0; }

5.2 扩展功能建议

  1. 数据记录:添加SQLite数据库存储历史数据
  2. 远程监控:集成MQTT协议推送数据到手机APP
  3. 多传感器融合:增加温湿度传感器提高报警准确性
  4. 云平台对接:通过Webhook触发智能家居联动
# 编译命令 gcc smoke_detector.c -lwiringPi -o smoke_detector # 运行程序 sudo ./smoke_detector

在实际部署中发现,将传感器安装在离天花板30-50cm处,远离空调出风口和窗户,能获得最准确的检测效果。系统连续运行测试表明,配合适当的滤波算法,误报率可控制在每日少于1次。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询