本帖最后由 神一样的老师 于 2026-5-23 09:50 编辑
1. 模块简介
DFRobot C4002 是一款基于 24GHz FMCW 技术的毫米波雷达模块,面向智能家居中的人体存在检测场景。相比传统 PIR 传感器,它不仅能检测运动人体,还能检测静止或微动人体,并支持运动距离、速度、方向、环境光等数据输出。
典型能力如下:
| 项目 | 参数 | | 工作电压 | DC 3.6V ~ 5.5V | | 检测对象 | 运动人体、静止/微动人体 | | 最大检测距离 | 运动约 11m,静止/微动约 10m | | 探测角度 | 120° x 120° | | 通信接口 | UART、OUT 电平输出 | | 工作频率 | 24GHz ~ 24.25GHz | | 光照检测 | 0 ~ 50 lux | | 工作温度 | -20℃ ~ 85℃ |
该模块适合用于:
- 智能灯光人体存在检测
- 房间无人节能控制
- Home Assistant 智能家居接入
- 静态人体存在感知
- 非接触式运动方向/速度检测
2. 引脚说明
C4002 模块提供 5 个主要引脚:
| 引脚 | 功能 | | VIN | 电源输入,DC 3.6V ~ 5.5V | | GND | 电源地 | | RX | 传感器串口接收端 | | TX | 传感器串口发送端 | | OUT | 可配置电平输出 |
UART 接线时要交叉连接:
| C4002 | 主控 | | RX | TX | | TX | RX | | VIN | 5V 或符合范围的电源 | | GND | GND |
官方示例默认串口波特率为 115200。
3. 接口协议整理
C4002 同时支持两类接口:
- OUT 电平接口:用于快速判断是否检测到目标,适合直接驱动 IO 判断。
- UART 串口协议:用于读取完整检测数据,例如目标状态、距离、能量、速度、方向、光照、距离门配置等。
3.1 OUT 输出模式
OUT 引脚的输出逻辑可以通过串口配置,主要有 3 种模式:
| 模式 | 含义 | | eOutpinMode1 | 仅检测到运动目标时输出高电平 | | eOutpinMode2 | 仅检测到存在/静止目标时输出高电平 | | eOutpinMode3 | 检测到运动或存在目标时输出高电平 |
如果只需要“有人/无人”判断,建议使用 eOutpinMode3。
3.2 UART 数据帧格式
从 DFRobot Arduino 库可以看出,C4002 串口帧格式如下:
| 字段 | 长度 | 说明 | | 帧头 | 4 字节 | 固定为 FA F5 AA A5 | | 帧长度 | 2 字节 | 小端格式,表示整帧长度 | | 保留位 | 1 字节 | 固定为 00 | | 帧类型 | 1 字节 | 请求、响应或通知 | | 数据区 | N 字节 | 命令字、状态码、数据长度、数据内容 | | 校验和 | 2 字节 | 小端格式,前面所有字节累加和 |
帧长度计算方式:
- frame_len = data_len + 10
复制代码
其中 data_len 是数据区长度,额外 10 字节包括:
- 4 字节帧头 + 2 字节长度 + 1 字节保留位 + 1 字节帧类型 + 2 字节校验
复制代码
3.3 帧类型
| 帧类型 | 值 | 说明 | | 写请求 | 0x00 | 主控向模块写入配置 | | 读请求 | 0x01 | 主控读取模块配置或数据 | | 写响应 | 0x02 | 模块对写请求的响应 | | 读响应 | 0x03 | 模块对读请求的响应 | | 通知帧 | 0x04 | 模块主动上报检测结果或校准状态 |
3.4 数据区格式
数据区一般由以下字段组成:
| 字段 | 长度 | 说明 | | CMD | 1 字节 | 命令字 | | RESP | 1 字节 | 请求时通常为 0x00,响应时为状态码 | | DATA_LEN | 2 字节 | 数据区内部长度,小端格式 | | DATA | N 字节 | 命令参数或返回数据 |
响应码常见含义如下:
| 响应码 | 含义 | | 0x01 | 成功 | | 0x02 | 命令不存在 | | 0x03 | 校验或认证错误 | | 0x04 | 资源忙 | | 0x05 | 参数错误 | | 0x06 | 数据长度异常 | | 0x07 | 内部错误 |
4. 常用命令字整理
| 命令 | 值 | 功能 | | CMD_CONFIG_OUT_MODE | 0xA0 | 设置 OUT 输出模式 | | CMD_SET_LED_MODE | 0xA1 | 设置运行 LED / 输出 LED | | CMD_ENVIRNMENT_CALIBRATION | 0x60 | 启动环境底噪校准 | | CMD_SET_DETECT_RANGE | 0x86 | 设置检测距离范围 | | CMD_SET_REPORT_PERIOD | 0x83 | 设置上报周期 | | CMD_SET_LIGHT_THRESHOLD | 0x88 | 设置环境光阈值 | | CMD_SET_DISTANCE_DOOR | 0x62 | 配置距离门使能 | | CMD_SET_DISTANCE_DOOR_THRESHOLD | 0x63 | 设置距离门阈值 | | CMD_GET_AND_SET_RESOLUTION_MODE | 0x66 | 获取/设置距离分辨率 | | CMD_SET_BAUDRATE | 0x21 | 设置串口波特率 | | CMD_TARGET_DISAPPEAR_DELAY_TIME | 0x84 | 设置目标消失延时 | | CMD_LOCK_TIME | 0x85 | 设置锁定时间 | | CMD_THRESHOLD_GROUP | 0x87 | 设置灵敏度分组 | | CMD_FACTORY_RESET | 0x80 | 恢复出厂设置 | | CMD_GET_VERSION | 0x82 | 获取版本信息 |
5. Arduino 编程方法
官方提供了 DFRobot_C4002 库,推荐直接使用库进行开发,而不是手写底层 UART 帧。
5.1 安装库
有两种方式:
- 在 Arduino IDE 的库管理器中搜索 DFRobot_C4002 安装;
- 从 GitHub/Gitee 下载库文件,放入 Arduino 的 libraries 目录。
5.2 创建传感器对象
UNO / ESP8266 使用软串口:
- #include "DFRobot_C4002.h"
-
- SoftwareSerial mySerial(4, 5); // RX, TX
- DFRobot_C4002 c4002(&mySerial, 115200);
复制代码
ESP32 使用硬串口:
- #include "DFRobot_C4002.h"
-
- DFRobot_C4002 c4002(&Serial1, 115200, D2, D3);
复制代码
Leonardo、Mega2560 等带 Serial1 的主控:
- #include "DFRobot_C4002.h"
-
- DFRobot_C4002 c4002(&Serial1, 115200);
复制代码
5.3 初始化模块
- void setup() {
- Serial.begin(115200);
-
- while (c4002.begin() != true) {
- Serial.println("C4002 begin failed!");
- delay(1000);
- }
-
- Serial.println("C4002 begin success!");
- }
复制代码
如果初始化失败,优先检查:
- TX/RX 是否接反;
- 模块供电是否正常;
- 波特率是否为 115200;
- 主控串口引脚是否正确。
6. 常用配置方法
6.1 设置 LED 状态
- c4002.setRunLedState(eLedOff);
- c4002.setOutLedState(eLedOff);
复制代码
可选参数:
复制代码
6.2 设置距离分辨率
- c4002.setResolutionMode(eResolution80Cm);
复制代码
支持两种模式:
| 模式 | 距离门分辨率 | 距离门数量 | 最大范围 | | eResolution80Cm | 80cm | 15 个 | 约 11.6m | | eResolution20Cm | 20cm | 25 个 | 约 4.9m |
如果需要较远检测范围,使用 80cm 模式;如果需要更细距离划分,使用 20cm 模式。
6.3 设置检测范围
- uint16_t closest = 0;
- uint16_t farthest = 1100;
-
- c4002.setDetectRange(closest, farthest);
复制代码
单位为 cm,范围为 0 ~ 1100cm。
例如只检测 1m 到 4m:
- c4002.setDetectRange(100, 400);
复制代码
6.4 设置环境光阈值
复制代码
参数范围为 0 ~ 50 lux。
- 设置为 0:不受环境光限制,始终进行目标检测;
- 设置为非 0:只有光照低于阈值时才触发目标检测。
这个功能适合智能灯场景,例如只在光线较暗且有人时开灯。
6.5 设置上报周期
- c4002.setReportPeriod(10);
复制代码
单位为 0.1s。
6.6 设置目标消失延时
- c4002.setTargetDisappearDelay(1);
复制代码
单位为秒,范围为 0 ~ 65535s。
该参数用于避免人体短暂丢失时立即判定无人。智能灯应用中可以设置为 10~60 秒。
6.7 配置距离门
- uint8_t gateState[15] = {
- C4002_ENABLE, C4002_ENABLE, C4002_ENABLE, C4002_ENABLE, C4002_ENABLE,
- C4002_ENABLE, C4002_ENABLE, C4002_ENABLE, C4002_ENABLE, C4002_ENABLE,
- C4002_ENABLE, C4002_ENABLE, C4002_ENABLE, C4002_ENABLE, C4002_ENABLE
- };
-
- c4002.configureGate(eMotionDistGate, gateState);
- c4002.configureGate(ePresenceDistGate, gateState);
复制代码
距离门类型:
| 类型 | 说明 | | eMotionDistGate | 运动目标距离门 | | ePresenceDistGate | 静止/存在目标距离门 |
距离门数组中的值:
- C4002_ENABLE // 使能
- C4002_DISABLE // 禁用
复制代码
7. 读取检测结果
C4002 会通过通知帧上报检测结果。使用库时,只需要调用:
- sRetResult_t retResult = c4002.getNoteInfo();
复制代码
当 noteType == eResult 时,表示收到检测结果。
7.1 读取目标状态
- eTargetState_t targetState = c4002.getTargetState();
-
- if (targetState == eNoTarget) {
- Serial.println("No Target");
- } else if (targetState == ePresence) {
- Serial.println("Static Presence");
- } else if (targetState == eMotion) {
- Serial.println("Motion");
- }
复制代码
目标状态:
| 状态 | 含义 | | eNoTarget | 无目标 | | ePresence | 检测到静止/微动目标 | | eMotion | 检测到运动目标 |
7.2 读取环境光
- float light = c4002.getLightIntensity();
-
- Serial.print("Light: ");
- Serial.print(light);
- Serial.println(" lux");
复制代码
7.3 读取静止/存在目标信息
- sPresenceTarget_t presenceTarget = c4002.getPresenceTargetInfo();
-
- Serial.print("Presence distance: ");
- Serial.print(presenceTarget.distance);
- Serial.println(" m");
-
- Serial.print("Presence energy: ");
- Serial.println(presenceTarget.energy);
复制代码
返回数据:
| 字段 | 含义 | | distance | 目标距离,单位 m | | energy | 目标能量,范围 0~99 |
7.4 读取运动目标信息
- sMotionTarget_t motionTarget = c4002.getMotionTargetInfo();
-
- Serial.print("Motion distance: ");
- Serial.print(motionTarget.distance);
- Serial.println(" m");
-
- Serial.print("Motion speed: ");
- Serial.print(motionTarget.speed);
- Serial.println(" m/s");
-
- Serial.print("Motion energy: ");
- Serial.println(motionTarget.energy);
-
- Serial.print("Motion direction: ");
- if (motionTarget.direction == eAway) {
- Serial.println("Away");
- } else if (motionTarget.direction == eApproaching) {
- Serial.println("Approaching");
- } else {
- Serial.println("No Direction");
- }
复制代码
运动方向:
| 枚举 | 含义 | | eAway | 远离 | | eNoDirection | 无方向 | | eApproaching | 靠近 |
8. 完整示例:读取所有检测结果
- #include "DFRobot_C4002.h"
-
- #if defined(ESP8266) || defined(ARDUINO_AVR_UNO)
- SoftwareSerial mySerial(4, 5);
- DFRobot_C4002 c4002(&mySerial, 115200);
- #elif defined(ESP32)
- DFRobot_C4002 c4002(&Serial1, 115200, D2, D3);
- #else
- DFRobot_C4002 c4002(&Serial1, 115200);
- #endif
-
- void setup() {
- Serial.begin(115200);
-
- while (c4002.begin() != true) {
- Serial.println("C4002 begin failed!");
- delay(1000);
- }
-
- Serial.println("C4002 begin success!");
-
- c4002.setRunLedState(eLedOff);
- c4002.setOutLedState(eLedOff);
-
- c4002.setResolutionMode(eResolution80Cm);
- c4002.setDetectRange(0, 1100);
- c4002.setLightThresh(0);
- c4002.setTargetDisappearDelay(1);
- c4002.setReportPeriod(10);
- }
-
- void loop() {
- sRetResult_t retResult = c4002.getNoteInfo();
-
- if (retResult.noteType == eResult) {
- Serial.println("------- C4002 Result -------");
-
- float light = c4002.getLightIntensity();
- Serial.print("Light: ");
- Serial.print(light);
- Serial.println(" lux");
-
- eTargetState_t state = c4002.getTargetState();
- Serial.print("Target state: ");
- if (state == eNoTarget) {
- Serial.println("No Target");
- } else if (state == ePresence) {
- Serial.println("Static Presence");
- } else if (state == eMotion) {
- Serial.println("Motion");
- }
-
- sPresenceTarget_t presence = c4002.getPresenceTargetInfo();
- Serial.print("Presence distance: ");
- Serial.print(presence.distance);
- Serial.println(" m");
- Serial.print("Presence energy: ");
- Serial.println(presence.energy);
-
- sMotionTarget_t motion = c4002.getMotionTargetInfo();
- Serial.print("Motion distance: ");
- Serial.print(motion.distance);
- Serial.println(" m");
- Serial.print("Motion speed: ");
- Serial.print(motion.speed);
- Serial.println(" m/s");
- Serial.print("Motion energy: ");
- Serial.println(motion.energy);
-
- Serial.print("Motion direction: ");
- if (motion.direction == eAway) {
- Serial.println("Away");
- } else if (motion.direction == eApproaching) {
- Serial.println("Approaching");
- } else {
- Serial.println("No Direction");
- }
-
- Serial.println("----------------------------");
- }
-
- delay(50);
- }
复制代码
9. 环境底噪校准
C4002 支持环境底噪采集,用于过滤窗帘、空调、绿植等环境干扰。
官方示例流程:
- 上传环境校准程序;
- 程序启动后 10 秒内离开检测区域;
- 等待约 30 秒完成底噪采集;
- 通过串口查看运动/存在距离门阈值。
启动校准:
- c4002.startEnvCalibration(10, 30);
复制代码
含义:
| 参数 | 说明 | | 10 | 延迟 10 秒后开始校准 | | 30 | 校准持续 30 秒 |
读取校准状态:
- sRetResult_t retResult = c4002.getNoteInfo();
-
- if (retResult.noteType == eCalibration) {
- Serial.print("Calibration countdown: ");
- Serial.print(retResult.calibCountdown);
- Serial.println(" s");
- }
复制代码
如果环境底噪阈值过高,需要检查附近是否存在持续运动或强干扰源。官方 FAQ 中提到,阈值高于 50 时环境可能存在较大干扰,达到 99 时可能导致传感器异常输出。
10. 开发建议
10.1 智能灯场景
推荐配置:
- c4002.setOutPinMode(eOutpinMode3);
- c4002.setTargetDisappearDelay(30);
- c4002.setLightThresh(20);
复制代码
含义:
- 运动或静止人体都认为“有人”;
- 人离开后延时 30 秒再判定无人;
- 环境光低于 20 lux 时才触发。
10.2 小空间检测
例如卫生间、书房等空间,可以缩小检测距离:
- c4002.setDetectRange(0, 300);
复制代码
这样可以减少墙外、门外人员造成的误触发。
10.3 大空间检测
客厅等空间可以使用最大检测距离:
- c4002.setResolutionMode(eResolution80Cm);
- c4002.setDetectRange(0, 1100);
复制代码
11. 总结
C4002 的使用可以分成两个层次:
- 简单应用:直接使用 OUT 引脚判断有人/无人;
- 完整应用:通过 UART 读取目标状态、距离、速度、方向、能量、光照等数据。
如果使用 Arduino、ESP32 或树莓派,推荐直接使用官方 DFRobot_C4002 库。该库已经封装了底层串口帧、校验和、命令字和数据解析,开发者只需要调用对应 API 即可完成检测范围、距离门、光照阈值、上报周期、环境校准等配置。
参考资料:
|