1. 还没到相位之前:先把中频信号这关过了
很多初学者看毫米波雷达的资料,一上来就撞上"中频信号的相位"这个坎。我最早接触这块内容的时候,也栽过跟头——光顾着盯频率、幅度,相位完全没当回事,结果后面看多普勒测速、MIMO测角的原理文章,每一篇都云里雾里。后来才明白,相位才是把距离、速度、角度这三件事串起来的那根线。
这篇内容就聚焦在"中频信号的相位"这个基础点上,扒开讲讲相位到底是怎么产生的、和哪些物理量挂钩、在真实雷达信号处理链路里又是怎么被使用的。适合刚入门毫米波雷达的同学,也适合做了几年嵌入式或者射频测试、想回头把信号模型捋清楚的人。
先说结论:中频信号的相位,本质上是发射信号与接收信号之间"相位差"在混频之后的投影。理解了这句话,后面所有关于测速、测角的运算都会顺理成章。但这句话展开来,牵扯到FMCW调制方式、混频器的工作机制、ADC采样时机等一系列问题。别急,我们从最基础的天线收发链路一步步走。
2. 中频信号是怎么造出来的
2.1 一个收发链路的基本盘
典型毫米波雷达前端(比如TI的IWR1443、IWR6843这类单芯片方案)内部的工作逻辑其实没想象中复杂:一片信号源产生线性调频连续波(FMCW),经过功分器分成两路——一路直接送到混频器的本振端口,另一路经发射天线辐射出去;辐射出去的电磁波遇到目标反射回来,被接收天线拾取,进入低噪声放大器放大,再送到混频器的射频端口;两路信号在混频器里相乘,输出的差频分量就是我们说的中频信号。
注意这里有个容易忽略的细节:混频器做的是乘法,而乘积会产生两个分量——和频与差频。低通滤波器会把和频分量滤掉,留下来的差频分量才是中频信号。而在FMCW体制下,这个差频分量刚好携带了目标的距离和速度信息,角度信息则藏在不同接收天线之间中频信号的相位关系里。
2.2 FMCW的调频斜率与差频
线性调频连续波发射频率随时间线性变化,斜率用S表示,单位是MHz/μs。一个chirp的周期通常只有几十微秒,在这么短的时间内,如果目标是静止的,接收信号就是发射信号的一个时延副本。设目标距离为R,电磁波往返时间τ = 2R/c(c是光速),那么在第t时刻,接收频率与本振频率之差就是 S·τ,这个差值就是中频频率f_IF。
例如S = 30 MHz/μs,R = 5 m,则τ = 2×5/(3×10^8) ≈ 33.3 ns,f_IF = 30×0.0333 ≈ 1 MHz。这个频率落在MHz量级,ADC采样毫无压力。但很多人没有继续往下多想一步:中频信号除了频率,还有个初相位,这个相位的值等于什么?
2.3 中频信号的完整表达式
把FMCW发射信号写出来,用实信号形式:
s_T(t) = A·cos(2π·f_c·t + π·S·t² + φ_0)
其中f_c是起始频率,φ_0是初始相位。接收信号经历了往返时延τ,并且幅度衰减,再叠加噪声:
s_R(t) = A'·cos(2π·f_c·(t-τ) + π·S·(t-τ)² + φ_0)
混频器把这两路相乘,经过低通滤波后,中频信号的相位可以近似写为:
φ_IF = 2π·f_c·τ + π·S·(2t·τ - τ²)
这里第一项2π·f_c·τ是主导项,第二项里Sτ²的数值在短距离场景下小到可以忽略。把τ = 2R/c代入,第一项变成4π·f_c·R/c。因为波长λ = c/f_c,所以又可以写成:
φ_IF ≈ 4π·R/λ
这个表达式是整个相位问题的核心。它说明中频信号的初相位和目标的距离R成正比,比例系数是4π/λ。λ在77GHz频段大约是3.9mm,也就意味着目标每移动不到1mm,中频信号的相位就会偏转接近一圈。这种"微小的距离变化引起剧烈相位变化"的特性,正是雷达能够测出亚毫米级位移的物理基础。
2.4 为什么用复信号表示中频更好
单独一路中频信号在模拟域就是个余弦波,但进入数字域之后,我们通常不直接拿实数采样来算相位,而是经过I/Q双通道解调,得到一组复数序列:
x[n] = I[n] + j·Q[n]
这样做的理由很直白:实数余弦波cos(2πft+φ)在频谱上有正负两个对称分量,直接用FFT看不出来相位方向;而复数信号e^(j(2πft+φ))只有一个方向的频率分量,相位就是复数向量与实轴之间的夹角,取atan2就能直接算出来。
很多做软件的同学刚开始用实数ADC数据,发现atan2的结果正负乱跳,就是因为没有I/Q两路信息,相位方向无法唯一确定。这算是一个高频踩坑点,我后文还会再提。
3. 相位是怎么"牵"着距离、速度、角度的
3.1 相位差解微小位移:从干涉说起
如果有两帧中频信号,分别对应目标在位置R1和R2,二者的相位差为Δφ = 4π(R2 - R1)/λ。只要ΔR远小于距离分辨率(分辨率由带宽决定,带宽大时可达厘米级),频率上的变化几乎看不出差别,但相位上的变化很明显。
打个比方:中频信号的频率告诉我们目标在"几米"这个量级上待在哪,而相位则告诉我们目标在"零点几毫米"这个量级上动了多少。两者一个管"大数",一个管"小数",配合使用才能实现高精度的位移测量。
我实际测过一个人体呼吸的静态场景:人坐在雷达前约1米处,胸腔起伏幅度大约为5~12mm。在77GHz频段,λ约3.9mm,5mm的位移意味着约4.6π的相位变化。只要连续采集chirp,提取每个chirp中频信号的相位,就能画出胸腔起伏的波形,甚至能区分呼吸和心跳两个频段(呼吸约0.2~0.5Hz,心跳约1~1.7Hz)。这就是生命体征雷达的基本原理,而核心只依赖一件事——相位对微小位移的敏感度。
3.2 相位差测速度:多普勒效应的另一种理解
传统多普勒理论说的是频率变化:运动目标会让接收信号产生多普勒频移f_d = 2v/λ,其中v是径向速度。在FMCW雷达里,单个chirp时间极短,多普勒频率在单个chirp上的体现微乎其微,但在脉冲间(chirp与chirp之间)看,目标移动了ΔR = v·T_c(T_c是chirp周期),于是中频信号的相位变化为:
Δφ = 4π·v·T_c/λ
这一串chirp按照时间排开,每个chirp对应一个相位点,构成一个以多普勒频率为频率的复指数序列。对这个序列做FFT(也就是常说的多普勒维FFT),就能提取出v。
这里有个容易混淆的点:不少人以为多普勒频率f_d直接出现在中频信号的频率上,其实要分场景。静止目标,中频频率只和距离相关;运动目标,在单个chirp期间多普勒频率会叠加进中频频率,但这个频偏量极小——比如v=10m/s,λ=3.9mm,f_d≈5.1kHz,而中频频率动辄几百kHz甚至上MHz,在几十微秒的采样窗口里,这点频偏很难被单chirp的FFT分辨出来。真正可靠的做法是跨chirp比相,也就是通过相位序列来提取速度,这也是为什么测速的核心算法叫"多普勒FFT",拿进去的是复数相位序列,而不是单chirp的中频波形。
3.3 相位差测角度:阵列雷达的本质
假设置雷达有N根接收天线,间距d,远场目标来向与法线夹角为θ,那么相邻天线之间的波程差是d·sinθ,换算成相位差是:
Δφ = 2π·d·sinθ/λ
目标回波在N根天线上产生的相位分别相差这个值,所以对N个天线通道同一时刻的中频复数样本做FFT(角度维FFT),峰值对应的频点就对应着sinθ,再反算θ即可。
这里相位的作用就更为直接了。可以说,角度测量的全部信息都存在于中频信号的相位里。工程上通常要求d不超过λ/2,否则会出现栅瓣;更大的间距虽然能提高测角分辨率,但会牺牲无模糊角度范围,这是一个经典矛盾。
3.4 一个公式串起三个维度
把前面几节串起来,做个总结:
- 距离维:单个chirp中频信号的频率 f_IF = S·2R/c
- 速度维:相邻chirp之间中频信号的相位差 Δφ = 4π·v·T_c/λ
- 角度维:相邻天线之间中频信号的相位差 Δφ = 2π·d·sinθ/λ
这个总结是我当年自己梳理出来的,建议你也拿张纸自己推导一遍。三个维度各自依赖的FFT虽然算法形式上一样,但输入的到底是什么数据、怎么reshape数据阵,是完全不同的。很多人把Range-Doppler-Angle三个FFT连起来做,却不知道为什么是"先距离、再多普勒、最后角度"的顺序,根子上就是对相位在哪个维度发挥作用没有建立清晰的图景。
4. 实操中的相位提取与避坑
4.1 从ADC原始数据到相位值
前端输出的是I/Q两路ADC数据,通常在DSP里以复数数组存成一个Range-Doppler矩阵。以TI的毫米波雷达为例,一帧数据里包含M个chirp,每个chirp包含N个采样点,整体数据可以看作N×M的矩阵:行方向是快时间(距离维),列方向是慢时间(多普勒维)。
提取某个距离单元的相位,步骤大概是这样的:
第一步,对每个chirp的N个采样点做距离维FFT(加窗,通常用Hamming或Hanning来压低旁瓣),得到一个距离谱序列。
第二步,找到目标所在的距离单元索引r_idx。通常在静态场景下,先做一帧积累的平均幅度谱,挑峰值位置,也可以用CFAR检测来定。
第三步,取所有chirp在r_idx处的复数幅值,组成一个长度为M的复数向量。这个向量的每个元素的幅角就是对应chirp在中频信号上的相位。
第四步,对这个复数向量做多普勒维FFT(仍然加窗),峰值对应的频率即多普勒频率,而峰值本身的相位是目标回波在某个初始时刻的相位。
这在数学上每一步都是I/Q复数的线性操作,所以相位信息不会丢。很多初学者有一个误区,觉得"FFT之后相位信息就没了",其实恰恰相反——FFT之后幅角里保存了目标回波的初始相位和跨chirp的相位演变,只不过它们被分散在不同的FFT bin里。
4.2 I/Q不平衡:相位精度的第一杀手
理想情况下I路和Q路应该幅度完全相同、相位严格相差90度。到了实际硬件上,射频通道的混频器、运放、ADC难免引入误差,导致I/Q不平衡。常见症状是:直流偏置不为零、I/Q增益不一致、正交相位误差不等于90度。
这些问题最终都会体现为复信号星座图上圆环变成了椭圆、圆心偏离原点。在提取相位时,圆心偏移会直接给幅角带来畸变——尤其当信号幅度小、距离远时,稍微一点直流偏置就可能让相位读数的误差大到完全不可用。
处理办法分几种:
- 在样本足够多时做校准:采集一段无目标回波的底噪数据,估算直流分量并在后续信号中扣除,这是最容易实现的一种补偿。
- 用系统校准流程:TI等厂商的mmWave SDK里本身带了校准引擎,可以测出I/Q增益和相位失配参数,在DSP里做2x2矩阵校正。
- 如果批量生产,需要在产线上做每个通道的出厂校准,把校准系数烧到板子的非易失存储里。
我第一次做生命体征雷达的时候,完全没有意识到I/Q不平衡的影响。波形图上明明能看到呼吸的起伏,但抖动量很大,后来排查了很久,发现是I路和Q路的增益差达到1.5dB,导致相位解算误差在5度以上。换算成位移误差大约是5度/360度×3.9mm ≈ 0.054mm,看着不大,但连续波段的抖动叠加后信噪比就显著下降。
4.3 相位解缠:别让atan2把你坑了
atan2的返回值范围是(-π, π],也就是说,真实相位如果跨越了这个区间,提取出来的相位就会出现跳变。比如目标微动超过λ/2(约2mm),相位变化就超过一圈,就会看到相位在±π之间跳变。这种跳变处理不当,会让后续的速度估计、位移曲线出现毛刺。
常用解法是相位解缠:检测相邻相位值的差值,如果大于π就减去2π,如果小于-π就加上2π,把相位序列拉成连续曲线。
具体伪代码如下:
def unwrap_phase(phase): unwrapped = [phase[0]] for i in range(1, len(phase)): delta = phase[i] - phase[i-1] while delta > np.pi: delta -= 2 * np.pi while delta < -np.pi: delta += 2 * np.pi unwrapped.append(unwrapped[-1] + delta) return np.array(unwrapped)注意一个细节:相位解缠依赖相邻采样点之间的真实相位差小于π,否则会出现模糊。如果chirp周期太长、目标运动速度太快,采样率不足,解缠结果就会出错。具体来说,就是不等式4π·v·T_c/λ < π必须成立,解出来v_max = λ/(4T_c),这个约束和经典多普勒测速模糊公式v_max = λ/(4T_c)完全一致。所以反过来看,设计chirp周期的时候就要先算好目标最大径向速度,否则后面无论怎么做解缠都救不回来。
4.4 相位噪声与信噪比的权衡
相位噪声来自本振源的不理想。FMCW雷达的线性调频源如果相噪性能差,中频信号的相位会产生随机抖动。这种抖动和热噪声是叠加的:前者直接影响相位读数,后者影响复数的幅值,提取相位时两者都会折算到角度误差上。
工程上有一个很实际的现象:目标回波越强,相位提取越干净;回波一旦接近噪底,相位就变成一堆乱码。原因在于,噪声在I/Q平面上叠加在信号矢量端点上,噪底越高,矢量端点的扰动越大,对应角度误差越大。
定量上,相位误差的均方根值大约为1/sqrt(2·SNR)。如果你想让相位精度达到1度,SNR必须超过20dB以上。这个数在很多应用里是想当然达不到的,不然相位法测位移也不会只适合近距离、强反射目标。
我在调机器人避障雷达的时候,试过用同样的算法跟踪远处墙面,距离8米时的相位抖动比0.8米处大了将近一个数量级,就是因为远距回波SNR衰减太厉害。所以做相位提取之前,先看看Range-Doppler谱上目标峰值高出噪底多少dB,低于15dB的基本就不要指望相位有多准了。
5. 工具箱与上手建议
5.1 用现成芯片快速验证相位模型
对大多数人来说,自己搭射频前端不太现实。更快的路径是拿一块TI的IWR1443BOOST或者IWR6843ISK这类的评估板,直接用毫米波SDK采集原始ADC数据,在MATLAB或者Python里复现整条信号处理链路。
这类板子原始数据格式为复数浮点,获取Phase数据不需要额外硬件,纯软件就能完成。我习惯的做法是:先用官方demo跑通一个标准的目标检测,然后把输出从"目标点云"切换到"距离维复数数据",自己写FFT和相位提取代码。这个过程能帮你在真实数据上验证,理论上推的公式到底和实际吻合度有多高。
我建议的起步练习是:
第一步,在雷达前面放一个角反射器或光滑金属板,位置固定在1米左右。采集一帧原始数据。
第二步,画出距离维FFT幅度谱,确认目标峰值位置。
第三步,提取该峰值在连续几十个chirp上的相位序列,用unwrap处理之后看看是否平稳。注意如果板子有通风振动或者桌面有共振,相位序列会出现周期性起伏。
第四步,用手以极慢的速度前后移动目标(哪怕只有零点几毫米的位移),观察相位波形。你大概率会发现,即使没有任何精确的移动平台,手部微小颤动都能被雷达捕捉到,这就是相位灵敏度的直观体现。
5.2 仿真先行:没有硬件也能把原理吃透
如果你手头暂时没有硬件,用MATLAB也好、Python也好,都能先做一些一维仿真来验证相位推导。仿真步骤就是按第二节的公式生成发射信号,手动加上延时产生接收信号,混频低通后得到中频复数信号,再做FFT、提相位、看相位的演变规律。
我当年自己写过一段很小的Python脚本验证多普勒相移公式。设置S=30MHz/μs,f_c=77GHz,目标以v=1m/s远离雷达,chirp周期T_c=100μs,理论上相邻chirp之间的相位差应该是4π×1×1e-4/3.9e-3≈0.3225rad。仿真得到的相位差和理论值误差在1%以内,当时的第一反应是"这么简单的东西竟然能对上",后来才意识到正是这种简单的推导,构成了整套雷达信号处理的基石。
仿真里还会发现一个有意思的事:如果把目标速度调大,使相位差逼近π,多普勒FFT会出现模糊;超过π后,峰值的速度估计会跳到一个错误的正负方向。这个现象在教科书上写得很枯燥,但亲手跑到之后,你的理解深度和看公式完全不是一个级别。
5.3 三种FFT维度数据的组织形式
用代码写Range-Doppler-Angle处理时,最常出错的就是数据维度的reshape。整理一下标准流程:
假设一帧数据由K个chirp组成,每个chirp有N个采样点,接收天线数为Rx。那么ADC原始数据可以组织成一个三维数组:
axes: (N, K, Rx)
第一步,沿着N轴做距离FFT,得到(N, K, Rx)的距离谱数据。
第二步,对距离谱数据沿着K轴做多普勒FFT,得到(N, K, Rx)的Range-Doppler谱。
第三步,取某个距离-多普勒峰值的索引(n0, k0),把这个索引在所有Rx天线上的复数取出来,得到长度为Rx的向量,对这个向量做角度FFT,峰值位置对应来波方向。
很多初学者搞不清楚为什么要分开处理三个维度,而不是一次做三维FFT。数学上当然可以做三维FFT,但它把所有信息混在一起,不便于逐级做滤波、CFAR检测和门限处理。分步处理的好处是每一级都可以加入独立的算法逻辑,比如距离维加窗压低旁瓣,速度维做MTD(动目标检测),角度维做超分辨算法(MUSIC、ESPRIT),灵活得多。
6. 常见问题与排查技巧实录
6.1 相位乱跳,一帧一个样
这是最常见的现象。多数情况下是目标太弱,SNR不足,噪声主导了相位提取结果。排查路径建议:
- 先看Range-Doppler谱上目标峰值旁瓣高度,确认SNR是否在15dB以上
- 检查目标是否在雷达的波束范围内,比如墙角目标可能在距离谱上露出一半旁瓣
- 排查是否存在强干扰源,比如附近Wi-Fi、5G频段对77GHz的影响虽然小,但板内数字噪声耦合到射频前端的情况并不少见
- 手动把雷达和目标都用三脚架固定,排除机械抖动
还有一种情况,目标明明静止,但相位呈周期性变化。这时重点查电源:开关电源的纹波调谐到VCO上,会让发射频率产生周期性偏移,最终体现为相位上的50Hz/100Hz成分。给板子换线性电源往往立刻见效。
6.2 测速方向反了
多普勒FFT的峰值出现在正频率还是负频率,对应目标的径向运动方向是靠近还是远离。如果方向反了,大概率是I/Q极性接反,也就是I路和Q路的正负号标定搞反了。在接收链路里,I/Q两路谁为正、谁是负,会影响复数的旋转方向。
排查方法是:在雷达正前方把手机/钥匙从近向远匀速移动,分别记录峰值在多普勒谱的哪个符号侧。如果和预期相反,在代码里做复共轭,或交换I/Q两路再重新验证。
注意,不同平台的ADC采样顺序可能不同,TI平台里I/Q采样顺序是固定,但如果你自己做的板子是分时采样,且ADC通道映射和代码假设不一致,就会出现这个经典问题。
6.3 距离FFT的峰值位置和理论距离对不上
这个问题的根子通常不在相位,而在起始频率和调频斜率标定不准。一般有两种可能:
一是调频斜率S有偏差,实际值和寄存器配置值不一致,导致同样的时延算出不同的中频频率。这种情况在宽温场景下尤其明显,温度变化会让VCO特性漂移。
二是FFT频率分辨率限制。FFT频率最小分辨率为fs/N,换算成距离分辨率是c/(2B),B是扫频带宽。比如B=4GHz时,距离分辨率约3.75cm。目标在1.04m处和1.02m处,峰值可能落在同一个bin上,这时相位才是分辨二者微小差别的关键。
6.4 相位解缠失败,曲线出现锯齿
这个问题的根子通常在chirp周期过长,相邻chirp之间的相位差超过π。比如你的目标最快径向速度是2m/s,chirp周期是150μs,那么相邻chirp相位差是4π×2×150e-6/3.9e-3≈0.97rad,还没超限;如果速度到3m/s,相位差就超过π了,解缠就会出错。
处理方法很直接:缩短chirp周期,或者减小调频周期内的占空比。还有另一种思路是提高雷达的工作频率,比如从60GHz换到77GHz,λ变短,相位变化速度反而更快,这会让速度模糊问题更严重,所以频率选择上需要权衡。
6.5 相位精度不够用
如果你的应用对相位精度要求很高(比如位移测量要优于0.1mm),那么除了提升SNR之外,还需要做系统级的校准。主要包括:
- 幅度和相位校准:通过已知位置的角反射器标定每个天线通道的幅相响应
- 温度校准:记录不同温度下的相位偏移,建立查找表补偿
- 逐个器件校准:混频器、放大器、ADC的通路延迟都要做延迟校准
在77GHz频段,1ps的延迟差异在相位上大约是0.28度(2π×77e9×1e-12≈0.48rad?这里需要仔细算,1ps×77e9×2π≈0.48rad≈27.7度,可见延迟校准多么敏感)。通路里任何一个微小的长度差异或器件延迟漂移,都会以相位误差的形式呈现出来。
7. 从相位出发,还能往哪走
中频信号的相位这个知识点的价值,不只是应付考试或者看懂论文,它是连接理论与实践的一座桥。顺着相位这条线索往深处走,你可能会对下面几个方向产生兴趣:
- 微多普勒效应:运动目标上不同部位的微动(旋转、振动)会在相位上调制出边带,这就是微多普勒分析的基础,常用于无人机桨叶识别、人体动作识别等。
- 干涉雷达(InSAR):利用不同时刻观测的相位差,生成地面形变图,分辨率可以达到毫米级甚至亚毫米级。地质监测、桥梁形变监测都用这个原理。
- 太赫兹与光子雷达:更高频率的雷达波长更短,相位对微小位移的敏感度更强,但要同时应对相位噪声更大、高精度系统校准更难的问题。
我自己在这条路上踩过不少坑,总结下来最重要的一点是:分析问题时先回到物理模型,动手写代码之前先把信号流、相位变化用笔推出来。很多看似复杂的信号处理问题,只要弄清了"哪个维度的FFT吃的是哪一组复数数据、相位在哪个维度起作用",思路立刻清晰。
最后再分享一个我实际操作中的小技巧:调试相位相关算法时,不要只看最终曲线,务必把中间级的变量(每个chirp的复数向量、unwrap前后的相位、SNR估算值)全部打印出来逐帧对照。有一次我花了整整半天,最后发现是一个信号从float转换到int时截断了低8位,导致相位抖动量异常。这种问题,只看最终位移曲线无论如何也定位不到,只有对照中间变量才能一眼揪出来。希望这篇内容,能帮你少走一些我当年走过的弯路。