【CanMV K210】传感器实验 火焰传感器检测与火焰报警
火焰检测类实验很适合作为 AI 硬件课程中的安全感知入门案例。它不像 LED 实验那样只负责输出状态,而是让开发板开始读取外部环境变化。传感器前方是否存在火焰,会通过数字电平和模拟电压变化反馈到程序中,代码再根据这些数据判断当前环境是否安全。
本实验使用 CanMV K210 开发板读取火焰传感器的 DO 和 AO 两种信号。DO 作为主要判断依据,直接接入 GPIO 输入引脚,用来判断是否检测到火焰;AO 作为辅助观察数据,通过 PCF8591 模数转换模块读取,用来观察火焰强弱或环境变化趋势。程序运行后,串口会持续输出安全状态或火焰警告信息,当检测状态发生变化时,会打印更明显的提示内容。
| 学习目标 | 说明 |
|---|---|
| 理解火焰传感器信号 | 区分 DO 数字输出和 AO 模拟输出的作用 |
| 掌握 GPIO 输入检测 | 使用 GPIOHS0 读取火焰传感器 DO 高低电平 |
| 掌握 PCF8591 模拟采样 | 通过 I2C 读取火焰传感器 AO 模拟量 |
| 理解稳定判断逻辑 | 通过多次采样平均和多数投票降低误报警概率 |
| 建立安全感知思路 | 将传感器输入、状态判断和报警处理拆成可扩展结构 |
这个实验的重点不是制造火焰场景,而是理解“环境信号如何进入程序”。实验过程中应使用安全、可控、短时间的测试方式,避免长时间明火、靠近易燃物、强光直射或无人看管。火焰传感器实验只能作为教学演示和基础检测案例,不能替代真实消防报警设备。
理论基础
火焰传感器通常会同时提供数字输出和模拟输出。DO 数字输出经过模块上的比较电路处理,结果只有高电平和低电平两种状态,适合快速判断是否触发报警。AO 模拟输出保留了传感器原始变化趋势,电压会随着火焰强弱、距离、角度、环境光发生变化,适合观察数据变化,但不能直接由普通数字 GPIO 精确读取。
CanMV K210 的 GPIO 可以读取高低电平,因此适合读取 DO。AO 属于模拟量,需要先通过 PCF8591 这类 ADC 模块转换成数字值,再由程序通过 I2C 总线读取。这样一来,DO 用来做主要报警判断,AO 用来辅助观察环境变化,两种信号配合使用,比单独读取一个引脚更适合教学调试。
本实验中,火焰传感器 DO 接到 CanMV 的物理引脚 8,并映射为 GPIOHS0 输入。火焰传感器 AO 接到 PCF8591 的 AIN0,CanMV 通过物理引脚 6 和物理引脚 7 建立 I2C 软件总线,读取 PCF8591 转换后的模拟采样值。程序中设置 FIRE_LEVEL = 0,表示当前模块按照“检测到火焰时 DO 输出低电平”的逻辑处理。
这张流程图展示的是火焰传感器实验的电路和数据链路。火焰传感器负责感知环境变化,DO 提供明确的开关量结果,AO 提供连续变化的模拟量结果。CanMV K210 一边通过 GPIO 读取 DO,一边通过 PCF8591 读取 AO,程序再把两类数据组合成安全状态或报警状态。
火焰传感器容易受到环境光、火焰距离、传感器角度和模块灵敏度影响。DO 触发阈值通常可以通过模块上的电位器调节,AO 数值则更适合用来观察变化趋势。实际调试时,DO 更适合作为报警依据,AO 更适合作为辅助参考,不建议只凭单次 AO 数值直接判断火焰状态。
硬件设施
本实验围绕火焰传感器、CanMV K210 开发板、PCF8591 模数转换模块和 I2C 通信展开。代码没有直接控制 LED、蜂鸣器、LCD 或摄像头,因此这些模块不作为当前实验的实际功能讲解内容。火焰传感器的 DO 直接给出高低电平,适合做报警判断;AO 输出模拟电压,需要借助 PCF8591 转换为数字值后才能被程序读取。
接线关系可以通过下面这张图建立整体印象。火焰传感器 DO 接入 CanMV 物理引脚 8,AO 接入 PCF8591 的 AIN0;PCF8591 再通过 SCL 和 SDA 与 CanMV 通信。实验通电前需要重点核对 VCC、GND、DO、AO、SCL、SDA,避免把模拟输出、数字输出或电源线接错。

