ESP-Mosaico 桌宠为什么会误睡?AS312 PIR 原理、休眠逻辑与排错方法

我用 ESP-Mosaico 和 Interaction V0.2 交互板做了一个"有人靠近才醒来"的桌面小精灵:检测到活动时睁眼并亮灯;一段时间没有活动,先进入困倦表情,再关闭屏幕。

实测时出现了一个容易被误判为 Bug 的现象:人还坐在桌前,小精灵有时却睡着了。

原因不一定是漏读,也不一定是 PIR 损坏。关键在于:PIR 检测的是热红外变化,不是持续的人体存在。

一、Interaction V0.2 上的 PIR 是什么

交互板正面下方的白色半球不是摄像头,而是 PIR 的菲涅尔透镜。透镜后面是原理图标注的 AS312 数字式热释电红外传感器

菲涅尔透镜把前方空间划分成多个感应区域,并把不同方向的红外能量集中到热释电元件。人体移动、跨过这些区域时,传感器接收到的红外能量发生变化,AS312 经过内部滤波和比较后输出数字电平。

Interaction V0.2 原理图中的关键信息如下:

项目 配置
PIR 型号 AS312
供电 3.3 V
传感器输出 REL
板级信号 PIR_DAT
插在右侧 H1 GPIO5
插在左侧 H2 GPIO4

因此,换插槽后如果仍读取原来的 GPIO,就会表现为"PIR 完全没反应"。

二、PIR 真正检测的是什么

PIR 是 Passive Infrared,也就是被动红外。它不主动发射无线电波,不测距离,也不会生成图像,只接收环境中的红外变化。

可以把完整链路简化为:

text 复制代码
人体移动
→ 不同感应区的红外能量发生变化
→ 热释电元件产生微弱电信号
→ AS312 内部滤波、比较
→ REL 输出高电平
→ ESP32-S31 记录"最近发生过活动"

AS312 的输出高电平时间约为 2.3 秒。一次动作触发后,即使人还在原地,如果没有新的有效变化,输出仍会回到低电平。

所以,正确的电平解释应该是:

读数 更准确的含义 不能直接推出
PIR=1 最近出现了满足阈值的红外变化 一定是人、人数、距离
PIR=0 当前没有新的有效红外变化 房间里一定没人

三、为什么静坐的人会"消失"

热释电器件对变化敏感,对稳定状态不敏感。人刚走到桌前时会跨过多个感应区,很容易触发;坐下后,如果只看屏幕或做幅度很小的动作,红外分布逐渐稳定,PIR 就可能不再产生新触发。

下面这些条件会进一步降低触发概率:

  • 身体动作太小,没有明显跨过透镜形成的感应区;
  • 人正对传感器缓慢靠近或远离,而不是横向移动;
  • 显示器、桌面、衣物或外壳遮挡人体红外;
  • 环境温度接近人体表面温度,人与背景的红外对比下降;
  • 安装方向没有覆盖上半身和手臂活动区域;
  • 在透镜前加了普通玻璃或亚克力,削弱了长波红外。

四、桌宠的 60 秒休眠逻辑

程序没有把一次低电平直接判断为"人已经离开",而是维护一个最后活动时间。

当前实现包含三层缓冲:

  1. 上电预热 30 秒,让 PIR 和环境状态稳定;
  2. PIR、屏幕触摸、交互板电容触摸,任一输入都刷新活动时间;
  3. 连续 60 秒无活动后进入困倦,约 2 秒后关闭屏幕。

核心逻辑可以简化为:

c 复制代码
bool active = pir_ready && pir_high;
active = active || screen_touch || board_touch;

if (active) {
    last_active_ms = now_ms;
}

if (now_ms - last_active_ms >= 60000) {
    enter_drowsy();
}

这里的 60 秒是应用层容错时间,不是 PIR 的检测时长。程序用长计时器把零散动作连接成"最近有人活动"。

当前的"睡眠"也只是界面休眠:屏幕进入 Sleep In,ESP32-S31、PIR、RGB 灯和触摸检测仍然运行,并非 MCU Deep Sleep。因此,重新检测到动作或触摸后仍能唤醒屏幕。

五、排错顺序

遇到"人靠近但桌宠不醒"时,建议按以下顺序排查。

