Funpack4-1 - 基于DWM3001CDK制作DIY AirTag
该项目使用了DWM3001CDK,实现了DIY AirTag的设计,它的主要功能为:通过DWM3001CDK的蓝牙与UWB实现与手机距离的检测,方位显示与提醒功能。
标签
UWB
AirTag
无线测距
颜七岁
更新2025-04-03
10

项目描述

Qorvo 的 DWM3001CDK 是为基于 DW3110 IC 的 DWM3001C 全集成 (UWB) 模块开发的设计套件,可与 Apple U1 和 U2 芯片互操作。DWM3001C 是一款基于Qorvo DW3110 IC的全集成 UWB 收发模块。 集成DW3110 IC、nRF52833 BLE SoC、平面 UWB 天线、加速度计、电源管理和晶振,大幅缩短设计周期。

内部框图

框图 - Qorvo DWM3001C 6.5GHz与8.0GHz超宽带 (UWB) 模块

本期活动我才用Qorvo 的 DWM3001CDK 开发板设计一款类似于AirTag的物品查找设备。该设备可实现1.5m以内的物品报警功能.

此任务我采用任务1+自命题方式完成。使用蓝牙连接设备,UWB进行距离显示,LED指示灯与蜂鸣器实现声光提醒。


AirTag 是苹果公司于 2021 年 4 月推出的一款蓝牙定位追踪器,主要用于帮助用户追踪和查找重要物品.

  • 精确查找以通过 iPhone 的“精确查找”功能,获取物品的方向和距离信息
  • 声音提示:如果物品在蓝牙范围内,用户可以通过“查找”应用或 Siri 让 AirTag 发出声音,从而快速找到它

简短的硬件介绍

本期我才用DWM3001CDK 开发板板载的LED灯和外接了一款有源蜂鸣器来实现整体功能。

板载有LED四个灯,一个有源蜂鸣器组成。并使用官方提供的Qorvo NearbyInteraction软件查看测距与方位。

整体组成

image.png

实物框图

image.png

软件流程图

在制作功能之前,除去创建了UWB任务初始化之外,还有蜂鸣器的任务,这样我可以在测距的函数中直接调用这个函数实现声光报警。

板载LED初始化,LED初始化有流水灯效果。

void BoardInit(void)
{
bsp_board_init(BSP_INIT_LEDS | BSP_INIT_BUTTONS);
peripherals_init();

for (int i = 0; i < 4; i++)
{

//1号灯
bsp_board_led_invert(BSP_BOARD_LED_0);
nrf_delay_ms(100);
//2号灯
bsp_board_led_invert(BSP_BOARD_LED_3);
nrf_delay_ms(100);
//3号灯
bsp_board_led_invert(BSP_BOARD_LED_2);
nrf_delay_ms(100);
//4号灯
bsp_board_led_invert(BSP_BOARD_LED_1);
nrf_delay_ms(100);
}

}

蜂鸣器初始化与任务创建

    nrf_gpio_cfg_output(BSP_BUZZ);   //引脚初始化
nrf_gpio_pin_set(BSP_BUZZ); // 设置 GPIO 11 高电平
nrf_delay_ms(100); // 延时 500 毫秒
nrf_gpio_pin_clear(BSP_BUZZ); // 设置 GPIO 11 低电平
nrf_delay_ms(100); // 延时 500 毫秒
buzzerQueue = xQueueCreate(5, sizeof(BuzzerCommand_t)); // 创建队列
// 创建蜂鸣器任务
if (xTaskCreate(buzzer_task, "BuzzerTask", BUZZER_TASK_STACK_SIZE, NULL, BUZZER_TASK_PRIORITY, &buzzerTaskHandle) != pdPASS) {
APP_ERROR_HANDLER(NRF_ERROR_NO_MEM);
}
  #define BUZZER_PWM_PIN  11  // 连接蜂鸣器的 GPIO 引脚
#define BUZZER_TASK_STACK_SIZE 128
#define BUZZER_TASK_PRIORITY 2
typedef struct {
uint32_t duration_ms; // 持续时间
uint8_t state; // 0 = 关闭, 1 = 打开
} BuzzerCommand_t;

static QueueHandle_t buzzerQueue; // 队列句柄
static TaskHandle_t buzzerTaskHandle; // 任务句柄
void buzzer_task(void *pvParameters) {
BuzzerCommand_t cmd;
nrf_gpio_cfg_output(BSP_BUZZ); // 配置为输出模式

while (1) {
if (xQueueReceive(buzzerQueue, &cmd, portMAX_DELAY) == pdPASS) {
if (cmd.state) {
nrf_gpio_pin_set(BSP_BUZZ); // 打开蜂鸣器
} else {
nrf_gpio_pin_clear(BSP_BUZZ); // 关闭蜂鸣器
}
vTaskDelay(pdMS_TO_TICKS(cmd.duration_ms)); // 持续时间
nrf_gpio_pin_clear(BSP_BUZZ); // 关闭蜂鸣器
}
}
}
void buzzer_control(uint8_t state, uint32_t duration_ms) {
BuzzerCommand_t cmd = { .state = state, .duration_ms = duration_ms };
xQueueSend(buzzerQueue, &cmd, portMAX_DELAY);
}

