我用 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 秒休眠逻辑
程序没有把一次低电平直接判断为"人已经离开",而是维护一个最后活动时间。
当前实现包含三层缓冲:
- 上电预热 30 秒,让 PIR 和环境状态稳定;
- PIR、屏幕触摸、交互板电容触摸,任一输入都刷新活动时间;
- 连续 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_high、screen_touch 和 board_touch,确认每种输入都能独立刷新 last_active_ms。这样可以快速判断是传感器、触摸驱动,还是状态合并逻辑出了问题。
六、怎样减少误睡
方案一:延长超时
把 60 秒改为 3~5 分钟,成本最低。缺点是人离开后屏幕也会多亮一段时间。
c
#define IDLE_TIMEOUT_MS (3 * 60 * 1000)
方案二:融合已有交互
把屏幕触摸、板上电容触摸、按键或上位机活动统一视为"用户仍在",比只依赖 PIR 更符合桌宠场景。
方案三:优化传感器位置
让常见动作横向穿过 PIR 感应区,并减少桌面和显示器遮挡。硬件位置调整常常比继续堆软件阈值更有效。
方案四:更换存在检测方案
如果目标是确认"人一直坐着",PIR 本身就不是最合适的单一传感器:
| 方案 | 优势 | 代价与限制 |
|---|---|---|
| 毫米波雷达 | 能感知细微运动,更适合静态存在 | 成本、功耗、调参复杂度更高 |
| ToF 测距 | 可判断固定方向是否有物体 | 不能天然确认物体是不是人 |
| 摄像头视觉 | 信息量最大 | 算力、功耗、遮挡与隐私成本高 |
| PIR + 触摸等输入 | 成本低,能复用现有硬件 | 仍属于间接推断 |
七、这次排错真正解决了什么
"人体感应器"这个日常叫法,很容易让人误以为它能持续输出"有人"。但从物理层看,PIR 检测的是红外能量的变化;从程序层看,我们拿到的只是一个高低电平,再依据最近一次触发时间推测是否有人活动。
因此,桌宠在人静坐时睡着,并不必然说明硬件或代码坏了。更准确的结论是:当前传感器解决的是运动检测,而产品需求逐渐变成了持续存在检测。
理解这个差异以后,60 秒就不再是一个神秘故障,而只是一个需要按场景调整的设计参数。
我是阿白,感谢你的观看。