多彩编程 多彩编程MZPH · CODE BLOG
ARTICLE DETAIL

文章详情

深耕前端与后端开发技术的一线实战笔记与踩坑复盘。

毫米波雷达IWR6843+DCA1000原始ADC数据解析与距离-多普勒热力图实测

毫米波雷达IWR6843+DCA1000原始ADC数据解析与距离-多普勒热力图实测 第一次把DCA1000EVM和IWR6843连在一起满心期待点下Trigger然后打开bin文件——满屏“乱码”。这不是什么新鲜事几乎所有入门毫米波雷达数据处理的人都会卡在这一步数据采到了但不知道怎么解析成能看的距离、速度。这篇文章把整个过程拆开揉碎讲清楚从硬件链路、mmwave Studio参数配置到bin文件的字节排列规则再到一套可以直接跑的MATLAB解析代码最后用距离-多普勒热力图验证解析是否正确。适合正在用IWR6843做跌倒检测、存在检测、手势识别这类应用的同学参考也适合刚拿到DCA1000EVM、还没跑通数据流的初学者。1. 硬件链路与采集准备1.1 这套系统是怎么工作的IWR6843是TI的60GHz毫米波雷达传感器板子上集成了3发4收的天线阵列内部自带MCU和DSP可以直接输出目标点云。但如果你要做定制化算法比如自己写CFAR、做微多普勒分析、做呼吸心跳检测就需要拿到最原始的ADC数据。这时候问题就来了IWR6843板载的USB接口默认只能输出处理后的目标级数据拿不到ADC原始采样。DCA1000EVM就是来解决这个问题的。它通过LVDS接口连接IWR6843把雷达前端采样到的中频信号原始I/Q数据搬出来再通过千兆以太网UDP包发给电脑保存成bin文件。整个数据链路是这样一个走向IWR6843射频前端 → ADC采样 → LVDS输出 → DCA1000EVM → 千兆网口 → PC端bin文件这里有个关键点DCA1000不负责目标检测它就是一个“数据搬家工”把ADCBuf里的原始采样逐bit搬到电脑里。所以数据解析这件事必须在电脑端用代码自己完成。1.2 采集前必做的三件事硬件接线直接影响数据质量我第一次踩坑就是供电问题。注意三项供电DCA1000EVM需要独立12V供电IWR6843通过DCA1000的接口供电不需要单独接。千万别只插IWR6843的USB就指望DCA1000工作。网口直连用网线直接把DCA1000的网口和电脑网口连起来不要经过路由器减少丢包。电脑网卡配置静态IP为192.168.33.30子网掩码255.255.255.0DCA1000默认IP是192.168.33.180确保在同一网段。启动顺序先给DCA1000上电等指示灯稳定后再打开mmwave Studio避免上位机识别不到设备。mmwave Studio里的配置是另一个容易翻车的地方。打开软件后在“mmWave Sensors”里选择IWR6843进入配置界面。关键参数在“Sensor Config”和“DCA1000”两个模块其中有几个要注意Data Mode必须选择LVDS模式4-bit LVDS这一步不能漏否则DCA1000拿不到数据。每帧chirp数、每chirp采样点数需要和你后面MATLAB代码里的参数严格对应。配置完记得点“DCA1000 ARM”和“Trigger Frame”等待采集完成后再点“Save”保存bin文件。2. bin文件到底长什么样数据格式拆解2.1 文件头怎么跳用MATLAB打开bin文件后前几十个字节往往不是我们需要的ADC数据。DCA1000保存的bin文件一般带有一个文件头常见长度是40字节20个int16。不同固件版本可能有差异有的版本是581字节有的版本开头有一段Magic Word标识。一个通用做法是先用fopen打开文件读前100个int16转成十六进制看一眼。如果你看到开头几个数像0x7243、0x5A4D、0xA5A5这种规整的Magic Word说明这些是文件头直接跳过。如果没有Magic Word、打开就是有规律的连续数据可能不需要跳过或只需要跳过少量字节。我在代码里统一按40字节头处理这是目前大多数固件版本和教程里最常见的格式。如果你用不同版本导出的bin文件解析出来波形不对优先检查这里。提示文件头偏移判断错了后面的IQ交错、通道顺序全都会错位而且不容易发现。建议在正式处理前先打印前几十个采样点确认一下排列规律。2.2 真正的ADC数据排列跳过文件头之后剩下的就是原始ADC采样数据数据类型是16bit有符号整数int16。这里有两个关键概念需要理解第一IQ数据交错。IWR6843内部ADC采样出来的是复数信号分为I路同相和Q路正交DCA1000传输时把I和Q交替排列。也就是说每两个int16代表一个复数采样点第一个是I第二个是Q。如果配置成实数据模式才没有这一层交错。第二多通道顺序排列。IWR6843有4个接收通道RX1~RX4在每一个采样时刻4个通道的数据按顺序排列排列规律是RX1(I) → RX1(Q) → RX2(I) → RX2(Q) → RX3(I) → RX3(Q) → RX4(I) → RX4(Q)然后才是下一个采样时刻。这个排列方式决定了reshape时每一列是2×numRx个数而不是别的长度。如果搞错了顺序距离FFT出来的峰值位置会对不上真实目标位置。3. MATLAB解析代码与参数计算3.1 从读取到复信号还原完整代码直接上代码。这个脚本我测试过很多次按下面的配置参数改一下就能跑通。%% 参数定义和mmwave Studio里的配置严格一致 numRx 4; % 接收通道数 numSamplesPerChirp 256; % 每个chirp的ADC采样点数 numChirpsPerFrame 128; % 每帧chirp数量 numFrames 10; % 采集帧数 numChirpsTotal numChirpsPerFrame * numFrames; %% 读取bin文件 fileName adc_data.bin; fp fopen(fileName, rb); if fp -1 error(打不开文件检查路径); end % 跳过文件头DCA1000 bin文件常见为40字节 headerLenBytes 40; Header fread(fp, headerLenBytes/2, int16); % 读取后丢弃 % 读取剩余ADC数据int16有符号数 rawData fread(fp, int16); fclose(fp); fprintf(读取到 %d 个int16数据点\n, length(rawData)); %% 数据长度校验 expectedLen 2 * numRx * numSamplesPerChirp * numChirpsTotal; if length(rawData) ~ expectedLen warning(数据长度不匹配实际 %d预期 %d请检查参数配置, ... length(rawData), expectedLen); end %% IQ分离与通道重排 % 原始排列: RX1_I, RX1_Q, RX2_I, RX2_Q, RX3_I, RX3_Q, RX4_I, RX4_Q % 先重排成 2*numRx 行 adcIQ reshape(rawData, 2*numRx, []); % 奇数行是I路偶数行是Q路 iData adcIQ(1:2:end, :); qData adcIQ(2:2:end, :); % 合成复数信号大小为 numRx x (总采样点数) adcComplex iData 1j * qData; %% 按chirp和帧整理 % 每个chirp上面有 numSamplesPerChirp 个复数采样点 % 先reshapenumRx x numSamplesPerChirp x numChirpsTotal adcData reshape(adcComplex, numRx, numSamplesPerChirp, numChirpsTotal); % 转成 [numSamples x numChirps x numRx]方便后面沿距离维做FFT adcData permute(adcData, [2 3 1]); fprintf(解析后的复数据矩阵大小%d x %d x %d\n, size(adcData));这段代码的核心就三步读数据、IQ合成、按维度重排。做完这一步你已经拿到了纯正的ADC复数矩阵剩下的FFT处理都基于这个矩阵。有一个细节要留意如果某一帧数据丢失或者以太网UDP丢包rawData的长度会发生偏差reshape会直接报错。代码里的长度校验就是用来兜住这种情况的。3.2 距离/速度分辨率怎么算解析出复数据之后下一个步骤是算目标距离和速度但算之前得先清楚每个FFT bin对应多少距离、多少速度。这几个公式是雷达基础建议直接抄下来用。距离维相关的两个关键参数距离分辨率ΔR c / (2B)其中B是chirp的扫频带宽最大不模糊距离Rmax c·Fs / (2S)其中Fs是ADC采样率S是chirp斜率速度维相关的两个关键参数速度分辨率ΔV λ / (2·Tf)其中Tf是一帧内所有chirp的总时间λ是载波波长最大不模糊速度Vmax λ / (4·Tc)其中Tc是一个chirp的周期举个实际例子。60GHz频段载波波长约5mm假设chirp配置为斜率S 50MHz/μsADC采样率Fs 5MHz每个chirp采256个点则chirp有效扫频时间约51.2μs带宽B 50MHz/μs × 51.2μs 2.56GHz。代入公式ΔR 3e8 / (2 × 2.56e9) ≈ 0.058m也就是约5.8cmRmax 3e8 × 5e6 / (2 × 50e12) ≈ 15m这组配置比较适合中短距离目标探测。如果要做更远距离需要降低斜率或降低采样率但分辨率会跟着变粗这是互相制约的关系。在MATLAB里可以直接写成一个参数计算小块方便调节配置后自动更新坐标轴刻度。%% 距离/多普勒坐标轴计算 c0 3e8; % 光速 fc 60e9; % 起始频率 lambda c0 / fc; % 波长约0.005m Fs 5e6; % ADC采样率根据mmwave Studio配置改 slope 50e12; % 斜率注意单位MHz/us需要转成Hz/s B slope * numSamplesPerChirp / Fs; rangeRes c0 / (2 * B); % 距离分辨率 maxRange c0 * Fs / (2 * slope); rangeAxis (0 : numSamplesPerChirp-1) * rangeRes; Tc 80e-6; % chirp周期单位秒 speedRes lambda / (2 * numChirpsPerFrame * Tc); maxSpeed lambda / (4 * Tc); dopplerAxis linspace(-maxSpeed, maxSpeed, numChirpsPerFrame);3.3 校验解析是否正确的小技巧数据解析完成后先别急着上复杂算法用最直观的方式验证对准一个静止目标比如一面墙、一个人站着不动做距离FFT在0多普勒附近应该出现一个明显峰值峰值对应的距离要和实际距离基本吻合。具体做法取一帧数据对每个chirp做距离维FFT取平均幅度然后找到最大峰位置算一下对应距离。%% 快速校验单帧距离FFT frameIdx 1; % 取第1帧 startIdx (frameIdx-1) * numChirpsPerFrame 1; endIdx frameIdx * numChirpsPerFrame; % 取一帧数据: numSamples x numChirps x numRx frameData adcData(:, startIdx:endIdx, :); frameData mean(frameData, 3); % 4个RX通道平均 % 距离维FFT rangeFFT fft(frameData, 256, 1); rangeProfile abs(rangeFFT(1:128, :)); meanProfile mean(rangeProfile, 2); % 找峰值 [~, idx] max(meanProfile); estimatedRange (idx - 1) * rangeRes; fprintf(最强目标距离约 %.2f m\n, estimatedRange);如果这个距离值和实际完全对不上大概率是三个原因数字上变频方向的顺序搞反了、IQ分离时奇偶取反了、或者文件头没跳干净。这属于解析层的问题跟后处理的FFT算法无关先把这里的值调对了再往下走。4. 距离-多普勒热力图与目标初检4.1 一维距离FFT与静态杂波抑制验证了解析没问题接下来就可以做完整的距离-多普勒二维处理了。先做距离维FFT这一步把每个chirp时域采样转换成距离维频率谱。%% 距离维FFT NfftRange 256; % 距离FFT点数一般取2的整数次幂 rangeFFT fft(adcData, NfftRange, 1); % 沿第1维采样点维做FFT % 取单边谱正频率部分 rangeFFT rangeFFT(1:NfftRange/2, :, :);这里要注意一个点静止目标和运动目标在距离维FFT之后都会出现峰如果室内场景有墙、桌子这些静止物体它们的能量会非常强把运动目标完全淹没。所以需要做一个静态杂波抑制操作常用做法是沿着chirp维减去平均值。原理很简单静止目标在帧内的所有chirp上幅度相位基本不变对所有chirp取平均就近似等于静止杂波每个chirp减去这个均值静止目标就基本被干掉了动态目标则保留下来。%% 静态杂波抑制MTI平均相消 rangeFFT rangeFFT - mean(rangeFFT, 2); % 按chirp维减均值广播到所有chirp这个操作对呼吸心跳检测、微动目标检测特别重要。做存在检测时如果目标走动这一步能显著提升后续检测概率。4.2 二维多普勒FFT与热力图绘制距离维处理完继续沿chirp维做多普勒FFT得到距离-多普勒图。多普勒维表示目标的径向速度信息正速度表示朝雷达靠近负速度表示远离。%% 多普勒维FFT NfftDop 128; % 多普勒FFT点数 dopplerFFT fftshift(fft(rangeFFT, NfftDop, 2), 2); dopplerMap abs(dopplerFFT); % 4个RX通道非相干累加提升信噪比 map2D squeeze(mean(dopplerMap, 3)); %% 绘制距离-多普勒热力图 figure; imagesc(rangeAxis, dopplerAxis, 10*log10(map2D eps)); xlabel(距离 (m)); ylabel(速度 (m/s)); title(距离-多普勒热力图); colorbar; axis xy;画出来的热力图里静止目标会出现在0速度附近那条线上运动的行人会出现一个亮斑横轴位置是距离纵轴位置是速度。行的速度约1~2m/s跑步约3~5m/s你可以根据纵轴位置大致判断目标运动状态。这里解释一下两个函数的用途fftshift是把零频移到频谱中间方便显示正负速度距离维FFT用的是单边谱所以不需要fftshift。如果后续要做到自动目标检测可以在距离-多普勒图上做CFAR检测。常用的有CA-CFAR、OS-CFAR等二维CFAR相对复杂一点我后面专门写一篇展开讲这里先用热力图人工观察验证整条数据链路是否正常。5. 常见问题与踩坑实录5.1 数据长度对不上、全零、错位怎么办做数据解析最烦的就是错误不报在明面上而是悄悄给一个错误结果。我把实际操作中遇到的问题整理成了表格方便快速对照排查。现象可能原因解决办法reshape报错数据长度对不上每帧chirp数、采样点数配置和代码不一致打印实际数据长度核对mmwave Studio里的配置尤其注意帧数是否按预期采完数据全是0或大量重复值LVDS接线松动、DCA1000未正确ARM检查硬件连接重新在mmwave Studio里执行ARM再Trigger距离FFT峰值位置不对文件头跳过字节数不对、IQ奇偶取反打印文件头部十六进制确认偏移量交换I/Q顺序测试热力图0速度处有超强信号且不衰减正常现象是墙面等静止杂波做静态杂波抑制后观察动态目标数据有偶发跳变幅度异常以太网UDP丢包使用千兆网卡、直连网线、关闭网卡节能模式、采集时避免其他大流量解析结果多普勒速度正负反了距离FFT相位方向理解偏差这通常是符号习惯问题确认配置中的频率上升/下降斜率速度轴向整体取反即可采样点数和chirp数对不上是我遇到最多的问题。记得一次采集200帧数据mmwave Studio里的“Frame count”设置成200但实际Save只保存了187帧导致reshape一直报错。后来发现是丢包导致的降低采样率后问题就消失了。5.2 大数据量下MATLAB卡死/内存不足的优化当每帧chirp多、帧数也大的时候一次把整个bin读进内存很容易爆内存。比如IWR6843配置256个采样点、每帧256个chirp、采1000帧4通道IQ模式下数据量大概有2GB直接fread会造成系统卡顿甚至OOM。我常用的优化方式是改用memmapfile逐帧处理不需要一次性把整个文件都读进内存。核心思路是把bin文件映射成内存映射数组按帧切好一帧一帧做FFT结果只保留最终的距离-多普勒图或者检测结果。%% 使用memmapfile逐帧读取示例 % 定义每帧的int16数量 frameSamples 2 * numRx * numSamplesPerChirp * numChirpsPerFrame; m memmapfile(adc_data.bin, Format, int16, ... Offset, headerLenBytes, Repeat, inf); allData m.Data; numTotalFrames floor(length(allData) / frameSamples); for frameIdx 1:numTotalFrames frameRange (frameIdx-1)*frameSamples 1 : frameIdx*frameSamples; rawFrame allData(frameRange); % 这里放入IQ分离、FFT等处理逻辑 end注意memmapfile的Offset参数只能按字节算这里传入的是40字节的headerLenBytes。如果文件名路径里有中文部分老版本MATLAB可能识别不了建议路径保持英文。另外还有一个性能细节MATLAB的fft在多通道大矩阵上支持直接沿指定维度计算不要用for循环逐个chirp做FFT向量化写法快几十倍。上面代码里fft(rangeFFT, NfftRange, 1)就是一次把全帧所有chirp、所有通道的距离FFT都算了这种写法要养成习惯。5.3 我对这套链路的使用体会用这套DCA1000EVM加IWR6843的方案做数据采集和算法验证整体体验是硬件链路稳定数据质量在60GHz频段传感器里算相当不错的难点不在采而在后面解析和标注那一大堆脏活。我个人的建议是采集数据时养成一个好习惯每次实验把mmwave Studio里的完整配置截图或存成txt同时在代码里把采样率、斜率、chirp数等参数以注释形式写在脚本头部。否则三个月后回来看数据你根本不知道当初这组bin文件是用什么参数采的等于废数据。数据解析完之后的扩展空间很大。你已经拿到了距离-多普勒-角度三维复数数据后面可以做恒虚警检测、多目标跟踪、微多普勒分类、甚至用深度学习做手势识别。解析只是起点但这一步走稳了后面的路就顺了。
返回列表