PY32F002A 光突变入侵检测传感器:低功耗双源唤醒与 433MHz 无线告警

关于 MCU:PY32F002A 标称 20KB Flash / 3KB RAM,但实际硅片内含 32KB Flash 和 4KB SRAM,以及数据手册未公开的隐藏外设。其内核与外设寄存器布局与 Air001 完全一致,可视为同一颗芯片的不同丝印。本项目基于 Air001 的 HAL 库和启动文件开发,直接运行于 PY32F002A 上无需修改。

一款基于 PY32F002A(Cortex-M0+)MCU 的电池供电光感入侵检测传感器。硅光片持续监测环境光,当有人或物体遮挡光线导致亮度骤变时,通过 433MHz OOK 射频发出无线告警信号。MCU 在 STOP 模式下功耗低于 5µA,由 RTC 闹钟定时校准和 ADC 模拟看门狗双源唤醒,适合长期电池部署。

硬件组成与引脚分配

组件 型号 / 接口 说明
MCU PY32F002A (Cortex-M0+) 32KB Flash / 4KB RAM,最高 48MHz(本项目降频至 4MHz)
光传感器 硅光片,接 PA1 ADC1 通道 1,12 位分辨率
RF 发射 433MHz OOK 模块,接 PA0 软件编码,3 字节告警帧
状态指示 LED,接 PB1 唤醒活动指示
系统时钟 HSI 4MHz → SYSCLK/HCLK/PCLK1 = 4MHz 最低功耗运行,关闭 PLL
低功耗时钟 LSI 32.768kHz → RTC STOP 模式持续运行

PA0 空闲时设为模拟高阻态以消除漏电流。RF 发射模块仅在告警时短暂上电。

检测原理

硅光片输出的电压随环境光照度线性变化。PY32F002A 的 12 位 ADC 将电压转换为 0–4095 的数字量。当有人穿越监控区域遮挡光源,或夜间有人开灯,硅光片接收到的光通量发生突变,ADC 读数在数百毫秒内跳变上百个计数——远快于自然光缓变。系统通过两个机制捕捉这种突变:

  1. RTC 定时采样:每 10 秒唤醒一次,用多次采样取平均更新当前亮度基线,消除工频闪烁和环境噪声。
  2. ADC 模拟看门狗:在两次定时采样之间,硬件自动监测 ADC 转换结果。一旦采样值超出预设的阈值窗口,立即通过中断唤醒 MCU。

两个机制互补:定时采样保证基线不漂移,模拟看门狗保证突变不遗漏。

状态机设计

系统有两个稳态。

值守态

RTC 闹钟每 10 秒唤醒一次,执行校准流程:连续采样 10 次,经 LLR 滤波器处理后取平均作为当前亮度基线,据此重新设定模拟看门狗阈值窗口——下限为基线值减去 150 个计数,上限为 4095。LLR 滤波器用于抑制工频闪烁和环境光的高频抖动,防止噪声尖峰污染基线值导致误报。随后启动 ADC 连续转换并进入 STOP 睡眠。

当有人遮挡光线导致亮度骤降至阈值下限以下,ADC 模拟看门狗触发 ADC_COMP 中断唤醒 MCU。固件执行二次确认采样,滤除瞬态干扰,确认突变后迁移到告警态。

告警态

进入此态后立即执行两个动作:

  1. 通过 433MHz 射频发送 3 字节告警帧(OOK 编码,重复 15 次)
  2. 设置 RTC 超时闹钟(默认 30 分钟),到达后自动发送「告警解除」帧并回到值守态

同时重新配置模拟看门狗阈值——下限为 0,上限为触发时的亮度值加 150 个计数(检测遮挡物移开后光线恢复)。之后进入 STOP 睡眠。唤醒后按来源分别处理:

1 秒消抖窗口解决了一个实际问题:告警发射瞬间的 RF 功率波动可能耦合到模拟前端造成光感读数抖动,误触发二次唤醒。

状态迁移

