火焰检测类实验很适合作为 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 物理引脚 8
GPIOHS0 输入

PCF8591 AIN0
ADC 模拟采样

I2C 总线
SCL=IO6 / SDA=IO7

程序读取 DO
多数投票稳定判断

程序读取 AO
多次采样取平均值

状态判断
safe / fire

状态处理
安全提示 / 火焰报警 / 后续扩展

安全注意
短时间测试 / 远离易燃物 / 异常发热立即断电

这张流程图展示的是火焰传感器实验的电路和数据链路。火焰传感器负责感知环境变化,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 负责运行检测程序并输出状态信息。测试时不建议让火焰长时间靠近模块,也不建议在桌面杂物、纸张、导线密集区域进行明火测试。

火焰传感器、PCF8591 与连接线零件图

接线关系需要结合代码中的常量配置、fm.register()I2C()GPIO()pcf8591.PCF8591() 进行判断。当前代码明确写出了 DO、SCL、SDA 和 ADC 通道,因此可以整理出火焰传感器与开发板、PCF8591 之间的连接关系。AO 不直接进入 K210 的 GPIO,而是接入 PCF8591 的 AIN0,再由 I2C 读取转换后的数字值。

信号 / 接口 连接位置 代码变量 对应硬件 说明
DO 物理引脚 8 FLAME_DO_PINflame_do 火焰传感器数字输出 检测到火焰时通常输出低电平,作为主要报警依据
AO PCF8591 AIN0 ADC_CHANNEL = 0flame_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。模块若出现明显发热、焦味、供电异常或串口反复报错,应立即断电检查接线。

CanMV K210 火焰传感器实验成品图

实验现象 正常表现 异常提示
程序启动 串口输出初始化完成信息 没有输出时检查脚本运行和串口连接
安全状态 串口周期性输出安全状态和 AO 模拟值 安全状态下频繁误报警时检查环境光和 DO 触发阈值
火焰靠近 串口输出醒目的火焰警告信息 没有反应时检查 DO 接线、模块灵敏度和火焰距离
AO 数值变化 火焰距离或角度变化时,AO 模拟值发生变化 AO 不变化时检查 AO 到 AIN0 的接线
DO 状态变化 火焰触发时 DO 电平进入 FIRE_LEVEL DO 逻辑相反时需要调整 FIRE_LEVELSAFE_LEVEL
模块发热 正常情况下模块不应明显发烫 立即断电检查 VCC、GND、接线短路和供电电压

软件代码

本实验代码围绕火焰传感器的双通道读取展开。程序通过 GPIO 读取 DO 数字信号,通过 PCF8591 读取 AO 模拟值,并对 DO 做多次采样稳定判断,减少瞬间抖动导致的误报警。主循环持续采集传感器数据,状态变化时输出明显提示,安全状态下控制打印频率,避免串口内容过度刷屏。

软件环境 作用 检查重点
CanMV IDE 编辑、运行和调试 K210 程序 能识别开发板串口,并能运行基础 print() 测试
CanMV 固件 提供 maix.GPIOmachine.I2Cfpioa_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_LEVELSAFE_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_LEVELSAFE_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_COUNTSAMPLE_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 摄像头识别等内容。

Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