1. 注意事项:
(1)在每次捕获中,第一帧都可能损坏,建议忽略所有捕获的第一帧;
(2)在使用Cascade_capture.lua文件采集数据时,如果“num_frames_to_capture”参数为 0,则当 AWR 设备配置为发送有限数量的帧时,TDA2 捕获的帧数比 AWR 设备发送的帧数少 1。但是,如果“num_frames_to_capture”参数设置为非零值,则 TDA2 将正确捕获该数帧。
num_frames_to_capture = 0 -- 0: default case; Any positive value - number of frames to capture
(3)在复数 1x/2x 模式下,每个线性调频的最大样本数目前限制为 512 个,在实数模式下限制为 1024 个。这是 TDA2 的局限性。目前没有解决方法。
(4)不支持 12 位和 14 位 ADC 数据格式模式。仅支持和验证 16 位 ADC 数据。
2. Cascade_capture.lua中的参数设置
capture_time = 2000 -- ms
inter_loop_time = 2000 -- ms
capture_time 和inter_loop_time的设置应大于总的采集时间。
3. 丢帧问题
采集到的数据保存在C:\ti\mmwave_studio_03_00_00_14\mmWaveStudio\PostProc目录下
使用TI官方给出的代码,输入idx文件路径计算有效帧:
function [numIdx, dataFileSize] = getValidNumFrames(adcIdxFileName)
idxFile = fopen(adcIdxFileName,'r');
heaferInfoSize = 6;
heaferInfo = fread(idxFile, heaferInfoSize,'uint32');
%有效帧数
numIdx = heaferInfo(4); % number of effective frame %有效帧数
fclose(idxFile);
idxFile = fopen(adcIdxFileName,'r');
heaferInfoSize = 3;
heaferInfo = fread(idxFile, heaferInfoSize,'uint64');
%有效帧数的数据大小
dataFileSize = heaferInfo(3); % data size for the effective number of frames
fclose(idxFile);
end
AWR2243采集数据时会出现随机丢帧问题。丢帧数可能跟capture_time 和inter_loop_time,frame周期,chirp周期有关。frame周期与chirp周期越大,丢帧现象越不明显。
采集到的数据大小应为:每chirp采样点数(256)*每个芯片RX数(4)*总TX数(12)*每帧chirp数*帧数*4.
出现丢帧时,可通过Winscp检查sd卡存储的数据(mnt/ssd路径下)与pc端数据大小是否一致,若不一致说明是传输问题,将sd卡数据直接复制过来即可。若一致则重新采集.
若多次采集数据仍丢帧,重启——重启能解决大部分问题
定期清理sd卡数据,内存不足也可能导致丢帧
4. 通过mmwave studio无法连接TDA板
按照用户手册13节:
关于如何刷新SD卡数据参考用户手册第9节:
5. 数据采集为空
雷达采集完成后,启用winscp传输数据时,显示捕获到的文件为0。
这种情况时而会出现,在配置没有问题的情况下重启可解决。
6. 数据读取函数
TI官方给出的数据处理案例中C:\ti\mmwave_studio_03_00_00_14\mmWaveStudio\MatlabExamples\4chip_cascade_MIMO_example
由于存在多普勒FFT的步骤,要求每帧chirp数大于等于16,否则程序无法正常运行:
scaleFactor函数要求输入参数为正数,因此要求nchirp_loops>8,即每帧chirp数至少为16。
根据TI的计算有效帧的函数getValidNumFrames.m,修改了读AWR2243Cascade数据的代码。
(1)主函数read_ADCdata_main.m如下:
clear
clc
adcIdxFileName = 'C:\ti\mmwave_studio_03_00_00_14\mmWaveStudio\PostProc\Cascade_20231215Test3\master_0000_idx.bin';
[numIdx dataFileSize] = getValidNumFrames(adcIdxFileName);%计算有效帧
numSamplePerChirp=256;%每个脉冲采样点数
numChirpPerLoop = 12;%发射天线数量
numLoops = 1;%每帧chirp数
numRXPerDevice = 4;%每个chip的RX数量
numDevices = 1;
dataFolder='C:\ti\mmwave_studio_03_00_00_14\mmWaveStudio\PostProc\Cascade_20231215Test3';%cascade路径
radar_data_Rxchain = zeros(numSamplePerChirp, numIdx-1,16,numChirpPerLoop) ;
for frameIdx=2:1:numIdx%对每一帧数据进行读取
radar_data_Rxchain(:,frameIdx-1,:,:) = read_ADC_bin_TDA2_separateFiles(dataFolder,frameIdx,numSamplePerChirp,numChirpPerLoop,numLoops, numRXPerDevice, numDevices);
end
save('adcDataAWR2243cascade_256_318_16_12.mat','radar_data_Rxchain');
(2)计算有效帧函数
function [numIdx dataFileSize] = getValidNumFrames(adcIdxFileName)
idxFile = fopen(adcIdxFileName,'r');
heaferInfoSize = 6;
heaferInfo = fread(idxFile, heaferInfoSize,'uint32');
numIdx = heaferInfo(4); % number of effective frame
fclose(idxFile);
idxFile = fopen(adcIdxFileName,'r');
heaferInfoSize = 3;
heaferInfo = fread(idxFile, heaferInfoSize,'uint64');
dataFileSize = heaferInfo(3); % data size for the effective number of frames
fclose(idxFile);
end
(3)修改后的adcdata读取文件
%% read raw adc data with MIMO
function [radar_data_Rxchain] = read_ADC_bin_TDA2_separateFiles(dataFolder,frameIdx,numSamplePerChirp,numChirpPerLoop,numLoops, numRXPerDevice, numDevices)
fileNameCascade_master ='master_0000_data.bin';
fileNameCascade_slave1 = 'slave1_0000_data.bin';
fileNameCascade_slave2 ='slave2_0000_data.bin';
fileNameCascade_slave3 ='slave3_0000_data.bin';
fileFullPath_master = fullfile(dataFolder,fileNameCascade_master);
fileFullPath_slave1 = fullfile(dataFolder,fileNameCascade_slave1);
fileFullPath_slave2 = fullfile(dataFolder,fileNameCascade_slave2);
fileFullPath_slave3 = fullfile(dataFolder,fileNameCascade_slave3);
[radar_data_Rxchain_master] = readBinFile(fileFullPath_master, frameIdx,numSamplePerChirp,numChirpPerLoop,numLoops, numRXPerDevice, numDevices);
[radar_data_Rxchain_slave1] = readBinFile(fileFullPath_slave1, frameIdx,numSamplePerChirp,numChirpPerLoop,numLoops, numRXPerDevice, numDevices);
[radar_data_Rxchain_slave2] = readBinFile(fileFullPath_slave2, frameIdx,numSamplePerChirp,numChirpPerLoop,numLoops, numRXPerDevice, numDevices);
[radar_data_Rxchain_slave3] = readBinFile(fileFullPath_slave3, frameIdx,numSamplePerChirp,numChirpPerLoop,numLoops, numRXPerDevice, numDevices);
% Arranged based on Master RxChannels, Slave1 RxChannels, slave2 RxChannels, slave3 RxChannels
% The RX channels are re-ordered according to "TI_Cascade_RX_ID" defined in
% "module_params.m"
radar_data_Rxchain(:,:,1:4,:) = radar_data_Rxchain_master;
radar_data_Rxchain(:,:,5:8,:) = radar_data_Rxchain_slave1;
radar_data_Rxchain(:,:,9:12,:) = radar_data_Rxchain_slave2;
radar_data_Rxchain(:,:,13:16,:) = radar_data_Rxchain_slave3;
%将四个雷达芯片的数据合并为一个数据。、每个雷达有四个接收天线,也就是numRXPerDevice x 4 = 16
end
function [adcData1Complex] = readBinFile(fileFullPath, frameIdx,numSamplePerChirp,numChirpPerLoop,numLoops, numRXPerDevice, numDevices)
Expected_Num_SamplesPerFrame = numSamplePerChirp*numChirpPerLoop*numLoops*numRXPerDevice*2;
fp = fopen(fileFullPath, 'r');%打开该二进制数据文件
fseek(fp,(frameIdx-1)*Expected_Num_SamplesPerFrame*2, 'bof');%*2是因为复数。使用fseek定位到第frameIdx个帧的起始位置
adcData1 = fread(fp,Expected_Num_SamplesPerFrame,'uint16');%读取到第frameIdx个帧的数据并保存到adcData1中
neg = logical(bitget(adcData1, 16));%对 adcData1 的最高位进行检验,得到 neg 表示哪些数据存在负溢出的标志位。
adcData1(neg) = adcData1(neg) - 2^16;%对发生负溢出的采样值减去 2^16,保证其在有符号 16 位整数范围内。
%%
adcData1 = adcData1(1:2:end) + sqrt(-1)*adcData1(2:2:end);adcData1(1:2:end) + i*adcData1(2:2:end) ;%用来构建每个组合的复数,实部取自后一组采样点,虚部取自前一组采样点。将 16 位实数采样点转换为 32 位复数
adcData1Complex = reshape(adcData1, numRXPerDevice, numSamplePerChirp, numChirpPerLoop, numLoops);
adcData1Complex = permute(adcData1Complex, [2 4 1 3]);
fclose(fp);
end
(4)86个不重合通道的选取和排序
RxForMIMOProcess = [13 14 15 16 1 2 3 4 9 10 11 12 5 6 7 8];
rawData = radar_data_Rxchain(:,:,RxForMIMOProcess, :); %对Rx重新排序
antenna_azimuthonly = [1;2;3;4;17;18;19;20;33;34;35;5;6;7;8;21;22;23;24;37;38;39;40;53;54;55;56;69;70;71;72;85;86;87;88;101;102;103;104;117;118;119;120;133;134;135;9;10;11;12;13;14;15;16;29;30;31;32;45;46;47;48;61;62;63;64;77;78;79;80;93;94;95;96;109;110;111;112;125;126;127;128;141;142;143;144];
rawDataMonostatic = reshape(rawData,Samples_per_Chirp,Num_chirp,Num_RX*Num_TX);
rawDataUniform = permute(rawDataMonostatic(:,:,antenna_azimuthonly),[3,2,1]);%nchannel*Num_chirp*Samples_per_Chirp
其中,RxForMIMOProcess和不重合的86个通道antenna_azimuthonly的来源如下C:\ti\mmwave_studio_03_00_00_14\mmWaveStudio\MatlabExamples\4chip_cascade_MIMO_example\main\cascade\input\test1_param.m文件中:
% New Format TDA
TI_Cascade_TX_position_azi = [11 10 9 32 28 24 20 16 12 8 4 0 ];%12 TX antenna azimuth position on TI 4-chip cascade EVM
TI_Cascade_TX_position_ele = [6 4 1 0 0 0 0 0 0 0 0 0];%12 TX antenna elevation position on TI 4-chip cascade EVM
TI_Cascade_RX_position_ele = zeros(1,16);%16 RX在y轴同一位置,设为仰角维的零点
% Changed for the new Data format
TI_Cascade_RX_position_azi = [ 11:14 50:53 46:49 0:3 ];%16 RX在方位维的坐标,单位为lambda/2
TI_Cascade_RX_ID = [13 14 15 16 1 2 3 4 9 10 11 12 5 6 7 8 ]; %RX channel order on TI 4-chip cascade EVM。固定的
TxToEnable = [12 11 10 9 8 7 6 5 4 3 2 1];
TxForMIMOProcess = TxToEnable;
%TxForMIMOProcess = [1:9 ];
[IdTxForMIMOProcess ia ib] = intersect(TxForMIMOProcess, TxToEnable,'stable' );
if length(IdTxForMIMOProcess)~= length(TxForMIMOProcess)
error('TX channel used for processing is not valid')
end
RxForMIMOProcess = TI_Cascade_RX_ID; %using all 16 RXs, user can also choose subset of RXs for MIMO data analysis
%RxForMIMOProcess = [1:8];
D_TX = TI_Cascade_TX_position_azi(TxToEnable(ib)); %TX方位天线坐标
D_TX_ele = TI_Cascade_TX_position_ele(TxToEnable(ib));%TX仰角天线坐标
D_RX = TI_Cascade_RX_position_azi(RxForMIMOProcess); %RX方位天线坐标
D_RX_ele = TI_Cascade_RX_position_ele(RxForMIMOProcess);%RX仰角天线坐标
%draw the virtual array
plotArray = 1;
RX_id_tot = [];
RX_id_tot_ele = [];
if plotArray == 1
figure(1);
end
for ii = 1:length(D_TX)
RX_id_new = D_RX + sum(D_TX(ii));%TX与RX的方位坐标之和,即虚拟通道的水平维坐标
RX_id_tot = [RX_id_tot RX_id_new];
RX_id_new_ele = D_RX_ele + D_TX_ele(ii);
RX_id_tot_ele = [RX_id_tot_ele RX_id_new_ele];%TX与RX的仰角坐标之和,即虚拟通道的俯仰维坐标
if plotArray == 1
plot(RX_id_new,RX_id_new_ele,'o');grid on; hold on
ylim([-8 8])
end
end
D(:,1) = RX_id_tot;%方位维,相当于x轴坐标
D(:,2) = RX_id_tot_ele;%俯仰维,相当于y轴坐标
ind = find(D(:,2)==0);%寻找D中所有y轴坐标为0的索引
[val ID_unique] = unique(D(ind,1));%寻找所有y轴坐标为0的数据中不重合的数据和索引。相当于找出不重合的86个通道
antenna_azimuthonly = ind(ID_unique); %virtual channel ID only for unique azimuth ID
由于采集过程中,接收天线是按照12,11,10,9,8,7,6,5,4,3,2,1顺序使能的,所以读取到的TX不需要重新排列
而RX是根据chip顺序master,slave1,slave2,slave3排列,所以还要根据RxForMIMOProcess重新排列