|
毫米波雷达传感器 RCWL-0516:人体存在检测实战

毫米波雷达传感器 RCWL-0516:人体存在检测实战

你有没有遇到过这种场景:人坐在书桌前一动不动,传感器就判定”没人”,把灯给关了?

这就是传统 PIR(红外人体热释电)传感器的老毛病——它检测的是人体热量变化,你不动,它就”瞎”。

今天要聊的 RCWL-0516 毫米波雷达传感器,正好解决了这个痛点。它用的是多普勒雷达原理,只要你在,哪怕你只是在打瞌睡、微微呼吸,它都能感知到。

这篇文章,咱们从原理讲到实战,用 Arduino 和 ESP32 搭建一套完整的人体存在检测系统。

RCWL-0516 是什么?

RCWL-0516 是一块基于 3.15 GHz 微波多普勒雷达 的运动检测模块。它通过发射微波信号并接收反射信号,比较两者的频率差(多普勒频移)来判断是否有物体在移动。

跟 PIR 红外传感器相比,毫米波雷达有几个明显优势:

特性RCWL-0516 雷达PIR 红外
检测原理多普勒微波红外热辐射变化
穿透能力可穿透塑料、木板、薄墙无法穿透,需直视线
静态检测能检测呼吸等微动静止后很快判定无人
检测距离5-7 米可调通常 3-5 米
温度影响不受环境温度影响高温环境灵敏度下降
隐蔽安装可以藏在天花板/墙内需要露在外面

硬件清单

器件数量说明
RCWL-0516 传感器模块1核心检测模块
ESP32 开发板1主控(也可用 Arduino Uno)
面包板 + 杜邦线若干接线用
LED 模块1状态指示(或直接用板载 LED)
100kΩ 电阻1可选,用于调整检测距离
USB 数据线1供电和烧录程序

RCWL-0516 模块上有 5 个引脚:

+---+
|   |
| 3V3  ← 3.3V 输出(可给外部供电)
| VIN  ← 4-28V 电源输入
| GND  ← 地线
| OUT  ← 数字输出:检测到目标 = HIGH(3.3V),无目标 = LOW(0V)
| CDS  ← 光敏电阻输入:加电阻或光敏元件可白天禁用
+---+

原理解析:多普勒效应怎么工作?

RCWL-0516 的核心原理其实不复杂,一句话概括就是:发射 → 反射 → 频率偏移检测

  1. 模块内部的微波振荡器产生 3.15 GHz 的连续波
  2. 电磁波通过 PCB 天线向外辐射
  3. 遇到移动物体后,反射波频率发生变化(多普勒频移)
  4. 内部电路比较发射波和反射波的频率差
  5. 如果频率差超过阈值,判定为”有运动”,OUT 引脚输出 HIGH

多普勒频移公式:

Δf = 2 × v × f₀ / c

其中 v 是目标速度,f₀ 是发射频率,c 是光速。哪怕人体呼吸时胸口起伏只有几毫米,这个微小的速度变化也会被 3.15 GHz 的电磁波放大,产生可检测的频率差。

这就是为什么 RCWL-0516 能检测到”几乎不动”的人。

接线:RCWL-0516 + ESP32

接线非常简单,就三根线:

RCWL-0516          ESP32
  VIN      ────▶   3.3V (或 5V)
  GND      ────▶   GND
  OUT      ────▶   GPIO4 (任意数字引脚)
  CDS      ────▶   悬空 或 接光敏电阻

注意:RCWL-0516 的 VIN 支持 4-28V 宽电压输入,但用 ESP32 时直接接 3.3V 也能工作(模块内部有稳压电路)。如果接 5V,检测灵敏度会稍微高一些。

实战一:基础检测(Arduino)

最基础的用法:检测到人 → 串口打印信息 + 点亮 LED。