1. 先确认插槽和 GPIO

  • 右侧 H1:GPIO5;
  • 左侧 H2:GPIO4。

不要只看丝印方向,要对照原理图和程序的板卡位置配置。

2. 给 PIR 留出预热时间

上电后的前 30 秒先不要据此判断硬件异常。可以在屏幕或串口输出倒计时,明确区分"预热中"和"正常检测"。

3. 直接打印原始电平和时间戳

c 复制代码
printf("pir=%d, now=%lu, idle=%lu\n",
       gpio_get_level(PIR_GPIO),
       now_ms,
       now_ms - last_active_ms);

先验证原始 GPIO 是否变化,再检查状态机和界面。不要一开始就把问题归因于动画。

4. 横向移动测试

在传感器前横向走动或挥手,比正对传感器缓慢前后移动更容易跨过多个感应区,也更适合验证 PIR 是否正常。

5. 检查遮挡与安装角度

让白色透镜正对上半身或手臂常活动区域,前方不要有普通玻璃、亚克力、显示器边框等遮挡。

6. 分开验证三种活动输入

分别记录 pir_highscreen_touchboard_touch,确认每种输入都能独立刷新 last_active_ms。这样可以快速判断是传感器、触摸驱动,还是状态合并逻辑出了问题。

六、怎样减少误睡

方案一:延长超时

把 60 秒改为 3~5 分钟,成本最低。缺点是人离开后屏幕也会多亮一段时间。

c 复制代码
#define IDLE_TIMEOUT_MS (3 * 60 * 1000)

方案二:融合已有交互

把屏幕触摸、板上电容触摸、按键或上位机活动统一视为"用户仍在",比只依赖 PIR 更符合桌宠场景。

方案三:优化传感器位置

让常见动作横向穿过 PIR 感应区,并减少桌面和显示器遮挡。硬件位置调整常常比继续堆软件阈值更有效。

方案四:更换存在检测方案

如果目标是确认"人一直坐着",PIR 本身就不是最合适的单一传感器:

方案 优势 代价与限制
毫米波雷达 能感知细微运动,更适合静态存在 成本、功耗、调参复杂度更高
ToF 测距 可判断固定方向是否有物体 不能天然确认物体是不是人
摄像头视觉 信息量最大 算力、功耗、遮挡与隐私成本高
PIR + 触摸等输入 成本低,能复用现有硬件 仍属于间接推断

七、这次排错真正解决了什么

"人体感应器"这个日常叫法,很容易让人误以为它能持续输出"有人"。但从物理层看,PIR 检测的是红外能量的变化;从程序层看,我们拿到的只是一个高低电平,再依据最近一次触发时间推测是否有人活动。

因此,桌宠在人静坐时睡着,并不必然说明硬件或代码坏了。更准确的结论是:当前传感器解决的是运动检测,而产品需求逐渐变成了持续存在检测。

理解这个差异以后,60 秒就不再是一个神秘故障,而只是一个需要按场景调整的设计参数。

我是阿白,感谢你的观看。

相关推荐
youcans_2 小时前
【嵌入式软件AI编程】08. 第一个STM32工程
stm32·单片机·ai编程·嵌入式软件·claude code
崇山峻岭之间3 小时前
HC32F460PETB的PH2的TIM4_2_CLK
单片机
Brilliantwxx3 小时前
【STM32】 I2C协议和设备主从( 图解 + 面试题 )
stm32·单片机·嵌入式硬件·架构
威嵌神州3 小时前
星载计算机产品方案:商业卫星国产化平台
嵌入式硬件
老当益壮梁奶奶3 小时前
51单片机中断系统详解
c语言·单片机·嵌入式硬件·学习·51单片机
Brilliantwxx3 小时前
【STM32】 I2C 外设内部硬件结构和状态位
开发语言·stm32·单片机·嵌入式硬件
天空'之城12 小时前
单片机基础核心知识点汇总(三十五)
单片机·嵌入式硬件
secondyoung12 小时前
I2C通信协议详解
arm开发·驱动开发·stm32·单片机·嵌入式硬件·mcu·51单片机
anew___12 小时前
蜂鸣器播放音乐——让 Arduino 唱出旋律
c++·stm32·单片机·嵌入式硬件·c