┌──────────┐   AWD 下降触发    ┌──────────┐
│  值守态   │ ────────────────→ │  告警态   │
│  ARMED   │                   │  ALERT    │
│          │ ←──────────────── │           │
└──────────┘  AWD 恢复 / 超时   └──────────┘
     ↑  │                           ↑  │
     │  │ 10s RTC                   │  │ RTC 超时
     │  │ 校准基线+设AWD              │  │ 或光线恢复
     │  ↓                           │  ↓
     │  STOP 睡眠                    │  STOP 睡眠
     └──────────────────────────────┘

低功耗架构与双源唤醒

系统绝大多数时间处于 STOP 模式。进入 STOP 前关闭所有不必要的外设时钟,仅保留两个可唤醒源:

唤醒源 时钟源 中断通道 典型用途
RTC 闹钟 LSI 32.768kHz EXTI 19 → RTC_IRQ 10 秒定时校准
ADC 模拟看门狗 ADC 异步 HSI 14MHz ADC_COMP_IRQ 光突变实时捕获

Py32F002A 的 RTC 没有独立唤醒定时器,通过时间匹配闹钟实现周期唤醒——每次读当前时分秒、加偏移量后写入闹钟寄存器。LSI 在 STOP 模式下保持振荡,闹钟匹配时通过 EXTI 19 唤醒 MCU。校准闹钟和超时闹钟共用同一硬件,ISR 中通过软件标志位区分来源。

ADC 模拟看门狗是硬件自动比较机制:每次 ADC 转换完成后,硬件比较结果寄存器的值与预设的高低阈值;超出窗口则置位 AWD 标志并产生中断。核心机制是 ADC 时钟选择异步 HSI(14MHz,4 分频到 3.5MHz),该时钟独立于 APB 总线,在 STOP 模式下持续运行。这样 MCU 睡眠期间 ADC 仍然在做连续转换和窗口比较。

433MHz 无线告警协议

告警信号通过软件 bit-bang 方式在 PA0 上输出 OOK(On-Off Keying)调制波形,驱动外部 433MHz 发射模块。编码方案:

每帧 24 位(3 字节),MSB 先发,末尾追加一位「0」尾位。帧间间隔 8750µs,每条指令重复 15 次以提高接收成功率。延时用 Cortex-M0+ 在 4MHz 下的 NOP 循环实现,每轮循环约 4 个周期即 1µs,微秒级精度足以满足 OOK 调制容差。

告警帧和告警解除帧各为 3 字节固定码,接收端通过帧内容区分事件类型。

固件模块划分

Src/
├── main.c                  # 时钟配置与主循环
├── gpio.c                  # PA0(RF TX) / PA1(ADC) / PB1(LED)
├── adc.c                   # ADC 驱动、AWD 阈值配置、校准采样
├── rtc.c                   # RTC 闹钟驱动、周期/超时唤醒管理
├── rf433.c                 # 433MHz OOK 编码与发送
├── app_light_sensor.c      # 状态机编排、STOP 进出、唤醒源分发
├── air001xx_it.c           # ADC_COMP / RTC 中断服务
└── air001xx_hal_msp.c      # HAL 外设 MSP 初始化

app_light_sensor.c 是顶层编排模块:App_LightSensor_Run() 由主循环反复调用,每次处理一次唤醒事件、驱动状态迁移并重新进入 STOP。外设模块仅暴露功能接口,不持有状态机逻辑。这种分层使得更换 MCU 平台时只需替换 HAL 层,上层逻辑无感。

可调参数

参数 默认值 说明
RTC_PERIODIC_WAKEUP_SEC 10 s 定时校准间隔
RTC_ALERT_TIMEOUT_SEC 1800 s 单次告警持续上限
DROP_THRESHOLD 150 光强下降检测阈值(ADC 计数)
RISE_THRESHOLD 150 光强恢复检测阈值
DEBOUNCE_IGNORE_SEC 1 s 告警后瞬态干扰消抖窗口
RF433_REPEAT_COUNT 15 单帧重复次数

构建

项目用 CMake + arm-none-eabi-gcc 构建,依赖 Puya HAL 库。Flash 占用约 17KB / 32KB,RAM 占用约 1.4KB / 4KB。

cmake -B build -G Ninja && ninja -C build

输出 build/Project.hexbuild/Project.bin,通过 SWD 烧录。