先把“有人动过”与“人还在”分开
PIR内部两片热释电区域比较红外变化,人在视野里移动时容易产生差分信号;人坐着不动,信号可能回LOW。本篇解决运动后保持一盏低压指示灯,并不保证静态存在检测。IDLE不能证明房间空,延时调到很长也不会改变传感原理。
固定Adafruit PID189带H/L jumper与TIME/SENS旋钮版本,GPIO4普通红LED作指示。Motion Raw表示处理后的运动、Indicator Command表示软件命令、Phase解释阶段;命令不是实物光反馈,更不控制市电灯。
- 做到这里,你应该看到
- 能解释为什么静坐时灯灭,并为运动和静坐分别设计观察。
参考:[1] Adafruit PIR PID189:5–12V输入/3.3V数字OUT[2] PIR两片热释电区域为何检测变化[3] PIR稳定时间、H/L、TIME与Tx/Ti
模块吃5V,信号仍只允许3.3V
PID189官方输入5–12V、OUT为3.3V高/低。本例以板5V/J1-21给模块供电,OUT到GPIO5/J1-5、地到J1-22;GPIO5加100kΩ到地作弱下拉。按本块板+、OUT、-丝印断电追线,不把接插件朝向或另一PIR的针序套过来,也不改板上稳压器去用3.3V。
GPIO4/J1-4经330Ω接WP7113ID阳极,阴极共地。只用一条桥USB供电,5V电源线不能误接GPIO。外部下拉使信号拔掉像LOW;本篇没有线路监督,不能将无运动当自检通过。
| 端点 | 连接 |
|---|---|
| 5V / J1-21 | PID189电源+ |
| GND / J1-22 | PIR-、下拉、LED阴极 |
| GPIO5 / J1-5 | PIR OUT;100kΩ到GND |
| GPIO4 / J1-4 | 330Ω→WP7113ID阳极 |
- 做到这里,你应该看到
- 先核5V电源与3.3V OUT两条不同线,再上电。
参考:[1] Adafruit PIR PID189:5–12V输入/3.3V数字OUT[4] ESPHome2026.9.1 GPIO binary_sensor实现[8] 指定DevKitC-1 v1.1排针、USB及存储范围[9] WP7113ID普通红LED器件手册
先固定H模式,再分清三个时间
断电把jumper置H可重触发,TIME轻旋至逆时针最小,记录SENS初始位置,不用力越过止点。厂商稳定期30–60秒会有脉冲,所以代码启动60秒Ready关闭/灯关;这只是屏蔽策略,结束时仍须确认模块稳定。厂家最小Tx约2.5秒是计算示例,不是本站测得的这块板时间。
输入先50ms双向滤波,再每100ms处理;HIGH让灯亮,最后一次被采到的HIGH后保持20秒,新HIGH重新延长。模块硬件Tx、软件20秒与人在视野中的停留不是同一个计时起点;真实熄灯还受滤波与调度影响,重启不恢复上一轮保持。
- 做到这里,你应该看到
- 不把“离开后20秒”说成精确保证,能定位保持在哪一层。
参考:[1] Adafruit PIR PID189:5–12V输入/3.3V数字OUT[3] PIR稳定时间、H/L、TIME与Tx/Ti[4] ESPHome2026.9.1 GPIO binary_sensor实现[5] ESPHome2026.9.1双向延时滤波实现
完整YAML:本地行为先独立于HA
Python3.12.13、ESPHome2026.9.1/IDF5.5.5固定,包中有完整requirements与本机完整依赖记录。先复制secrets.example.yaml为私有secrets.yaml,填Wi-Fi和自己随机生成的32字节base64 key;同key用于API和OTA加密,不发布私有文件。先config/compile,再用H01的桥USB首次写入。
api/wifi reboot_timeout均0s,网络或HA缺失不因此周期复位,本地灯由同一个状态模型处理。YAML引用同目录motion_hold.h,完整源包不可只复制片段。没有后台HA运行记录,DEBUG/配置输出也不等于PIR触发过。
esphome:
name: hixinwu-s06
friendly_name: Hixinwu S06
min_version: 2026.9.1
includes:
- motion_hold.h
esp32:
board: esp32-s3-devkitc-1
variant: ESP32S3
flash_size: 8MB
flash_mode: qio
flash_frequency: 80MHz
toolchain: esp-idf
framework:
type: esp-idf
version: 5.5.5
psram:
mode: octal
speed: 80MHz
logger:
baud_rate: 115200
hardware_uart: UART0
level: DEBUG
api:
encryption:
key: !secret api_key
reboot_timeout: 0s
ota:
- platform: esphome
encryption:
key: !secret api_key
wifi:
ssid: !secret wifi_ssid
password: !secret wifi_password
reboot_timeout: 0s
ap:
ssid: "hixinwu-s06 Recovery"
password: !secret fallback_password
ap_timeout: 90s
captive_portal:
switch:
- platform: gpio
id: indicator
pin: GPIO4
internal: true
restore_mode: ALWAYS_OFF
binary_sensor:
- platform: gpio
id: pir_raw
pin:
number: GPIO5
mode: INPUT
internal: true
filters:
- delayed_on_off: 50ms
- platform: template
id: input_ready
name: "Input Ready"
entity_category: diagnostic
- platform: template
id: motion_report
name: "Motion Raw"
device_class: motion
- platform: template
id: indicator_report
name: "Indicator Command"
text_sensor:
- platform: template
id: motion_phase
name: "Phase"
interval:
- interval: 100ms
then:
- lambda: |-
auto &c=s06::controller();
c.step(s06::now_ms(),id(pir_raw).has_state(),id(pir_raw).state);
if(c.light)id(indicator).turn_on();else id(indicator).turn_off();
id(input_ready).publish_state(c.ready);
id(motion_report).publish_state(c.motion);
id(indicator_report).publish_state(c.light);
id(motion_phase).publish_state(c.label());
参考:[4] ESPHome2026.9.1 GPIO binary_sensor实现[5] ESPHome2026.9.1双向延时滤波实现[8] 指定DevKitC-1 v1.1排针、USB及存储范围
同一头文件在设备与主机上处理时间输入
下方状态模型在ESPHome事件循环中使用,输入来自滤波后的PIR,输出motion/light/ready/phase;没有另开线程、离线运动队列或恢复上次保持。YAML实际调用s06::now_ms(),取ESP-IDF5.5.5完整64位启动微秒再换成uint64毫秒。跨过2³²毫秒(约49.7天)后,已经结束的暖机不会重开、过期HIGH不会再激活HOLD;只有新的HIGH才能重新点亮。设备重启从新的启动时间重新暖机。
同源头文件检查60秒启动、持续HIGH、20秒截止、无输入与完整32位周期后的状态;production_call.py还逐字提取本页YAML lambda,配合同一头文件和注入IDF时钟编译运行,检查完整时刻流到实际灯命令分支。它们不运行ESPHome调度、PIR光学、实体GPIO或HA,也不是49天实板运行。
// SPDX-License-Identifier: MIT
#pragma once
#include <stdint.h>
#ifdef ESP_PLATFORM
#include "esp_timer.h"
#endif
namespace s06 {
constexpr uint32_t WARMUP_MS=60000,HOLD_MS=20000;
#ifdef ESP_PLATFORM
// Keep the full monotonic IDF boot-time value, not millis() widened afterwards.
inline uint64_t now_ms(){return static_cast<uint64_t>(esp_timer_get_time())/1000ULL;}
#endif
struct Controller{
uint64_t boot=0,last_high=0;bool ready=false,motion=false,light=false,seen=false;
explicit Controller(uint64_t start=0):boot(start){}
void step(uint64_t now,bool has_input,bool raw){
ready=has_input&&now>=boot&&now-boot>=WARMUP_MS;
motion=ready&&raw;
if(!ready){light=false;return;}
if(raw){seen=true;last_high=now;}
light=seen&&(raw||(now>=last_high&&now-last_high<HOLD_MS));
}
const char* label()const{return !ready?"WARMUP_OR_NO_INPUT":motion?"MOTION":light?"HOLD":"IDLE";}
};
inline Controller& controller(){static Controller value;return value;}
}
- 做到这里,你应该看到
- 能从HIGH序列算出灯命令,同时把光学范围留给实板。
参考:[3] PIR稳定时间、H/L、TIME与Tx/Ti[4] ESPHome2026.9.1 GPIO binary_sensor实现[5] ESPHome2026.9.1双向延时滤波实现[10] ESP-IDF5.5.5:64位启动微秒时钟与接口[11] ESP-IDF5.5.5:Obtaining Current Time与深睡重启边界
HA先显示不可用,再接收有效运动状态
在HA设置→设备与服务添加ESPHome,填节点真实IP与私有API key。核对Input Ready、Motion Raw、Indicator Command、Phase的实际entity_id;包中ha-package.yaml给包装Motion实体,只有Ready=on才可用。启动和节点离线会unavailable,不把它们显示成“没有运动”。
把完整package放config/packages,合并已有homeassistant/packages入口而非重复顶层键,先按实际ID改模板,再运行HA自己的配置检查和重载/重启。本文只做YAML语法检查,没有运行HA。状态路线不需要把用户的真实照明自动化改成一套未经测量的市电控制。
# Check actual source entity IDs in your HA before enabling this package.
template:
- binary_sensor:
- name: "Hixinwu S06 Motion"
unique_id: hixinwu_s06_motion_checked
device_class: motion
availability: "{{ is_state('binary_sensor.hixinwu_s06_input_ready', 'on') }}"
state: "{{ is_state('binary_sensor.hixinwu_s06_motion_raw', 'on') }}"
- 做到这里,你应该看到
- 启动Ready关闭时包装不可用,Ready后运动与保持命令分别观察。
参考:[6] HA Core2026.10.2模板binary_sensor状态与availability[7] HA Core2026.10.2 availability计算与实体可用性
走动、静坐、离开,同位置分别记录
等模块稳定且Ready后,同一视野走动30秒、静坐2分钟、离开2分钟,保持位置、人数、jumper和旋钮不变;记录原始电平、Phase、命令、实体灯与HA包装状态。再在保持期间重新走动,看最后HIGH是否延长;按EN确认重启先走60秒启动期。
关闭HA或断Wi-Fi时本地仍按策略,恢复只传当前状态,不承诺补录之前每次运动。PIR/HA/显示软件的某一项通过不能替其他项填表;本站没有这些物理/HA结果,CSV为空。
- 做到这里,你应该看到
- 静坐结果如实记录,不能只挑走动成功片段。
参考:[1] Adafruit PIR PID189:5–12V输入/3.3V数字OUT[2] PIR两片热释电区域为何检测变化[3] PIR稳定时间、H/L、TIME与Tx/Ti[4] ESPHome2026.9.1 GPIO binary_sensor实现
误触发和不亮各有检查顺序
误触发先看朝向、热源、冷热气流、阳光、供电,再看旋钮;一直亮先查OUT是否持续HIGH以及H模式Tx,不直接认定检测到了静态人。一直不亮先看Ready、模块5V、OUT/普通LED极性;不把5V试接GPIO。先恢复H+TIME最小和原代码,再逐项调参数。
HA找不到先看真实IP/key/entity_id,旧监视器占用串口先关闭;凭据错等90秒恢复热点,连接私有密码并打开192.168.4.1修网络,OTA失败回桥USB重写。完整步骤在README。实际主机检查命令如下;实板、覆盖、延时与HA运行仍pending。
clang++ -std=c++17 -Wall -Wextra -Werror host_check.cpp -o /tmp/s06-host
/tmp/s06-host
python3 tests/production_call.py参考:[1] Adafruit PIR PID189:5–12V输入/3.3V数字OUT[3] PIR稳定时间、H/L、TIME与Tx/Ti[4] ESPHome2026.9.1 GPIO binary_sensor实现[5] ESPHome2026.9.1双向延时滤波实现[8] 指定DevKitC-1 v1.1排针、USB及存储范围
资料来源与版本说明
实际读取固定版本源码/器件资料,构建与主机逻辑分别留证。本站未完成烧录、GPIO/ADC/光学/传感器或HA运行;电路名义值与软件命令不冒充实测。资料核对日期:。资料核对、程序构建与实板测试分别记录,不互相替代。
- Adafruit PIR PID189:5–12V输入/3.3V数字OUT
- PIR两片热释电区域为何检测变化
- PIR稳定时间、H/L、TIME与Tx/Ti
- ESPHome2026.9.1 GPIO binary_sensor实现
- ESPHome2026.9.1双向延时滤波实现
- HA Core2026.10.2模板binary_sensor状态与availability
- HA Core2026.10.2 availability计算与实体可用性
- 指定DevKitC-1 v1.1排针、USB及存储范围
- WP7113ID普通红LED器件手册
- ESP-IDF5.5.5:64位启动微秒时钟与接口
- ESP-IDF5.5.5:Obtaining Current Time与深睡重启边界