工位旁边有一盏台灯是那种要摸一下开关的,人抱着笔记本坐下来手是满的,摸开关这事儿就特别反人类。这周给家里玄关搞了个小改造:HC-SR501 人体红外感应模块加一颗 LED,人一走近灯就亮,走开过一会儿自己灭。整套东西十几块钱,接线四根,程序三十行,属于周末一个下午能收工的项目。这篇把这颗传感器的原理、调参、接线和代码触发逻辑一次说透,你照着做就能点亮。

PIR 是怎么"看见"人的
HC-SR501 属于被动红外(PIR)传感器,它自己不发射任何东西,只接收。自然界里凡是高于绝对零度的物体都在往外辐射红外线,人体体温 37 度左右,辐射出来的红外波段正好落在它的探测范围里。
核心是一颗热电传感器,上面开着两个探测窗口,输出的极性一个正一个负。人不动的时候,两个窗口接收到的红外能量一样,信号相互抵消,输出为零;人一移动,热源先进了一个窗口再进另一个,两路信号出现先后差,差分信号就出来了。所以这颗传感器对"移动的热源"敏感,对站着不动的你完全没反应——不是坏了,是原理如此。

模块前面那颗白色半球罩是菲涅尔透镜,表面一圈一圈的同心纹路把视野切成多个交叠的探测区,红外聚焦到那颗小小的感应元件上。有了它,探测距离和视角才拉得开:官方标称探测距离 3 到 7 米、视角约 120 度。芯片用的是 BISS0001,把微弱的差分信号处理成干净的高低电平输出,抗噪做得不错。
模块引脚、旋钮和跳线帽

HC-SR501 一共三个引脚:VCC 接电源正、OUT 输出信号、GND 接地。引脚丝印有的版本藏在透镜底下,掀开罩子才看得到,接线前先确认清楚。供电范围 4.5V 到 20V,典型用 5V,模块内部自带 3.3V 稳压,整颗静态电流不到 2mA,用电池也能挂很久。
板子上两个橙色旋钮最容易让人懵。一个管灵敏度,实际就是调探测距离:顺时针转到头大约 7 米,逆时针减小到 3 米左右。另一个管延时,控制输出保持高电平多久:顺时针最长约 3 分钟,逆时针最短约 1 秒。建议先把延时旋到最小再上手调,不然每次触发都挂着等它慢慢灭。
跳线帽两个挡位是触发方式的选择。拨到 L 是单次触发,输出高电平期间再来人也不刷新计时,时间到了才归零;拨到 H 是可重复触发,延时期间只要再有动作,计时就重新开始,人一直在灯就一直亮。做自动灯这种场景直接用 H,体验顺滑得多。另外板子上还留了两个焊盘:RT 是给热敏电阻的,用来在极端温度下修正精度;RL 是给光敏电阻的,加上以后天亮就不触发,做楼道夜灯正好。
接线:Arduino 与 ESP32 通用

接线只有三根,按下面的表来。这里注意一个容易踩的点:HC-SR501 的 OUT 输出是 3.3V 电平,接 Arduino 完全没问题;接 ESP32 时这个电平也正好在 GPIO 的安全范围内,不用电平转换,反而比很多 5V 输出的传感器更省事。VCC 那一路接 5V(ESP32 上接 VIN 或 5V 引脚),别接 3V3,有用户反馈供电不足时会出现乱触发。
| HC-SR501 | Arduino / ESP32 |
|---|---|
| VCC | 5V(ESP32 接 VIN) |
| OUT | GPIO 8(ESP32 可换 GPIO 4) |
| GND | GND |
LED 直接用板上 13 号引脚那颗自带灯也行,外接的话串一个 220 欧限流电阻从 GPIO 拉出来,负极回 GND。想再加点动静,并一颗无源蜂鸣器上去也行,但记得声学报警在出租屋深夜并不礼貌,量力而行。
代码与触发逻辑
程序逻辑很简单:循环读 OUT 引脚,读到高电平就点亮 LED,同时用状态变量保证串口只在电平变化那一刻打印一次,而不是刷屏。下面这段直接可烧:
int ledPin = 13; // choose the pin for the LED
int inputPin = 8; // choose the input pin (for PIR sensor)
int pirState = LOW; // we start, assuming no motion detected
int val = 0; // variable for reading the pin status
void setup() {
pinMode(ledPin, OUTPUT); // declare LED as output
pinMode(inputPin, INPUT); // declare sensor as input
Serial.begin(9600);
}
void loop(){
val = digitalRead(inputPin); // read input value
if (val == HIGH) // check if the input is HIGH
{
digitalWrite(ledPin, HIGH); // turn LED ON
if (pirState == LOW)
{
Serial.println("Motion detected!"); // print on output change
pirState = HIGH;
}
}
else
{
digitalWrite(ledPin, LOW); // turn LED OFF
if (pirState == HIGH)
{
Serial.println("Motion ended!"); // print on output change
pirState = LOW;
}
}
}烧完打开串口监视器,波特率 9600。你起身在传感器前面走两步,会看到 "Motion detected!",静止几秒、等延时耗尽后打印 "Motion ended!"。如果想改判断逻辑,比如在检测到人的瞬间做别的事,挂在 pirState 从 LOW 变 HIGH 的那个 if 里就行,电平持续期间它只执行一次。
两个值得知道的细节。一是封锁期:输出归低之后,BISS0001 内部大约有 2 秒的封锁时间,这期间所有动作都被忽略,所以别指望它毫秒级连发。二是重触发:跳线在 H 挡时,延时窗口内的每个新动作都会把定时器拉满,这就是"人一直在灯不灭"的实现方式;L 挡则完全不刷新,做走廊灯建议 H,做"每次触发只跑一段固定动作"的场景才用 L。
上电预热与几个踩坑提示
这颗模块上电后需要 30 到 60 秒的稳定期,期间输出会乱跳、LED 可能无故闪,属于正常现象。稳定期内别挪动它也别在它面前晃,等它安静下来再开始调参,否则你会把正常的预热当成故障排查半天。
其他几个高频坑:探测面对着空调口、暖气片或阳光直晒的窗户,热气流和红外背景变化会频繁误触发,装的时候避开这些方向;透镜朝向决定了探测区形状,正前方最灵,侧面衰减明显,安装角度比调灵敏度旋钮更值得花时间;延时旋钮顺时针是加长不是减短,拧之前先想清楚要哪个方向;最后,模块供电电压不足或用 USB 口带多颗外设时,乱触发率会明显上升,玄关灯这种场景给单独一路 5V 最省心。
整套做完,成本不到二十块,得到的却是一个"人来灯亮、人走灯灭"的完整闭环。后面想进阶,可以把 OUT 接到 ESP32 再顺手发条消息到手机,或者给灯加个光敏电阻,让白天自动不触发——不过那就是另一篇的事了。











ESP32不用担心电平这个点受用,省了电平转换的钱。
上周刚好也在折腾这颗,玄关灯的需求一模一样。补充一个我自己观察到的点:透镜朝向基本决定了探测区形状,正前方最灵,侧面衰减很明显,我一开始挂在门框侧面怎么调都漏检,转个角度立刻正常。安装角度确实比灵敏度旋钮更值得花时间,文章这句说到点子上了。
跳线帽那个H挡的解释很清楚,之前一直没搞明白单次触发和重复触发差在哪。
上电预热那段太真实了,第一次玩的时候以为买到了坏货,差点退了。