深色模式
第 13 章:看懂火焰检测代码
本章任务
看懂火焰传感器的检测代码——先弄明白"标定"是怎么回事,再看懂"检测到火焰就亮灯报警"的完整逻辑。
接线回顾
| 火焰模块 | Pico | 说明 |
|---|---|---|
| VCC | 3V3 | 3.3V 供电(不要接 5V) |
| GND | GND | 共地 |
| A 口(模拟) | GP26 | 连续变化的数值,用 ADC 读 |
| D 口(数字) | GP14 | 只有 0/1,火焰强到一定程度就变 1 |
报警灯用板载 LED(GP25),无需额外接线。
传感器原理
- A 口(模拟):输出连续数值,火焰越近、越旺,读数越小(和直觉相反!),要用
ADC读。实测参考:正前方 30cm 有火时读数小于 50,普通室内无火环境约 300 - D 口(数字):模块内部有个"裁判员"(比较器),火焰强到一定程度就输出 1;这个"程度"可用模块上的小旋钮(电位器)调
Mind+ 生成的典型代码
python
from machine import Pin, ADC # Pin 工具 + ADC(读模拟量)工具
import time
flame_analog = ADC(Pin(26)) # A 口接 GP26(ADC0)
flame_digital = Pin(14, Pin.IN) # D 口接 GP14,输入模式
led = Pin(25, Pin.OUT) # 板载 LED 当报警灯
THRESHOLD = 100 # 阈值:读数低于它就算"有火焰"
# 这个数是先标定出来的(见下文)
while True: # 一直重复检测
analog_val = flame_analog.read_u16() # 读 A 口:0~65535
digital_val = flame_digital.value() # 读 D 口:0 或 1
print(f"A口={analog_val} D口={digital_val}", end="") # 打印读数,不换行
if analog_val < THRESHOLD or digital_val == 1: # 模拟值够小(火焰够近)或数字报警
led.value(1) # 点亮报警灯
print(" ⚠️ 检测到火焰!")
else: # 否则一切正常
led.value(0) # 报警灯灭
print(" 正常")
time.sleep(0.3) # 每 0.3 秒检测一轮代码讲解
什么是"标定"? 阈值 100 不是拍脑袋来的:
- 先在正常环境下读几次 A 口(比如都是 300 左右)
- 再让火焰靠近读几次(比如跌到 50 以下)
- 取两者之间的值当阈值(比如 100)——读数低于它才算有火,这样既不误报、也不漏报
判断行的读法:if analog_val < THRESHOLD or digital_val == 1 —— "A 口读数够小(火焰够近)或者 D 口报警,满足任意一个就亮灯"。or 就是"或者"的意思(第 4 章)。
运行效果
- 无火焰:A 口读数较高(约 300)、D 口为 0,打印"正常",灯灭
- 火焰靠近:A 口读数骤降(小到 50 以下)、D 口变 1,打印"⚠️ 检测到火焰!",板载 LED 点亮
常见坑
- 方向记反:以为"火越大读数越大"——其实相反,火越近读数越小。判断写成
>会导致有火不报警、没火乱报警 - 无火时读数不是满格:室内有灯光、阳光等人眼看不见的红外线,没火焰也可能读到 300 左右,这是正常的,不是模块坏了
- D 口一直是 1:模块太灵敏了,逆时针拧一下电位器
- 读数波动大:白炽灯、阳光都含红外线会干扰,换到自然光环境测
想一想
代码里的
or如果改成and(两个条件都满足才报警),报警会更灵敏还是更迟钝?💡 查看答案
更迟钝。
or是"任何一个满足就报警",and要求模拟值和数字口同时满足才报警——条件更苛刻,有些真实火焰反而会被漏报。报警器宁误报、不漏报,所以用or。阈值 100 改大(比如 250),会发生什么现象?这是更灵敏还是更迟钝?
💡 查看答案
阈值改大,"读数低于它"更容易成立,更容易报警——更灵敏,但代价是误报变多(环境红外底数稍一波动就可能低于它)。调阈值就是在"灵敏"和"误报"之间找平衡。
安全提醒
观察火焰实验时必须有家长陪同,远离易燃物,每次点火 1~2 秒即可。