// RCWL-0516 基础人体存在检测
// 硬件:RCWL-0516 + Arduino Uno
const int SENSOR_PIN = 2;  // RCWL-0516 OUT 接 Arduino D2
const int LED_PIN = 13;    // 板载 LED

void setup() {
  Serial.begin(115200);
  pinMode(SENSOR_PIN, INPUT);
  pinMode(LED_PIN, OUTPUT);
  
  Serial.println("RCWL-0516 人体存在检测启动...");
  Serial.println("等待传感器初始化...");
  delay(3000);  // 给传感器 3 秒初始化时间
}

void loop() {
  int sensorValue = digitalRead(SENSOR_PIN);
  
  if (sensorValue == HIGH) {
    digitalWrite(LED_PIN, HIGH);
    Serial.println("[存在] 检测到人体活动!");
  } else {
    digitalWrite(LED_PIN, LOW);
    Serial.println("[离开] 无人检测");
  }
  
  delay(500);  // 500ms 采样间隔
}

这段代码跑起来后,你在传感器前面挥手、走动、甚至只是坐着动一下手指,串口就会打印 [存在]

实战二:ESP32 + 防误触滤波

RCWL-0516 有一个常见问题:输出信号有时会抖动,短时间内反复 HIGH-LOW 切换。我们通过简单的时间窗口滤波来解决。

// RCWL-0516 ESP32 版:带防误触滤波
const int SENSOR_PIN = 4;     // OUT 接 GPIO4
const int LED_PIN = 2;        // 板载 LED
const int LED_BUILTIN = 13;

// 滤波参数
const unsigned long PRESENCE_CONFIRM_MS = 2000;   // 确认"有人"需持续 2 秒
const unsigned long ABSENCE_CONFIRM_MS = 10000;   // 确认"无人"需持续 10 秒

bool currentState = false;        // 当前判定的存在状态
unsigned long lastChangeTime = 0; // 上次状态变化时间

void setup() {
  Serial.begin(115200);
  pinMode(SENSOR_PIN, INPUT);
  pinMode(LED_PIN, OUTPUT);
  pinMode(LED_BUILTIN, OUTPUT);
  
  Serial.println("=== RCWL-0516 ESP32 人体存在检测 ===");
  Serial.println("防误触滤波已启用");
  delay(3000);
}

void loop() {
  bool rawSignal = (digitalRead(SENSOR_PIN) == HIGH);
  unsigned long now = millis();
  
  if (rawSignal && !currentState) {
    // 从"无人"检测到"有人"信号
    if (now - lastChangeTime >= PRESENCE_CONFIRM_MS) {
      currentState = true;
      Serial.println("[✅ 确认] 检测到人体存在!");
      digitalWrite(LED_PIN, HIGH);
      digitalWrite(LED_BUILTIN, HIGH);
      lastChangeTime = now;
    }
  }
  else if (!rawSignal && currentState) {
    // 从"有人"检测到"无人"信号
    if (now - lastChangeTime >= ABSENCE_CONFIRM_MS) {
      currentState = false;
      Serial.println("[❌ 确认] 人体已离开");
      digitalWrite(LED_PIN, LOW);
      digitalWrite(LED_BUILTIN, LOW);
      lastChangeTime = now;
    }
  }
  
  // 状态持续时重置计时器
  if (rawSignal == currentState) {
    lastChangeTime = now;
  }
  
  delay(100);
}

这段代码的逻辑:

  • 必须连续 2 秒检测到 HIGH,才判定”有人”(防止误触发)
  • 必须连续 10 秒检测到 LOW,才判定”无人离开”(防止呼吸间隙误判离开)
  • 每次信号与当前状态一致时,重置计时器

你可以根据实际环境调整这两个时间阈值。

实战三:ESP32 + MQTT 上报(智能家居集成)

这才是真正有用的——把检测结果发到 MQTT Broker,让 Home Assistant 或其他智能家居平台来处理。

