fuhua817/ed_radar

1.1.0

Latest
uploaded 21 hours ago
Unified UART driver and abstraction layer for ED mmWave radar modules (EDQ152, EDV163, EDV163_ASCII, EDV11P, EDV151)

Readme (en)

# Easydetek Radar 模组通信API 操作指南

[English](README_EN.md) | 简体中文

`ed_radar` 组件提供了一个针对多款易探雷达(如 `EDQ152`、`EDV163`、`EDV11P`、`EDV151` 等)的**面向对象抽象接口层**。通过该层,应用开发者(Apps)无需关注具体型号的数据组包、解包细节及局部结构体差异,可以通过统一的结构完成控制,并且系统提供严格的模型不兼容拦截。

各型号雷达的串口协议说明见 [`docs/`](docs/) 目录。

---

## 0. 作为 ESP Component Registry 组件使用

本组件为标准 ESP-IDF 组件(支持 IDF v5.0+),无任何私有依赖,可直接通过组件管理器引用。

### 0.1 在工程中引用

发布到 registry 后,在工程根目录执行:

```bash
idf.py add-dependency "fuhua817/ed_radar^1.0.0"
```

或者在工程的 `main/idf_component.yml` 中手动添加(支持直接从 Git 拉取):

```yaml
dependencies:
  ed_radar:
    git: https://github.com/fuhua817/ed_radar.git
    version: "*"
```

### 0.2 配置组件

```bash
idf.py menuconfig
# -> Component config -> ED Radar Configuration
```

在此选择雷达型号(EDQ152 / EDV163 / EDV163_ASCII / EDV11P / EDV151)、UART 端口号、TX/RX/EN 引脚、波特率及协议距离单位。选择 EDV163_ASCII 时还会出现存在状态输入引脚 `RADAR_PIN_PRESENCE` 的配置(该型号通过 GPIO 电平获取有人/无人状态,配为 -1 表示不使用)。

### 0.3 上传组件到 ESP Component Registry