| 硬件 / 软件 | 作用 | 说明 |
|---|---|---|
| CanMV K210 开发板 | 实验运行平台 | 负责执行 MicroPython 程序,读取 GPIO 数字信号和 I2C 模拟采样数据 |
| 火焰传感器 | 环境检测模块 | DO 输出数字信号,AO 输出模拟信号,用于检测传感器前方火焰变化 |
| PCF8591 | 模数转换模块 | 将火焰传感器 AO 模拟量转换为程序可读取的数字值 |
| 物理引脚 8 | 火焰数字输入引脚 | 火焰传感器 DO 接到该引脚,并映射为 GPIOHS0 |
| 物理引脚 6 | I2C 时钟线 | 作为 PCF8591 的 SCL 连接线 |
| 物理引脚 7 | I2C 数据线 | 作为 PCF8591 的 SDA 连接线 |
maix.GPIO |
GPIO 控制模块 | 用于创建火焰传感器 DO 数字输入对象 |
machine.I2C |
I2C 通信模块 | 用于建立开发板与 PCF8591 之间的数据通信 |
fpioa_manager.fm |
引脚功能映射模块 | 用于将物理引脚 8 注册为 GPIOHS0 |
pcf8591 |
ADC 读取驱动 | 用于读取 PCF8591 指定通道的模拟采样值 |
time |
延时控制模块 | 用于控制采样间隔和多次读取之间的短暂等待 |
实验中用到的核心零件如下。火焰传感器负责检测火焰或强红外变化,PCF8591 负责读取 AO 模拟信号,CanMV K210 负责运行检测程序并输出状态信息。测试时不建议让火焰长时间靠近模块,也不建议在桌面杂物、纸张、导线密集区域进行明火测试。

接线关系需要结合代码中的常量配置、fm.register()、I2C()、GPIO() 和 pcf8591.PCF8591() 进行判断。当前代码明确写出了 DO、SCL、SDA 和 ADC 通道,因此可以整理出火焰传感器与开发板、PCF8591 之间的连接关系。AO 不直接进入 K210 的 GPIO,而是接入 PCF8591 的 AIN0,再由 I2C 读取转换后的数字值。
| 信号 / 接口 | 连接位置 | 代码变量 | 对应硬件 | 说明 |
|---|---|---|---|---|
| DO | 物理引脚 8 | FLAME_DO_PIN、flame_do |
火焰传感器数字输出 | 检测到火焰时通常输出低电平,作为主要报警依据 |
| AO | PCF8591 AIN0 | ADC_CHANNEL = 0、flame_adc |
火焰传感器模拟输出 | 用于读取火焰强弱变化或环境变化趋势 |
| SCL | 物理引脚 6 | I2C_SCL_PIN |
PCF8591 时钟线 | 用于 I2C 软件总线时钟信号 |
| SDA | 物理引脚 7 | I2C_SDA_PIN |
PCF8591 数据线 | 用于 I2C 软件总线数据信号 |
| GPIOHS0 | 物理引脚 8 映射得到 | GPIO.GPIOHS0 |
DO 数字输入 | 程序通过该 GPIO 读取火焰传感器数字状态 |
| GPIOHS1 | I2C 软件总线映射 | gscl=fm.fpioa.GPIOHS1 |
I2C SCL 功能 | 作为软件 I2C 的时钟功能引脚 |
| GPIOHS2 | I2C 软件总线映射 | gsda=fm.fpioa.GPIOHS2 |
I2C SDA 功能 | 作为软件 I2C 的数据功能引脚 |
| VCC | 模块供电 | 无 | 火焰传感器与 PCF8591 | 按模块标识接入对应供电端 |
| GND | 公共地线 | 无 | CanMV、火焰传感器与 PCF8591 | 保证数字输入和模拟采样具有统一参考电平 |
完成接线后的整体状态如下。检查时应重点确认 DO 是否接到物理引脚 8,AO 是否接到 PCF8591 AIN0,SCL/SDA 是否分别接到物理引脚 6 和物理引脚 7。模块若出现明显发热、焦味、供电异常或串口反复报错,应立即断电检查接线。

