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 读数在数百毫秒内跳变上百个计数——远快于自然光缓变。系统通过两个机制捕捉这种突变:
- RTC 定时采样:每 10 秒唤醒一次,用多次采样取平均更新当前亮度基线,消除工频闪烁和环境噪声。
- ADC 模拟看门狗:在两次定时采样之间,硬件自动监测 ADC 转换结果。一旦采样值超出预设的阈值窗口,立即通过中断唤醒 MCU。
两个机制互补:定时采样保证基线不漂移,模拟看门狗保证突变不遗漏。
状态机设计
系统有两个稳态。
值守态
RTC 闹钟每 10 秒唤醒一次,执行校准流程:连续采样 10 次,经 LLR 滤波器处理后取平均作为当前亮度基线,据此重新设定模拟看门狗阈值窗口——下限为基线值减去 150 个计数,上限为 4095。LLR 滤波器用于抑制工频闪烁和环境光的高频抖动,防止噪声尖峰污染基线值导致误报。随后启动 ADC 连续转换并进入 STOP 睡眠。
当有人遮挡光线导致亮度骤降至阈值下限以下,ADC 模拟看门狗触发 ADC_COMP 中断唤醒 MCU。固件执行二次确认采样,滤除瞬态干扰,确认突变后迁移到告警态。
告警态
进入此态后立即执行两个动作:
- 通过 433MHz 射频发送 3 字节告警帧(OOK 编码,重复 15 次)
- 设置 RTC 超时闹钟(默认 30 分钟),到达后自动发送「告警解除」帧并回到值守态
同时重新配置模拟看门狗阈值——下限为 0,上限为触发时的亮度值加 150 个计数(检测遮挡物移开后光线恢复)。之后进入 STOP 睡眠。唤醒后按来源分别处理:
- AWD 触发(亮度恢复):距告警发出不足 1 秒的触发视为外界瞬态光干扰,丢弃后重新入睡。超过 1 秒则做确认采样,验证亮度确实回升后发送「告警解除」帧,回到值守态。
- RTC 超时:告警持续时长用尽,发送「告警解除」帧,重新采样基线后回到值守态。
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 发射模块。编码方案:
- 逻辑「1」:高电平 950µs,低电平 325µs
- 逻辑「0」:高电平 325µs,低电平 950µs
每帧 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.hex 和 build/Project.bin,通过 SWD 烧录。