1. 在 [components.espressif.com](https://components.espressif.com) 注册账号(命名空间即账号名,本项目为 `fuhua817`);
2. 配置 API Token(token 在网站账号设置中生成,写入本地配置,不会进入仓库):

```bash
compote config set --api-token <你的token> --default-namespace fuhua817
```

3. 在 ESP-IDF 终端中执行:

```bash
compote component upload --namespace fuhua817 --name ed_radar
```

上传前请确认 `idf_component.yml` 中的 `version`、`url` 已填写正确,每次发布新版本需递增 `version`。

---

## 1. 架构与设计思想

组件采用了**多态(Polymorphism)**与**外观模式(Facade)**:
- **`ed_radar_obj_t`(基类句柄)**:暴露给应用层的抽象句柄,对内通过 `void *ctx` 挂载各型号真实的设备上下文。
- **向下强转拦截**:在每个通用接口内,会按创建实例时指定的设备型号(`obj->config.type`)进行 `switch` 分发。如果当前物理型号支持该功能(比如 XYZ 范围配置),则转化为底层结构并下发;如果不兼容该动作(比如让 EDQ152 设置 XYZ 安装高度),则向控制台抛出预警并拦截(返回 `ED_FAIL`),防止内存或逻辑错误。

---

## 2. 基础使用流程

### 2.1 引入头文件
应用层仅需引入顶层头文件,无需直接涉及底层协议头文件(除非需要穿透配置):
```c
#include "ed_radar.h"
```

### 2.2 创建雷达实例
通过 `ed_radar_config_t` 配置结构体创建雷达句柄(可传入 `NULL` 或 `&ED_RADAR_CONFIG_DEFAULT` 使用 Kconfig 默认配置),底层会自动分配所需的内存与解析结构。
```c
// 示例 1:使用 Kconfig 默认配置(型号在 menuconfig 中选择)
ed_radar_obj_t *my_radar = ed_radar_creat(&ED_RADAR_CONFIG_DEFAULT);

// 示例 2:自定义配置,创建一个 EDV11P 实例
ed_radar_config_t cfg = {
    .type        = ED_RADAR_DEVICE_EDV11P,
    .uart_num    = 1,
    .pin_tx      = 5,
    .pin_rx      = 4,
    .pin_en      = 7,
    .baudrate    = 921600,
    .buffer_size = 1024,
};
ed_radar_obj_t *my_radar = ed_radar_creat(&cfg);

if (my_radar == NULL) {
    // 实例化失败处理
}
```

### 2.3 数据泵接管(数据收发任务)
在独立的数据接收 Task 中循环调用解析核心即可。底层驱动内部会自动通过 `ed_radar_receive_data()` 从 UART 取数、组帧并分发给具体型号的解析器,应用层**不要**自己先读串口数据(否则会把数据抢走,导致解析器收不到完整帧):
```c
while (1) {
    // 内部自动取数并分发给具体型号的解析器
    ed_radar_data_handle(my_radar);
    vTaskDelay(pdMS_TO_TICKS(10));
}
```

### 2.4 读取有人/无人结果
数据泵运行后,可在任意时刻查询当前检测结果:
```c
uint8_t has_person = ed_radar_get_presence(my_radar); // 1 = 有人,0 = 无人
```
- EDQ152:任一通道延时存在即判定有人;
- EDV11P:综合存在标志与各感应区目标数判断;
- EDV151:睡眠状态非"离床"(在床/清醒/REM/浅睡/深睡/翻身)即判定有人;
- 其他型号恒返回 0(EDV163 请按第 5 节向下穿透读取通道数据)。

如需调试或旁路抓帧,可注册原始串口接收回调(回调在数据泵任务上下文中执行,请勿阻塞):
```c
ed_radar_register_raw_rx_callback(my_raw_rx_cb, user_ctx);
```

---

## 3. 标准通用 API 概览

所有雷达尽量统一对齐这些方法,传入统一的基于空间(毫米 mm)的物理参数即可。**当前实例不支持的调用会打印 `not supported` 日志并返回 `ED_FAIL`**,各接口的型号支持情况见本节末尾的支持矩阵。

> 大多数 set 接口配有对应的 get 查询接口(如 `ed_radar_get_detect_range`、`ed_radar_get_sensitivity`)。get 系列目前仅 EDV11P 适配,详见支持矩阵。

### 获取设备信息
```c
ed_err_t ed_radar_get_module_info(ed_radar_obj_t *obj);
```
### 检测结果查询
```c
// 读取有人/无人结果:1 = 有人,0 = 无人
// EDQ152 取延时存在状态;EDV11P 综合存在标志与各感应区目标判断;
// EDV151 取体征上报的睡眠状态(非离床即有人);
// EDV163 / EDV163_ASCII 暂未适配,恒返回 0(请通过第 5 节向下穿透获取)
uint8_t ed_radar_get_presence(ed_radar_obj_t *obj);
```
### 系统级控制
```c
ed_err_t ed_radar_factory_reset(ed_radar_obj_t *obj);
ed_err_t ed_radar_set_work_mode(ed_radar_obj_t *obj, uint8_t mode);          // 仅 EDV11P
ed_err_t ed_radar_set_radar_onoff(ed_radar_obj_t *obj, uint8_t onoff);       // EDQ152 / EDV163
ed_err_t ed_radar_set_report_freq(ed_radar_obj_t *obj, uint16_t period_ms);  // 仅 EDV11P
```
### 核心空间与边界控制
这些接口通常服务于 2D/3D 空间雷达(如 EDV163/EDV11P):
```c
// 设置雷达实际安装高度
ed_err_t ed_radar_set_install_height(ed_radar_obj_t *obj, uint16_t mm);

// 触发自动测高,由雷达自行标定安装高度
ed_err_t ed_radar_trigger_auto_measure_height(ed_radar_obj_t *obj);

// 限制雷达检测高度范围
ed_err_t ed_radar_set_detect_height(ed_radar_obj_t *obj, uint16_t min_mm, uint16_t max_mm);

// 设置空间 XYZ 轴探测边界(统一采用 ed_radar_detect_range_t)
ed_err_t ed_radar_set_detect_range(ed_radar_obj_t *obj, ed_radar_detect_range_t *range);

// 设置屏蔽区 / 感应区
ed_err_t ed_radar_set_shield_areas(ed_radar_obj_t *obj, uint8_t count, ed_radar_area_t *areas);
ed_err_t ed_radar_set_induct_areas(ed_radar_obj_t *obj, uint8_t count, ed_radar_area_t *areas);
```
### 延迟与灵敏度
```c
// 设置无人目标丢失的判定延迟时间
ed_err_t ed_radar_set_detect_delay_time(ed_radar_obj_t *obj, uint16_t delay_seconds);

// 设置动作与存在的整体探测灵敏度(内部会自动展开给多通道雷达的全通道)
ed_err_t ed_radar_set_sensitivity(ed_radar_obj_t *obj, uint8_t motion, uint8_t presence);
```
### 射频参数(仅 EDV11P)
```c
// 设置发射功率等级(0-100)
ed_err_t ed_radar_set_tx_power(ed_radar_obj_t *obj, uint8_t level);
```

### 型号支持矩阵

✅ = 已适配;`—` = 调用会被拦截并返回 `ED_FAIL`。

| API | EDQ152 | EDV163 | EDV163_ASCII* | EDV11P | EDV151** |
| --- | :-: | :-: | :-: | :-: | :-: |
| `ed_radar_data_handle`(数据泵) | ✅ | ✅ | — | ✅ | ✅ |
| `ed_radar_get_presence`(有人/无人) | ✅ | — | — | ✅ | ✅ |
| `ed_radar_get_module_info` | ✅ | ✅ | — | ✅ | ✅ |
| `ed_radar_factory_reset` | ✅ | ✅ | — | ✅ | ✅ |
| `ed_radar_set_radar_onoff` | ✅ | ✅ | — | — | ✅ |
| `ed_radar_set_detect_delay_time` | ✅ | ✅ | — | ✅ | — |
| `ed_radar_set_install_height` | — | ✅ | — | ✅ | — |
| `ed_radar_set_detect_height` | — | ✅ | — | ✅ | — |
| `ed_radar_set_detect_range` | — | ✅ | — | ✅ | ✅(一维距离) |
| `ed_radar_set_shield_areas` | — | ✅ | — | ✅ | — |
| `ed_radar_set_sensitivity` | ✅ | — | — | ✅ | — |
| `ed_radar_trigger_auto_measure_height` | — | ✅ | — | ✅ | — |
| `ed_radar_set_trigger_mode` | — | ✅ | — | — | — |
| `ed_radar_set_work_mode` | — | — | — | ✅ | — |
| `ed_radar_set_report_freq` | — | — | — | ✅ | ✅ |
| `ed_radar_set_induct_areas` | — | — | — | ✅ | — |
| `ed_radar_set_tx_power` | — | — | — | ✅ | — |
| `ed_radar_set_trigger_enable` | ✅ | — | — | — | — |
| `ed_radar_set_energy_notify_onoff` | ✅ | — | — | — | — |
| `ed_radar_force_no_person` | ✅ | — | — | — | — |
| `ed_radar_set_presence_switch` | — | — | — | ✅ | — |
| 环境自学习系列(enter/exit/restore/status) | ✅ | — | — | ✅ | — |

> \* **EDV163_ASCII** 目前在抽象层仅支持实例创建(`ed_radar_creat`)。创建后请通过 `ed_radar_get_ctx()` 向下穿透调用 `radar/edv163_ascii.h` 中的专属接口:数据泵直接循环调用 `edv163_ascii_data_handle()`,有人/无人状态用 `edv163_ascii_get_delay_presence()` 读取(基于 `RADAR_PIN_PRESENCE` GPIO 电平)。
>
> \*\* **EDV151** 为生命体征监测雷达(睡眠/心率/呼吸),射频**默认关闭**,创建后需调用 `ed_radar_set_radar_onoff(obj, 1)` 开启才会有体征上报。心率/睡眠报告等专属能力通过 `radar/edv151.h` 向下穿透使用(见 `docs/EDV151-N-H01串口通用协议.md`)。

---

## 4. 特殊定制 API (静默拦截过滤)

部分雷达拥有独特的功能(如环境自学习模式),在此层面您可以随时调用。若当前实例不支持,日志将打印 `not supported` 警告并返回 `ED_FAIL`。

### 环境自学习系列(EDQ152 / EDV11P)
```c
ed_err_t ed_radar_enter_self_learning(ed_radar_obj_t *obj, uint16_t duration_seconds);
ed_err_t ed_radar_exit_self_learning(ed_radar_obj_t *obj, uint8_t save);
ed_err_t ed_radar_restore_self_learning(ed_radar_obj_t *obj);
ed_err_t ed_radar_get_self_learning_status(ed_radar_obj_t *obj, uint16_t *remaining_seconds);
```
### 特殊强制控制
```c
// EDQ152:强制定帧输出无人
ed_err_t ed_radar_force_no_person(ed_radar_obj_t *obj);

// EDQ152:外部触发使能
ed_err_t ed_radar_set_trigger_enable(ed_radar_obj_t *obj, uint8_t enable);

// EDQ152:原始能量图输出开关
ed_err_t ed_radar_set_energy_notify_onoff(ed_radar_obj_t *obj, uint8_t onoff);

// EDV163:触发模式(0-3)
ed_err_t ed_radar_set_trigger_mode(ed_radar_obj_t *obj, uint8_t mode);

// EDV11P:存在检测单独开关
ed_err_t ed_radar_set_presence_switch(ed_radar_obj_t *obj, uint8_t enable);

// EDV11P:目标丢失延时(与 ed_radar_set_detect_delay_time 等价的别名)
ed_err_t ed_radar_set_target_missing_delay(ed_radar_obj_t *obj, uint16_t delay_s);
```

---

## 5. 进阶开发:专属向下穿透策略 (Down-casting)

由于抽象必须妥协,例如 `ed_radar_set_detect_range` 要求通用 XYZ 参数,但如果要对**多扇区雷达 (EDQ152) 进行单通道独立细粒度的配置**,抽象层无法同时覆盖。

`ed_radar_obj_t` 对应用层是**不透明句柄**(内部成员不可直接访问),此时可以通过 `ed_radar_get_ctx()` 安全地取出 `ctx` 指针并调用驱动专属头文件:

```c
#include "ed_radar.h"
#include "radar/edq152.h" // 引用专属驱动头

// type 为创建实例时使用的设备型号(即 ed_radar_config_t.type)
void custom_edq152_setup(ed_radar_obj_t *obj, uint32_t type) 
{
    // 判断实体是否为 EDQ152
    if (type == ED_RADAR_DEVICE_EDQ152) {
        
        edq152_channel_range_t ch_range = {0};
        
        // 独家定制:针对通道1进行 0m 到 3m 的设置
        ch_range.channel = 1;                     
        ch_range.min_motion_dist = 0;             
        ch_range.max_motion_dist = 3000;          
        
        // 通过 ed_radar_get_ctx() 取出真实句柄并安全强转为 edq152_t
        edq152_set_detect_distance((edq152_t*)ed_radar_get_ctx(obj), ch_range);
    }
}
```
通过上述手段:我们兼顾了 **核心层 95% 代码的高度复用统一** ,并保留了 **应用层 5% 对实体特殊性能的安全穿透性**。

Links

Supports all targets

To add this component to your project, run:

idf.py add-dependency "fuhua817/ed_radar^1.1.0"

download archive

Stats

  • Archive size
    Archive size ~ 721.01 KB
  • Downloaded in total
    Downloaded in total 0 times
  • Downloaded this version
    This version: 0 times

Badge

fuhua817/ed_radar version: 1.1.0
|