深色模式
第 13 章:看懂火焰检测代码
本章任务
看懂"火焰传感器检测报警"的 Arduino C++ 代码——和第二册第 13 章是同一个任务。这也是本册最后一个实验,前面学过的所有"单词"都会在这里汇合。
接线回顾
| 火焰模块 | Pico | 说明 |
|---|---|---|
| VCC | 3V3 | 3.3V 供电(不要接 5V) |
| GND | GND | 共地 |
| A 口(模拟) | GP26 | ADC0,读连续电压——火焰越近,读数越小 |
| D 口(数字) | GP14 | 火焰强到一定程度输出高电平 |
报警 LED 用板载 LED(GP25),无需额外接线。
Mind+ 生成的典型代码
cpp
const int FLAME_ANALOG = 26; // A 口(模拟)接 GP26
const int FLAME_DIGITAL = 14; // D 口(数字)接 GP14
const int LED_PIN = 25; // 报警灯用板载 LED
const int THRESHOLD = 3; // 报警阈值:读数低于它算有火(analogRead 范围 0~1023)
void setup() {
Serial.begin(115200);
pinMode(FLAME_DIGITAL, INPUT); // D 口是"输入"
pinMode(LED_PIN, OUTPUT); // 报警灯是"输出"
// 上电先标定:看看正常环境和有火焰时读数各是多少
Serial.println("=== 阈值标定 ===");
Serial.println("正常环境读数:");
for (int i = 0; i < 5; i++) {
Serial.println(analogRead(FLAME_ANALOG)); // 连打 5 次基准值
delay(500);
}
Serial.println("现在把火焰靠近传感器...");
delay(3000); // 留 3 秒点火时间
for (int i = 0; i < 5; i++) {
Serial.println(analogRead(FLAME_ANALOG)); // 再连打 5 次火焰值
delay(500);
}
Serial.println("=== 开始检测 ===");
}
void loop() {
int analogVal = analogRead(FLAME_ANALOG); // 读模拟值(0~1023)
int digitalVal = digitalRead(FLAME_DIGITAL); // 读数字值(0 或 1)
Serial.print("A口=");
Serial.print(analogVal);
Serial.print(" D口=");
Serial.print(digitalVal);
if (analogVal < THRESHOLD || digitalVal == 1) {
// 模拟值够小(火焰够近)"或"数字口触发——任何一个都算有火焰
digitalWrite(LED_PIN, HIGH); // 点亮报警灯
Serial.println(" ⚠️ 检测到火焰!");
} else {
digitalWrite(LED_PIN, LOW); // 熄灭报警灯
Serial.println(" 正常");
}
delay(300); // 每 0.3 秒检测一次
}代码讲解
这段代码几乎是全册知识点的"毕业汇演",逐个认一认:
analogRead(26):读 GP26 的模拟电压,返回 0~1023。注意:第二册 Python 的read_u16()返回 0~65535,两个量程不同,阈值不能照抄setup()里的标定流程:先测无火焰的基准值(比如 5 左右),再测有火焰的值(比如跌到 1 以下),阈值取中间——方法和第二册一模一样loop()里的判断analogVal < THRESHOLD || digitalVal == 1:第 4 章的逻辑运算符||(或)实战——模拟值够小(火焰够近)或数字触发,都报警,双保险- 剩下的
pinMode/digitalWrite/Serial.print/delay,全是前面章节的老朋友
运行效果
- 无火焰:A 口读数较高(约 5),D 口为 0,板载 LED 灭,串口打印"正常"
- 火焰靠近:A 口读数骤降(小到 1 左右),D 口变 1,板载 LED 点亮,串口打印"⚠️ 检测到火焰!"
常见坑
- 方向记反:以为"火越大读数越大"——其实相反,火越近读数越小。判断写成
>会导致有火不报警、没火乱报警 - 无火时读数不是顶格的 1023:室内有灯光、阳光等人眼看不见的红外线,没火焰也有一定读数,这是正常的,不是模块坏了
- D 口一直是 1:模块灵敏度太高,逆时针调模块上的电位器
- 读数波动大:避开白炽灯等强红外光源(火焰传感器对红外线敏感,不止火焰会让它误报)
- 阈值对不上:第二册阈值是 100(0~65535 量程),本册是 3(0~1023 量程)——量程不同,别直接照抄
安全提醒
- 火焰测试必须有成人陪同,远离易燃物
- 每次点火 1~2 秒即可,不要把火焰贴着探头
想一想
第二册阈值 100(量程 0~65535)和本册阈值 3(量程 0~1023),验算一下:它们对应的是不是差不多同一个电压?
💡 查看答案
算一算比例:
- Python:100 ÷ 65535 ≈ 0.0015,× 3.3V ≈ 0.005V
- C++:3 ÷ 1023 ≈ 0.0029,× 3.3V ≈ 0.010V
很接近(都在 0.01V 量级),基本对应同一个电压——阈值这个东西本来就是标定出来的经验值,差一点没关系。
如果想分三级报警(读数 < 2 危险、2~4 注意、> 4 安全),判断部分该怎么改?(提示:第 4 章的
else if)💡 查看答案
cppif (analogVal < 2) { Serial.println("危险!"); } else if (analogVal <= 4) { Serial.println("注意"); } else { Serial.println("安全"); }注意顺序:范围最小的(最严格的)条件放前面,从小到大排。
如果把板载 LED 换成蜂鸣器报警,代码里要改哪几行?(提示:回顾第 8 章)
💡 查看答案
只需把"灯"换成"蜂鸣器",改三处:
- 引脚定义:
const int LED_PIN = 25;改成蜂鸣器实际接的引脚,比如const int BEEP_PIN = 15; setup()里的pinMode(LED_PIN, OUTPUT)对应改名(仍然是输出)loop()里两处digitalWrite改成控制蜂鸣器——高电平蜂鸣器响,低电平安静
写法和第 8 章控灯一模一样,只是控制的器件换了。
- 引脚定义:
