
自动门为什么人还没碰到就先开了?楼道的灯为什么半夜有人走过自己就亮?这背后多半是同一类器件:PIR被动红外传感器。而玩家圈里最经典的型号,就是这颗白色小圆窗、几块钱一片的HC-SR501。它工作电流不到2mA,标称探测距离最远7米,三根线就能给任何项目加上"有没有人在动"这层感知。
这篇把HC-SR501一次讲透:工作原理、模块背面两个电位器加一个跳线的调校方法、接Arduino的完整接线与示例代码,外加两个最容易让人迷惑的延迟特性。内容以Last Minute Engineers的HC-SR501教程为骨架,关键参数都对照了原文写法,步骤按国内玩家的上手顺序重新捋了一遍。
先懂原理:双元热释电加菲涅尔透镜
一切温度高于绝对零度(零下273.15℃)的物体都会向外辐射红外线,物体越热辐射越强,人体自然也不例外。PIR名字里那个"被动",意思就是它不主动发射任何东西,只安安静静接收环境里的红外。
但只测"有没有红外"没什么用,真正要测的是"红外变了没有"。HC-SR501的核心是一颗热释电传感器:窗口上开着两条矩形槽,槽后藏着两个探测电极,一个输出正信号、一个输出负信号。环境静止时,两边收到的红外量相同,信号相互抵消,输出为零;一旦有人从探测区走过,两个电极先后感受到变化,信号出现差值,模块由此判定——有东西在动。

热释电元件本身只有指甲盖大,能罩住大半个房间,靠的是前面那颗白色半球罩——菲涅尔透镜。它由一圈圈同心刻槽构成,每个小格都是一片独立的小透镜,把对应方向的红外聚焦到感光元上;整个探测面于是被切成许多互相重叠的小区,人从小区之间跨过去,就制造出一次红外突变。没有这层透镜,探测距离和视角都会大幅缩水。

模块本体:BISS0001、两个旋钮一个跳线
模块开箱即用:接上电源和地,检测到移动时输出脚拉高,平时保持低电平。供电范围很宽,板载3.3V精密稳压器,直流4.5V到12V都能直接喂,绝大多数人直接取Arduino的5V;电源输入端还串了一颗保护二极管,电源接反也不会立刻烧板,对新手相当友好。
板上的主控是BISS0001这颗专用芯片,负责把热释电输出的微弱信号放大、整形、延时,最后变成干净的数字输出,抗噪性能在同类方案里口碑不错,想深挖可以翻它的数据手册。
真正需要动手调的是背面三个东西。第一个是灵敏度电位器:顺时针拧,探测距离变远,最远约7米;逆时针拧,距离收缩到3米左右。做小走廊感应灯这种场景,故意调低一点,反而免得隔壁屋走动也把灯点亮。
第二个是延时电位器:控制检测到人之后输出保持高电平多久,可调范围约1秒到3分钟,同样是顺时针加长、逆时针缩短。第三个是触发跳线,分两挡:L挡单次触发,延时期间来多少动作都忽略,延时结束、输出回低之后才开始下一轮检测;H挡重复触发,延时期间再有动作就重新计时,只要人一直在动,输出就一直保持高。做"人来灯亮、人走灯灭"的灯控项目,H挡明显更顺手。

板上还留了两个焊盘:RT和RL。RT焊热敏电阻,用来改善极端温度下的检测精度;RL焊光敏电阻,能让模块只在环境变暗之后才工作,做感应夜灯正好用得上。有些板子这两个丝印藏在透镜底下,找不到就把半球罩抠开看背面。
几个关键规格列成表,选型时心里有个数:
| 项目 | 参数 |
|---|---|
| 工作电压 | 4.5V至20V(常见取5V) |
| 工作电流 | 小于2mA |
| 输出保持延时 | 约1秒至3分钟 |
| 探测距离 | 3至7米 |
| 探测角度 | 约120度 |
接Arduino:三根线加一段代码
最省事的玩法是让HC-SR501单干:电池接VCC和GND,输出脚串一颗220Ω限流电阻接LED,有人经过LED就亮;想控制台灯这类大件,把输出接到继电器模块就行,全程不需要单片机。不过要记录事件、做联动逻辑,还是接Arduino更灵活。
接线只有三根:VCC接Arduino的5V,GND接GND,输出脚OUT接数字8脚。OUT是3.3V TTL电平输出,Arduino按普通数字输入读高电平没有任何问题。
| HC-SR501 | Arduino |
|---|---|
| VCC | 5V |
| GND | GND |
| OUT | 数字8脚 |
上电之前建议先做三件事:跳线拨到H挡;延时电位器逆时针拧到底,让延时至少有3秒;灵敏度电位器拿不准就先放中间。接好线就是下面这个样子:

代码很简单,就是盯着8号脚的状态变化:变高就点亮板载LED并打印Motion detected,变低就熄灭并打印Motion ended。下面这段示例代码逐字符照搬自原文,可直接粘进IDE:
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!交替刷出来:

两个容易踩坑的延迟
第一个是锁死时间(Lockout Time)。输出从高变低之后,模块会闭关约2秒,这段时间里任何新动作都直接忽略。举例:跳线在L挡、延时设3秒,挥手后输出高3秒再回低,接着还要等2秒锁死时间过去,传感器才会重新响应;中间再怎么挥手它都装看不见。做多区域覆盖或者频繁触发的项目,这2秒一定要算进节奏里。
第二个是上电热身(Power On Delay)。刚通电的30到60秒里,模块在学习房间环境红外的基线,期间可能误触发几次,LED闪几下属于正常现象。这段时间的信号先忽略,也别在它跟前大幅晃动,否则基线学歪了,后面的检测会一直不准。
写在最后
HC-SR501便宜、省电、接线简单,缺点也明摆着:只能探移动、上电要热身、人体静止就无能为力,高温环境下灵敏度还会往下掉。给机器人做避人感知、给灯控做触发,它依然是成本最低的那一颗;需要感知静止目标的场景,就得换毫米波雷达或者热释电阵列了。
把灵敏度、延时、触发方式这三样调明白,这颗模块基本不会再给你惊喜式的翻车。手边有Arduino的话,按上面的接线和代码,十分钟就能跑通。











这模块之前买过三颗,一直没搞明白背面两个旋钮谁管距离谁管时间,看了这篇才对上号:靠OUT那边的是灵敏度,另一个管延时。之前做楼道灯用的L挡,人站住不动灯就灭,换成H挡重复触发果然稳多了。锁死那2秒以前真不知道,难怪有时候挥手没反应,原来不是模块坏了,是它在闭关。
锁死时间和上电热身这两点太关键了,当年调感应灯被坑了好几天才反应过来。
接线十分钟跑通,串口果然交替刷Motion detected,满意。
几块钱的器件讲得比数据手册还明白,收藏了。