uwb模块测距代码程序 uwb测距代码,h,c文件。 支持基站,标签设置编号(每组支持8个基站128个标签),串口可以看实时距离数据,烧录单片机。 这个是代码资料

直接上干货!最近在折腾UWB模块的测距功能,发现网上开源方案对多设备支持都不太友好。刚好手头有个支持8基站+128标签的工程源码,实测能用串口直接输出距离数据,咱们边看代码边分析实现逻辑。

先看设备地址配置部分。工程里用了个骚操作——通过宏定义控制设备类型:

// 在config.h里切换模式
#define DEVICE_MODE_BASE_STATION  //基站模式
//#define DEVICE_MODE_TAG         //标签模式

// 设备地址配置
#if defined(DEVICE_MODE_BASE_STATION)
    uint8_t device_id = 0x01;  //基站ID范围0x01-0x08
#elif defined(DEVICE_MODE_TAG)
    uint16_t device_id = 0x0100; //标签ID范围0x0100-0x017F
#endif

这种设计让同一套代码适配两种设备类型,编译时切换模式就行。注意标签用16位地址,通过高字节区分不同基站组,实测最多支持16组基站(每组8个)x128标签的架构。

测距核心逻辑在distance_calc.c里,重点看时间戳处理:

double calculate_distance(uint32_t t_prop) {
    // 无线电波速度补偿(单位:米)
    return (SPEED_OF_LIGHT * t_prop) / 1e12 * CORRECTION_FACTOR;
}

void process_twr_data(TwrFrame* frame) {
    uint64_t t1 = frame->poll_tx_ts;
    uint64_t t2 = frame->resp_rx_ts;
    uint64_t t3 = frame->final_tx_ts;
    
    // 计算飞行时间
    uint32_t t_prop = (t2 - t1 - t3) / 2; 
    
    // 温度补偿
    t_prop -= get_temperature_offset();
    
    current_distance = calculate_distance(t_prop);
}

这里用了双向测距(TWR)算法,三点时间戳取平均降低误差。注意SPEEDOFLIGHT常数要根据环境温湿度做动态补偿,不然毫米级误差就出来了。

uwb模块测距代码程序 uwb测距代码,h,c文件。 支持基站,标签设置编号(每组支持8个基站128个标签),串口可以看实时距离数据,烧录单片机。 这个是代码资料

串口输出部分用了轻量级协议:

// 数据包结构
typedef struct {
    uint8_t header[2];    // 0xAA 0xBB
    uint16_t tag_id;
    uint8_t base_id;
    float distance_m;
    uint8_t checksum;
} __attribute__((packed)) DistancePacket;

void send_distance_data() {
    DistancePacket packet;
    packet.header[0] = 0xAA;
    packet.header[1] = 0xBB;
    packet.tag_id = current_tag_id;
    packet.base_id = current_base_id;
    packet.distance_m = current_distance;
    
    // 异或校验
    packet.checksum = packet.tag_id ^ packet.base_id 
                    ^ *((uint8_t*)&packet.distance_m);
    
    HAL_UART_Transmit(&huart1, (uint8_t*)&packet, sizeof(packet), 100);
}

接收端解析时要注意结构体对齐问题,attribute((packed))强制编译器不进行内存对齐。校验用简单的异或操作,比CRC更适合资源有限的单片机。

烧录时容易遇到的坑:不同型号STM32的Flash地址需要改ld文件。比如F4系列要调整这个:

/* STM32F407VG_FLASH.ld */
MEMORY {
    RAM    (xrw)    : ORIGIN = 0x20000000,   LENGTH = 192K
    FLASH    (rx)    : ORIGIN = 0x8000000,    LENGTH = 1024K 
}

遇到过有人把ORIGIN设成0x08000000直接报HardFault,少个零后果很严重...

实测发现标签功耗优化是关键,工程里用了个挺巧妙的动态休眠机制:

void tag_power_manage() {
    static uint32_t last_ranging = 0;
    uint32_t interval = HAL_GetTick() - last_ranging;
    
    // 根据运动传感器数据调整检测频率
    if(accelerometer_active()) {
        ranging_interval = ACTIVE_INTERVAL; //500ms
    } else {
        ranging_interval = SLEEP_INTERVAL;  //5s
        enter_light_sleep();
    }
    
    if(interval >= ranging_interval) {
        wakeup_from_sleep();
        perform_ranging();
        last_ranging = HAL_GetTick();
    }
}

通过加速度计判断设备是否移动,静止时拉长测距间隔,实测能让标签续航时间提升3倍以上。

最后提醒下天线延迟校准的重要性,不同硬件批次记得重新校准:

// 在空旷环境放置标准距离(如10米)
void antenna_delay_calibration() {
    float measured_dist = 10.0; //实际物理距离
    float raw_dist = get_raw_distance();
    
    ANTENNA_DELAY = (raw_dist - measured_dist) * 1e12 / SPEED_OF_LIGHT;
    save_to_flash(&ANTENNA_DELAY); //保存到flash
}

校准值不准确会导致所有测距数据出现固定偏移。有个项目组曾因这个疏忽导致全场定位误差20cm,血泪教训啊!

Logo

智能硬件社区聚焦AI智能硬件技术生态,汇聚嵌入式AI、物联网硬件开发者,打造交流分享平台,同步全国赛事资讯、开展 OPC 核心人才招募,助力技术落地与开发者成长。

更多推荐