| 实验现象 | 正常表现 | 异常提示 |
|---|---|---|
| 程序启动 | 串口输出初始化完成信息 | 没有输出时检查脚本运行和串口连接 |
| 安全状态 | 串口周期性输出安全状态和 AO 模拟值 | 安全状态下频繁误报警时检查环境光和 DO 触发阈值 |
| 火焰靠近 | 串口输出醒目的火焰警告信息 | 没有反应时检查 DO 接线、模块灵敏度和火焰距离 |
| AO 数值变化 | 火焰距离或角度变化时,AO 模拟值发生变化 | AO 不变化时检查 AO 到 AIN0 的接线 |
| DO 状态变化 | 火焰触发时 DO 电平进入 FIRE_LEVEL |
DO 逻辑相反时需要调整 FIRE_LEVEL 和 SAFE_LEVEL |
| 模块发热 | 正常情况下模块不应明显发烫 | 立即断电检查 VCC、GND、接线短路和供电电压 |
软件代码
本实验代码围绕火焰传感器的双通道读取展开。程序通过 GPIO 读取 DO 数字信号,通过 PCF8591 读取 AO 模拟值,并对 DO 做多次采样稳定判断,减少瞬间抖动导致的误报警。主循环持续采集传感器数据,状态变化时输出明显提示,安全状态下控制打印频率,避免串口内容过度刷屏。
| 软件环境 | 作用 | 检查重点 |
|---|---|---|
| CanMV IDE | 编辑、运行和调试 K210 程序 | 能识别开发板串口,并能运行基础 print() 测试 |
| CanMV 固件 | 提供 maix.GPIO、machine.I2C 和 fpioa_manager 模块 |
固件环境需要支持 GPIO 输入、I2C 软件总线和 FPIOA 映射 |
| USB 串口驱动 | 让电脑识别开发板串口 | 串口工具中能看到对应端口 |
pcf8591.py |
PCF8591 驱动文件 | 需要与主程序放在同一运行目录,确保可以 import pcf8591 |
| 串口终端 | 查看检测结果 | 能看到安全状态、火焰报警状态和 AO 模拟采样值 |
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
CanMV K210 火焰传感器实验 Demo
实验说明:
火焰传感器通常同时提供 AO 和 DO 两种输出。
AO:模拟量输出,可通过 PCF8591 读取,用来观察火焰强弱变化。
DO:数字量输出,可直接通过 GPIO 读取,用来判断是否检测到火焰。
本 Demo 以 DO 作为主要报警判断依据,以 AO 作为辅助观察数据。
"""
import time
from maix import GPIO
from machine import I2C
from fpioa_manager import fm
import pcf8591
# =========================
# 硬件配置区
# =========================
FLAME_DO_PIN = 8 # 火焰传感器 DO 接到开发板物理引脚 8
I2C_SCL_PIN = 6 # PCF8591 SCL
I2C_SDA_PIN = 7 # PCF8591 SDA
ADC_CHANNEL = 0 # 火焰传感器 AO 接 PCF8591 的 AIN0
FIRE_LEVEL = 0 # 大多数火焰模块检测到火焰时 DO 输出低电平
SAFE_LEVEL = 1 # 未检测到火焰时 DO 输出高电平
SAMPLE_INTERVAL_MS = 200 # 采样间隔
STABLE_SAMPLE_COUNT = 5 # 稳定判断采样次数
# =========================
# 全局对象
# =========================
flame_do = None
flame_adc = None
# =========================
# 初始化
# =========================
def setup():
"""初始化 GPIO 与 PCF8591"""
global flame_do
global flame_adc
fm.register(FLAME_DO_PIN, fm.fpioa.GPIOHS0, force=True)
i2c = I2C(
I2C.I2C_SOFT,
freq=400000,
scl=I2C_SCL_PIN,
sda=I2C_SDA_PIN,
gscl=fm.fpioa.GPIOHS1,
gsda=fm.fpioa.GPIOHS2
)
flame_do = GPIO(GPIO.GPIOHS0, GPIO.IN, GPIO.PULL_UP)
flame_adc = pcf8591.PCF8591(i2c)
print("火焰传感器初始化完成")
print("AO -> PCF8591 AIN0")
print("DO -> GPIOHS0")
print("--------------------------------")
# =========================
# 读取函数
# =========================
def read_flame_adc(samples=5):
"""
多次读取 AO 模拟值并取平均值
这样可以减少瞬间抖动,让显示结果更稳定
"""
total = 0
for _ in range(samples):
total += flame_adc.read(ADC_CHANNEL)
time.sleep_ms(10)
return total // samples
def read_flame_do_stable(samples=5):
"""
多次读取 DO 数字信号
通过多数结果判断当前状态,降低误触发概率
"""
fire_count = 0
for _ in range(samples):
if flame_do.value() == FIRE_LEVEL:
fire_count += 1
time.sleep_ms(10)
if fire_count > samples // 2:
return FIRE_LEVEL
return SAFE_LEVEL
def is_fire_detected():
"""判断是否检测到火焰"""
return read_flame_do_stable(STABLE_SAMPLE_COUNT) == FIRE_LEVEL
# =========================
# 状态提示
# =========================
def print_safe(adc_value):
"""安全状态提示"""
print("状态:安全 | AO模拟值:%d | 未检测到火焰" % adc_value)
def print_fire(adc_value):
"""火焰状态提示"""
print("")
print("================================")
print("警告:检测到火焰!")
print("AO模拟值:%d" % adc_value)
print("请立即检查传感器前方环境")
print("================================")
print("")
def on_fire_alarm(adc_value):
"""
火焰报警处理函数
后续可在这里扩展:
控制蜂鸣器报警
控制 LED 闪烁
上传检测结果
显示屏显示警告信息
"""
print_fire(adc_value)
def on_safe_status(adc_value):
"""安全状态处理函数"""
print_safe(adc_value)
# =========================
# 主循环
# =========================
def loop():
"""
持续读取火焰传感器数据
状态变化时输出明显提示
状态未变化时只打印简洁数据
"""
last_status = None
safe_print_count = 0
while True:
adc_value = read_flame_adc()
fire_detected = is_fire_detected()
current_status = "fire" if fire_detected else "safe"
if current_status != last_status:
if fire_detected:
on_fire_alarm(adc_value)
else:
on_safe_status(adc_value)
last_status = current_status
safe_print_count = 0
else:
if fire_detected:
print("持续报警中 | AO模拟值:%d" % adc_value)
else:
safe_print_count += 1
# 安全状态下不需要每次都刷屏,隔一段时间打印一次即可
if safe_print_count >= 10:
print_safe(adc_value)
safe_print_count = 0
time.sleep_ms(SAMPLE_INTERVAL_MS)
# =========================
# 程序入口
# =========================
if __name__ == '__main__':
try:
setup()
loop()
except KeyboardInterrupt:
print("程序已停止")
这段代码可以理解成三个层级。底层是 setup(),负责完成 DO 引脚映射、GPIO 输入对象创建、I2C 总线初始化和 PCF8591 对象创建;中间层是 read_flame_adc()、read_flame_do_stable() 和 is_fire_detected(),负责把原始 AO/DO 信号转换成稳定数据;上层是 on_fire_alarm()、on_safe_status() 和 loop(),负责把检测结果转换成串口提示和后续报警入口。
硬件配置区把 DO 引脚、I2C 引脚、ADC 通道、电平判断规则、采样间隔和稳定采样次数集中放在一起。后续调整接线或模块逻辑时,不需要在程序中到处查找参数。若实际火焰传感器为高电平触发,只需要调整 FIRE_LEVEL 和 SAFE_LEVEL,主循环和报警处理逻辑不需要重写。
read_flame_adc() 负责读取模拟量。函数内部连续读取多次 PCF8591 的 AIN0 数据,并通过平均值减少瞬间波动。火焰传感器 AO 会受到距离、角度、环境光和模块灵敏度影响,单次读取可能出现抖动,多次采样取平均更适合用于串口观察。
read_flame_do_stable() 负责读取数字量。函数不是只读取一次 DO,而是在短时间内读取多次,并统计其中被判断为火焰状态的次数。只要火焰状态数量超过一半,就返回 FIRE_LEVEL。这种多数投票方式能够降低误触发概率,比单次 flame_do.value() 更适合做报警判断。
| 函数名 | 功能 | 对应现象 |
|---|---|---|
setup() |
初始化 GPIO 输入、I2C 总线和 PCF8591 对象 | 串口输出初始化完成信息,传感器进入可读取状态 |
read_flame_adc(samples=5) |
多次读取 AO 模拟值并取平均值 | 串口显示更稳定的 AO 模拟采样数据 |
read_flame_do_stable(samples=5) |
多次读取 DO 数字信号并进行多数判断 | 降低 DO 抖动造成的误报警 |
is_fire_detected() |
判断当前是否检测到火焰 | 返回火焰检测结果,供主循环决定状态 |
print_safe(adc_value) |
输出安全状态提示 | 串口显示“状态:安全”和 AO 模拟值 |
print_fire(adc_value) |
输出火焰报警提示 | 串口打印醒目的火焰警告信息 |
on_fire_alarm(adc_value) |
火焰报警处理入口 | 当前负责打印警告,后续可扩展报警动作 |
on_safe_status(adc_value) |
安全状态处理入口 | 当前负责打印安全状态 |
loop() |
持续采样并根据状态变化输出提示 | 程序持续监测火焰传感器状态 |
KeyboardInterrupt 捕获 |
停止程序时输出提示 | 手动中断后串口显示“程序已停止” |
主循环中使用 last_status 保存上一次状态,这样程序可以在状态变化时输出更明显的提示,而不是每次采样都重复打印完整报警框。安全状态下使用 safe_print_count 控制打印频率,每隔一段时间输出一次安全信息,避免串口被大量重复内容刷屏。火焰状态下则持续打印报警信息,确保异常状态不会被忽略。
扩展应用
火焰传感器实验同时涉及数字输入、模拟采样和 I2C 通信,排查问题时需要分清是 DO 判断异常,还是 AO 数据读取异常。DO 更适合判断是否触发,AO 更适合观察趋势,两个通道的作用不同,调试时不应混在一起判断。
| 问题现象 | 可能原因 | 处理思路 |
|---|---|---|
| 程序一直显示安全 | 火焰传感器 DO 未触发、接线错误、模块灵敏度偏低 | 检查 DO 是否接到物理引脚 8,调整传感器模块电位器,确认测试距离在有效范围内 |
| 程序一直显示火焰警告 | DO 输出逻辑与代码相反、传感器受到强光干扰、输入引脚悬空 | 尝试交换 FIRE_LEVEL 和 SAFE_LEVEL,检查 DO 接线和上拉配置,避开强光直射 |
| AO 模拟值始终不变化 | AO 没有接到 PCF8591 AIN0、I2C 通信异常、读取通道不匹配 | 核对 AO 到 AIN0 的接线,确认 ADC_CHANNEL = 0 与实际通道一致 |
| AO 模拟值波动明显 | 环境光变化、传感器距离不稳定、采样次数偏少 | 适当增加 read_flame_adc(samples=5) 的采样次数,保持传感器位置稳定 |
| 程序启动后报 I2C 或 PCF8591 错误 | SCL、SDA 接线错误,PCF8591 供电异常,驱动文件缺失 | 检查 SCL 是否接物理引脚 6,SDA 是否接物理引脚 7,确认 pcf8591.py 可正常导入 |
| 报警反应太慢 | 稳定采样次数和采样间隔偏大 | 适当降低 STABLE_SAMPLE_COUNT 或 SAMPLE_INTERVAL_MS,但过低可能增加误触发 |
| 串口输出太频繁 | 采样间隔过短或报警状态持续存在 | 增大 SAMPLE_INTERVAL_MS,或调整安全状态打印计数逻辑 |
| 模块明显发热 | VCC/GND 接反、供电异常、线路短接 | 立即断电检查,不要继续使用明火测试 |
| 明火测试风险较高 | 测试环境存在纸张、塑料线材、易燃物或无人看管 | 使用短时间、可控距离测试,远离易燃物,实验后及时熄灭火源 |
火焰传感器实验的价值不只是读取一个高低电平,而是建立“环境变化到程序判断”的完整链路。DO 通道让程序获得明确的报警状态,AO 通道提供更细致的变化数据,主循环负责持续监测,状态处理函数负责把检测结果转化成提示动作。这种结构可以自然扩展到安全监测、设备保护、教学演示和物联网数据采集等场景。
| 应用场景 | 实现思路 | 可扩展能力 |
|---|---|---|
| 火焰安全监测 | 使用 DO 判断是否检测到火焰,AO 观察环境变化趋势 | 可扩展为实验室、设备间或教学场景中的基础安全提醒 |
| 设备异常保护 | 当检测到火焰状态时,程序进入报警分支 | 后续可扩展继电器或电源控制,实现设备保护动作 |
| 声光报警系统 | 当前代码已预留 on_fire_alarm() 报警入口 |
后续可扩展蜂鸣器和 LED 闪烁,形成声光提示 |
| 传感器数据教学 | 通过 AO 和 DO 对比,理解模拟量与数字量的区别 | 可用于讲解 ADC、阈值、电平判断和采样稳定性 |
| 物联网状态上报 | 将火焰检测结果作为设备状态数据 | 后续可扩展 Wi-Fi、MQTT 或 HTTP 上传检测结果 |
| 屏幕可视化显示 | 当前串口输出可替换为屏幕状态显示 | LCD 可显示 AO 数值和报警状态 |
| 多传感器融合 | 火焰检测可与温度、烟雾等数据组合判断 | 后续可扩展更多传感器,提高异常判断可靠性 |
| 安全教学案例 | 通过短时间可控测试演示安全感知流程 | 可结合课程讲解输入信号、状态判断和报警处理边界 |
从工程角度看,当前代码已经把采集、判断和处理动作拆开。read_flame_adc() 负责模拟量读取,is_fire_detected() 负责状态判断,on_fire_alarm() 负责报警处理入口。这样的结构方便后续扩展,不需要破坏主循环逻辑。例如增加蜂鸣器时,只需要在 on_fire_alarm() 中加入蜂鸣器控制;增加屏幕显示时,可以在安全状态和报警状态处理函数中更新显示内容;增加网络上报时,也可以把当前状态和 AO 数值封装成数据包发送出去。
总结
本实验通过 CanMV K210 开发板完成了火焰传感器的数据读取与状态判断,核心能力包括 GPIO 输入、FPIOA 引脚映射、I2C 软件总线、PCF8591 模拟采样、数字电平判断、多次采样平均、多数投票防抖和主循环状态调度。DO 提供快速明确的火焰判断结果,AO 提供辅助观察数据,两种信号配合使用,比单纯读取一个引脚更适合教学和调试。
这类传感器实验是硬件编程从“控制外设”走向“感知环境”的关键一步。代码中的变量不再只是内存里的数据,而是来自真实传感器的环境反馈。实验过程中必须重视火源和接线安全,测试火焰应短时间、可控距离、远离易燃物,模块发热或供电异常时立即断电检查。后续课程可以在当前结构基础上继续扩展蜂鸣器报警、LED 状态灯、LCD 显示、无线数据上传、多传感器融合和 AI 摄像头识别等内容。
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐

所有评论(0)