// RCWL-0516 + ESP32 + MQTT → 智能家居人体存在传感器
#include <WiFi.h>
#include <PubSubClient.h>

// WiFi 配置
const char* ssid = "YOUR_WIFI_SSID";
const char* password = "YOUR_WIFI_PASSWORD";

// MQTT 配置
const char* mqtt_server = "192.168.1.100";  // 你的 MQTT Broker 地址
const int mqtt_port = 1883;
const char* mqtt_user = "mqtt_user";
const char* mqtt_password = "mqtt_password";

const int SENSOR_PIN = 4;
const char* mqtt_topic_presence = "home/sensor/presence/office";

WiFiClient espClient;
PubSubClient mqttClient(espClient);

// 滤波
bool presenceState = false;
unsigned long stateChangeTime = 0;
const unsigned long ON_DELAY = 2000;
const unsigned long OFF_DELAY = 10000;

void setup() {
  Serial.begin(115200);
  pinMode(SENSOR_PIN, INPUT);
  
  // 连接 WiFi
  WiFi.begin(ssid, password);
  Serial.print("连接 WiFi");
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println("\nWiFi 已连接!");
  
  // 配置 MQTT
  mqttClient.setServer(mqtt_server, mqtt_port);
  mqttClient.setKeepAlive(30);
  
  connectMQTT();
  delay(3000);  // 传感器初始化
}

void connectMQTT() {
  while (!mqttClient.connected()) {
    String clientId = "ESP32-Presence-" + String(random(0xffff), HEX);
    if (mqttClient.connect(clientId.c_str(), mqtt_user, mqtt_password)) {
      Serial.println("MQTT 已连接");
      // 发布离线状态
      mqttClient.publish(mqtt_topic_presence, "OFFLINE", true);  // retain
    } else {
      Serial.print("MQTT 连接失败, rc=");
      Serial.println(mqttClient.state());
      delay(3000);
    }
  }
}

void loop() {
  if (!mqttClient.connected()) {
    connectMQTT();
  }
  mqttClient.loop();
  
  bool raw = (digitalRead(SENSOR_PIN) == HIGH);
  unsigned long now = millis();
  
  if (raw && !presenceState) {
    if (now - stateChangeTime >= ON_DELAY) {
      presenceState = true;
      mqttClient.publish(mqtt_topic_presence, "ONLINE", true);
      Serial.println("[MQTT] 发布: ONLINE (有人)");
      stateChangeTime = now;
    }
  }
  else if (!raw && presenceState) {
    if (now - stateChangeTime >= OFF_DELAY) {
      presenceState = false;
      mqttClient.publish(mqtt_topic_presence, "OFFLINE", true);
      Serial.println("[MQTT] 发布: OFFLINE (无人)");
      stateChangeTime = now;
    }
  }
  
  if (raw == presenceState) {
    stateChangeTime = now;
  }
  
  delay(100);
}

在 Home Assistant 中,你可以用 MQTT Discovery 自动发现这个传感器:

# Home Assistant configuration.yaml
binary_sensor:
  - platform: mqtt
    name: "办公室人体存在"
    state_topic: "home/sensor/presence/office"
    payload_on: "ONLINE"
    payload_off: "OFFLINE"
    device_class: occupancy
    qos: 1

搞定之后,你的 Home Assistant 就会多一个”办公室人体存在”传感器,比 PIR 灵敏得多,不会动不动就判定”无人”。

进阶:检测距离调整

RCWL-0516 默认检测距离约 5-7 米。如果你想在更小的空间使用(比如卫生间、衣柜),可以调整检测距离。

方法一:加装屏蔽罩

最简单粗暴——用金属箔(铝箔)做一个罩子盖住传感器天线面,只留一个方向开口。这能显著缩小检测范围。

方法二:修改电容

模块上的 C-TM 电容决定了检测灵敏度。原装通常是 1nF:

  • 减小电容 → 降低灵敏度 → 缩短检测距离
  • 增大电容 → 提高灵敏度 → 增加检测距离