UWB的任务初始化与任务的创建

	if (uwb_init() != DWT_SUCCESS) {
APP_ERROR_HANDLER(NRF_ERROR_RESOURCES);
}
DefaultTaskInit();
//探测DW芯片后,驱动程序版本可用
const char ver[] = FULL_VERSION;
const char *drv_ver = dwt_version_string();
const char *mac_ver = uwbmac_get_version();
char str[256];
int sz;
sz = sprintf(str, "Application: %s\r\n", ApplicationName);
sz += sprintf(&str[sz], "BOARD: %s\r\n", BoardName);
sz += sprintf(&str[sz], "OS: %s\r\n", OsName);
sz += sprintf(&str[sz], "Version: %s\r\n", ver);
sz += sprintf(&str[sz], "Modified By: yanqisui\r\n");
sz += sprintf(&str[sz], "%s\r\n", drv_ver);
sz += sprintf(&str[sz], "MAC: %s\r\n", mac_ver);
sz += sprintf(&str[sz], "ACCESSORY_RANGING_ROLE: %s\r\n", (ACCESSORY_RANGING_ROLE) ? "Initiator" : "Responder");
reporter_instance.print(str, sz);
//启动FreeRTOS调度程序。
osKernelStart();
for (;;) {
APP_ERROR_HANDLER(NRF_ERROR_FORBIDDEN);

}

软件运行逻辑图

image.png

功能展示图片及说明

在与手机非常进的时候(距离 <0.1m)

第一个LED0灯会亮,并且蜂鸣器长响,表示物体距离非常近。

最小距离.jpg

在与手机非常进的时候(距离 <0.5m)

第二个LED3灯会亮,并且蜂鸣器50ms响50ms关闭,表示物体距离已接近。

2.jpg

在与手机非常进的时候(距离 <1.0m)

第二个LED3灯会亮,并且蜂鸣器100ms响100ms关闭,表示物体距离已靠近。

3.jpg

在与手机非常进的时候(距离 <1.5m)

第二个LED4灯会亮,并且蜂鸣器关闭,表示物体距离太远。此时应该提醒客户继续更改查找的方向。

4.jpg


主要代码与逻辑实现

      if (distance_cm <= 10)
{
bsp_board_led_on(BSP_BOARD_LED_0);
bsp_board_led_off(BSP_BOARD_LED_3);
bsp_board_led_off(BSP_BOARD_LED_2);
bsp_board_led_off(BSP_BOARD_LED_1);
nrf_gpio_pin_set(BSP_BUZZ);// 蜂鸣器常响

}else if(distance_cm <= 50)
{
bsp_board_led_off(BSP_BOARD_LED_0);
bsp_board_led_on(BSP_BOARD_LED_3);
bsp_board_led_off(BSP_BOARD_LED_2);
bsp_board_led_off(BSP_BOARD_LED_1);
buzzer_control(1, 50); // 蜂鸣器响 50ms
buzzer_control(0, 50); // 关闭蜂鸣器 50ms
}else if(distance_cm <= 100){

bsp_board_led_off(BSP_BOARD_LED_0);
bsp_board_led_off(BSP_BOARD_LED_3);
bsp_board_led_on(BSP_BOARD_LED_2);
bsp_board_led_off(BSP_BOARD_LED_1);
buzzer_control(1, 100); // 蜂鸣器响 100ms
buzzer_control(0, 100); // 关闭蜂鸣器 100ms
}else if(distance_cm <= 150){

bsp_board_led_off(BSP_BOARD_LED_0);
bsp_board_led_off(BSP_BOARD_LED_3);
bsp_board_led_off(BSP_BOARD_LED_2);
bsp_board_led_on(BSP_BOARD_LED_1);
}


项目中遇到的难题和解决方法

由于第一次接触UWB的开发,因此在协议上及开发商遇到了不少的困难,虽然这款NRF52833芯片非常强大。对于前期入门的我来说,开发环境都要搭建好久,最后我在官方的代码中和文件的备注中寻找到了一些线索,通过提供的代码示例,外加大模型来给予解释,因此我很快了解了这款框架的运行逻辑,由于我之前没有接触过FreeRtos因此在编写代码还是比较困难。因为现在AI发展非常好,我很多地方的解读,代码的构建让AI来制作,因此我在给AI喂数据的同时,我也了解了很多,也许这就是作中学,学中作的感觉吧!让我受益匪浅。

对本活动的心得体会

本期的活动让我学习了NRF的开发,使用SEGGER Embedded Studio和官方实例代码完成了一项简单的UWB任务,在这学习期间学到了很多关于UWB的知识,同时通过开发板完成了一个能够解决实际生活的DIY制作。因此我非常心满意足。同时也感谢硬禾学堂举办的Funpack4活动。感谢群友的互助与交流。接下来我会继续学习有关UWB相关的知识和制作。继续给大家分享出有趣好玩的作品。本期就到这里。我们下一期活动再见。


感谢您的耐心阅读

由于工程文件较大,使用网盘进行分项

链接: https://pan.baidu.com/s/1JaoKIlNObF3cPFZ3qQLWzg?pwd=15ut 提取码: 15ut

附件下载
主要代码.zip
团队介绍
电子爱好者
评论
0 / 100
查看更多
硬禾服务号
关注最新动态
0512-67862536
info@eetree.cn
江苏省苏州市苏州工业园区新平街388号腾飞创新园A2幢815室
苏州硬禾信息科技有限公司
Copyright © 2024 苏州硬禾信息科技有限公司 All Rights Reserved 苏ICP备19040198号