经验值参考:

C-TM 电容大致检测距离
0.5nF~2-3 米
1nF (默认)~5-7 米
2nF~8-10 米

方法三:在 VIN 上加电位器

降低供电电压会降低发射功率,从而缩短检测距离。加一个可调电位器在 VIN 回路中,可以从 4V 调到 9V 来微调。

CDS 引脚:白天自动禁用

RCWL-0516 的 CDS 引脚是用来接光敏电阻的。当环境光足够亮时,传感器自动停止输出 HIGH,避免白天浪费资源。

接法:

CDS 引脚 ──▶ 光敏电阻 ──▶ 5V

              10kΩ 电阻

              GND

光线暗时,光敏电阻阻值变大 → CDS 引脚电压低 → 传感器正常工作 光线亮时,光敏电阻阻值变小 → CDS 引脚电压高 → 传感器被禁用

如果你不需要这个功能,让 CDS 引脚悬空就行(默认正常工作)。

常见问题排查

Q1:传感器一直输出 HIGH,从不变 LOW?

可能原因:

  • 检测范围内有持续运动物体:风扇转动、窗帘飘动、宠物走动都会触发。建议检查周围环境,或缩短检测距离。
  • 传感器故障:用万用表测量 OUT 引脚电压。正常无人时应该接近 0V。
  • 供电不足:VIN 电压低于 4V 可能导致工作异常。确保供电在 4-28V 范围内。

Q2:传感器灵敏度太低,检测不到人?

  • 检查供电:3.3V 时灵敏度较低,换 5V 试试
  • 检查安装方向:雷达波主要从模块正面(元件面)发射,背面灵敏度很低
  • 增大 C-TM 电容(见上文”检测距离调整”部分)

Q3:输出信号抖动频繁,状态来回切换?

这是 RCWL-0516 的已知特性。解决方案就是前文实战二中的时间窗口滤波。根据实际环境调整 ON_DELAY 和 OFF_DELAY 的值。

Q4:能穿透墙壁检测隔壁房间的人吗?

理论上可以,但实际效果取决于:

  • 墙壁材质(石膏板/木板容易穿透,钢筋混凝土几乎不行)
  • 距离(穿透墙壁后有效距离大幅缩短)
  • 干扰(隔壁如果有风扇、空调等也会被检测到)

如果你的场景是”检测隔壁是否有人”,建议改用 WiFi 探针或蓝牙 beacon 方案更可靠。

Q5:RCWL-0516 vs LD2410,选哪个?

如果你在做新项目,强烈建议看看 LD2410(24GHz 毫米波雷达)。对比:

特性RCWL-0516LD2410 (24GHz)
频率3.15 GHz24 GHz
检测精度只能判断有人/无人可区分有人/无人 + 距离信息
微动检测一般优秀(能检测呼吸心跳)
价格~¥5~¥20
接口数字 OUTUART 串口
推荐场景简单存在检测精细人体存在检测

LD2410 是更新一代的方案,适合对精度要求更高的场景。但 RCWL-0516 胜在便宜和简单,入门学习用它足够了。

总结

RCWL-0516 毫米波雷达传感器是入门人体存在检测的最佳选择之一:

  • 优点:便宜、接线简单、可穿透障碍物、不受温度影响、能检测微动
  • 缺点:信号会抖动、不能提供距离信息、无法区分人和宠物

用本文的三个实战项目,你已经能搭建:

  1. 基础人体检测(本地指示)
  2. 带防误触滤波的稳定检测
  3. MQTT 上报的智能家居集成方案

下一步,你可以把多个传感器部署到不同房间,用 Home Assistant 做全屋人体存在监控;或者结合光照传感器实现”有人且天黑才开灯”的智能照明逻辑。

有问题或想分享你的项目,欢迎在评论区交流!