简介:面向电子工程与嵌入式开发者的多普勒雷达信号处理实践包,基于HB100(FMCW体制)与RCWL0516(脉冲多普勒体制)两款常见模块,完整演示从微波收发、混频解调到FFT频谱分析与目标速度判别的全流程,适合学习雷达原理、Arduino采集与Python信号处理的入门及进阶人群。包内文件共9个,约28.6MB,其中ino程序负责雷达信号采集,Python脚本实现STFT/PSD分析和可视化,mp4展示实测风扇多普勒回波,jpg/png提供硬件接线与频谱结果,README和settings.txt辅助快速复现实验。目前已有168人浏览学习。包内不仅给出可直接运行的代码,还附带测试视频与图像,便于对照理解多普勒频移与信号处理各步骤;通过修改采样参数和脚本,可迁移至人体感应、速度测量等真实项目,是理论结合实践的紧凑型参考。
1. 两个雷达模块摆在桌上,为什么一个动一个静
把两个雷达模块放到同一块面包板上,供电、天线朝向、测试目标完全一样,输出却像来自两个世界:HB100 的 IF 端只有连续而细微的电压起伏,RCWL0516 的 OUT 端则是干脆的高电平或低电平。有人第一次拿到这套组合时,以为 HB100 坏了,因为万用表量不出任何稳定电压;也有人觉得 RCWL0516 太“傻”,只知道有人没人,给不出速度。实际上两个模块都在正常工作,只是把多普勒信号处理到了不同深度:前者保留了完整的频移信息,后者直接做了存在性判断。标题里提到的多普勒雷达信号处理,核心就是把这种微弱的频移变成可测量、可计算的数据。这篇文章会把 HB100 和 RCWL0516 放在一条完整的测试链路上讲清楚:信号从天线下来之后经历了什么、怎么放大、怎么采样、怎么算出速度,以及哪些地方最容易翻车。适合做小车避障、人体感应、速度测量、手势识别,或者单纯想把雷达信号处理链路亲手摸一遍的硬件开发者。
2. 先弄清两个模块在链路里的位置:HB100 是探针,RCWL0516 是成品
很多人一开始就把希望寄托在模块自身的输出上,忽略了模块内部已经替你做了多少事。HB100 和 RCWL0516 虽然都被叫作雷达模块,但它们处在信号链路上完全不同的位置。把这个问题理清楚,后面所有接线和调试才有方向。
2.1 HB100 与 RCWL0516 的核心差异
HB100 是典型的 X 波段多普勒雷达前端,工作在 10.525GHz,发射连续波,接收回波后直接在模块内部混频,输出一个基带信号,也就是 IF 引脚。这个 IF 信号的频率等于发射频率和回波频率之差,也就是多普勒频移;幅度则和目标的尺寸、距离、反射特性都有关。关键点在于,HB100 只做到“混频出基带”这一步,后面放大、滤波、整形、判断全部交给用户。
RCWL0516 则是一个集成度很高的微波感应模块。它同样基于多普勒原理,但板子上已经把混频输出、前置放大、比较器、定时逻辑全部做完了。它对外提供两种输出:OUT 引脚输出高/低电平,用来直接接单片机 GPIO 或继电器;VOUT 引脚输出模拟电压,可以反映信号的包络变化。对用户来说,RCWL0516 更像一个“成品传感器”,你只需要关心有人没人,而不需要关心 10GHz 信号发生了什么。
差异可以直接看这张表:
| 对比项 | HB100 | RCWL0516 |
|---|---|---|
| 工作频率 | 10.525GHz | 约 3.2GHz 频段 |
| 输出形式 | IF 模拟基带信号 | OUT 开关电平 + VOUT 模拟包络 |
| 信号幅度 | 微伏到毫伏级,需要外部放大 | 内部已处理,可直接接 GPIO/ADC |
| 是否需要外围电路 | 需要放大、滤波、偏置 | 不需要,上电即用 |
| 能测的信息 | 多普勒频移、相对速度、运动方向 | 存在性、触发/锁存 |
| 适合的角色 | 信号处理实验对象 | 对照实验、触发信号源 |
这张表引出一个重要结论:如果你想研究的是多普勒信号处理,HB100 是更好的切入点,因为它的输出还带着原始频移信息;RCWL0516 更适合作为对照,用来验证你对硬件链路的判断是否正确。
2.2 按测试目的选型:要测速选 HB100,要测存在选 RCWL0516
在做“测试多普勒雷达信号处理”这个题目时,常见做法是同时用两个模块。HB100 负责提供原始频移,RCWL0516 负责提供一个已经处理好的输出,两者对照,能帮你快速定位问题是出在硬件链路还是算法逻辑。
如果只想要一个人体感应开关,选 RCWL0516 就够了,它的 OUT 信号可以直接控制灯或者蜂鸣器。但如果想测一个目标的移动速度,比如手挥过模块的速度、小车接近的速度,那就必须用 HB100,或者至少用输出未被阈值电路篡改的模拟通道。RCWL0516 的 OUT 是阈值比较后的结果,已经丢失了连续频移信息,虽然理论上可以从触发频率推断有一定速度,但精度和可解释性都远不如 HB100。
我的习惯是:先用 RCWL0516 确认“这个目标确实能产生多普勒信号”,再用 HB100 接放大电路和 ADC,做完整个频移提取。这样如果 HB100 链路里看不到信号,至少知道不是目标的问题,而是放大或采样的问题。
2.3 信号链路上要补什么
HB100 和 RCWL0516 之间的差距,本质上就是信号链路完整度的差距。RCWL0516 内部已经完成了放大和比较,HB100 则需要你自己搭起以下几部分:
- 前置放大:IF 输出太弱,直接进 ADC 什么都看不到,需要低噪声运放放大 60dB 以上。
- 带通滤波:多普勒频移一般在几十赫兹到几千赫兹,滤掉直流分量和高于 5kHz 的噪声,能显著提高信噪比。
- 电平抬升:IF 信号是双极性的,有正有负,而单片机 ADC 只能采 0 到 3.3V,必须把信号偏置到 1.65V 附近。
- 抗混叠:如果 ADC 采样率不高,需要在滤波里把高频噪声压住,否则频谱分析时会出现混叠。
RCWL0516 则不用做这些,但代价是你只能拿到“已判决”的结果。把这两个模块放在一起理解,你会发现所谓多普勒雷达信号处理,其实一半功夫在做硬件链路,另一半功夫在做频谱分析。任何一个环节没打通,最后都算不出速度。
3. 搭建测试台:从接线到把多普勒信号送进 ADC 采样
第二章解决了“为什么这么选”的问题,这一章开始动手。搭建一个能同时测 HB100 和 RCWL0516 的测试台,需要的物料不多,但接线、放大、采样这三步每一步都有讲究。
3.1 物料清单与最小接线
我给这套测试台推荐的最小物料如下:
| 物料 | 数量 | 说明 |
|---|---|---|
| HB100 雷达模块 | 1 | X波段多普勒前端 |
| RCWL0516 雷达模块 | 1 | 集成微波感应模块 |
| 5V 稳压电源 | 1 | 纹波尽量小,最好 LDO |
| 通用双运放及外围阻容 | 若干 | 搭建两级放大 |
| 某款带 ADC 的开发板 | 1 | 至少 10 位以上 ADC |
| 示波器或逻辑分析仪 | 可选 | 调试放大链路时很有用 |
| 耳机或音频线 | 可选 | 直接听 IF 信号确认信号活着 |
接线的最小原则是:两个模块共地,电源分开滤波。HB100 的 Vcc 接 5V,GND 接系统地,IF 引脚接放大电路输入端;RCWL0516 的 Vcc 接 5V,GND 共地,OUT 接 GPIO,VOUT 接 ADC 第二通道。如果直接把 HB100 的 IF 接到 ADC,大概率采到的是噪声,因为信号幅度太低,所以必须先经过放大。
3.2 HB100 的微伏级信号怎么放大
HB100 的 IF 输出幅度变化很大,近距离挥手可能有几十毫伏,远距离或小目标可能只有几十微伏。我一般会用两级运放,第一级提供 50 到 100 倍放大,第二级提供 20 到 30 倍放大,总增益控制在 60dB 到 70dB 之间。
下面是一个典型的放大电路结构,用普通双运放就能搭:
IF 信号 --- 10uF 隔直电容 --- 10k 电阻 --- 运放A 同相输入端 | 运放A 输出 --- 1k 电阻 --- 10uF 电容 --- 运放B 同相输入端 | 运放B 输出 --- 1.65V 偏置电压叠加 --- ADC 输入这个电路里隔直电容负责把 IF 信号里的直流成分去掉,因为 HB100 的 IF 在静止时接近 0V,但会有漂移。第一级运放放大后,第二级再做一次放大并叠加 1.65V 偏置,目的是把双极性信号整体抬升到 ADC 输入范围的中间点。
如果你不想自己调运放电路,也可以用音频前置放大模块,但必须确认它的通带范围和输出偏置是否匹配。很多音频放大模块输出以 0V 为中心,直接接 ADC 会把负半周削掉,仍然需要后级加偏置。放大倍数不是越大越好,后面避坑章会专门讲削顶失真。
3.3 两个模块的信号输出到底接哪
RCWL0516 的接线比较直接。OUT 接 GPIO,用来读取高电平触发;VOUT 接 ADC,可以在示波器或者串口绘图里看到信号包络。需要注意的是,RCWL0516 的 VOUT 输出的是包络信号,不是原始的 IF 波形,所以不要指望从 VOUT 算出精确速度。如果你把 VOUT 接到音响上,移动手掌时能听到类似“沙沙”的声音,但那是包络变化,不是纯正的多普勒频移。
HB100 的 IF 则需要更谨慎地对待。IF 引脚是高阻抗输出,外接电路不要用低阻负载去拉它,否则信号会被直接压没。放大电路输入端至少要 10k 以上的输入阻抗,且连线尽量短,避免引入工频干扰。我习惯在 IF 引脚和第一级运放之间串一个 10k 电阻再加对地 10k 电阻做分压保护,避免运放上电瞬间的反冲损坏模块。
3.4 用示波器/耳机快速确认信号是否活着
在做 ADC 采样之前,最好先用最原始的方式确认雷达信号链路是真的通的。两个办法都很实用:
- 耳机法:把 HB100 的 IF 信号接到耳机放大器的输入端,或者直接接到高阻抗耳机上,手掌在模块前快速晃动,如果听到明显的“呜呜”或“扑扑”声,说明多普勒信号存在。这个方法能听出频移随速度的变化,非常直觉。
- 示波器法:把放大后的信号接到示波器,观察波形包络。手掌静止时只有噪声,手掌挥过时能看到一个纺锤形的包络,内部填充着高频振荡。
我用耳机法确认信号“活了”之后,才会继续做 ADC 采样和软件分析。如果耳机里什么都听不到,先回头查供电和放大电路,不要急着写代码调参数。硬件没通,算法再漂亮也白搭。
完成放大和确认之后,就可以把信号正式送进 ADC。开发板 ADC 采样率设到 8kHz 或 16kHz,采样时长建议至少 2 秒,存成数组或文件用于后续频谱分析。这样采集到的数据里就包含了目标移动产生的完整多普勒频移信息。
4. 把波形变成速度:多普勒公式与 FFT 测频
数据采进来了,下一步是从波形里算出频率,再换算成速度。这一章是整个信号处理的核心,也是最容易让新手迷糊的地方。
4.1 多普勒公式:从频移到速度
多普勒雷达测速的出发点是一个简单公式:
fd = 2 * v * cos(θ) / λ
其中 fd 是多普勒频移,单位 Hz;v 是目标相对雷达的运动速度,单位 m/s;θ 是目标运动方向和雷达波束中心轴的夹角;λ 是雷达工作波长。HB100 工作在 10.525GHz,波长约为:
λ = c / f = 3e8 / 10.525e9 ≈ 0.0285m
把波长代入公式,可以得到一个很实用的换算关系:
v = fd * λ / 2 ≈ fd * 0.0142 m/s
也就是说,如果从频谱里测出 fd = 100Hz,那么目标速度大约是 1.42m/s。这个数字对应成人正常步速的一半左右,所以模块靠近行走的人,频谱峰值通常在几十到几百赫兹之间。
如果目标是斜着移动,测出的速度会偏小,因为公式里的 cos(θ) 小于 1。这是测速实验里最常见的误差来源,后面标定环节会专门处理。
4.2 用 FFT 从采集数据中提取频移
拿到 ADC 采集的数据后,最直接的做法是做 FFT 频谱分析。下面是一段可以直接套用的 Python 脚本,假定你已经把采样数据存成了 WAV 文件,或者从串口导出了 CSV。
import numpy as np from scipy.io import wavfile # 读入波形文件 fs, data = wavfile.read('doppler.wav') x = data.astype(np.float64) # 去除直流分量:静止目标的反射和天线馈通会在 0Hz 附近产生巨大能量 x = x - np.mean(x) # 加汉宁窗抑制频谱泄漏 win = np.hanning(len(x)) xw = x * win # 单边 FFT,只取正频率部分 spectrum = np.fft.rfft(xw) freqs = np.fft.rfftfreq(len(x), d=1/fs) power = np.abs(spectrum) ** 2 # 忽略 0~2Hz 的极低频区,那里往往是呼吸、晃动和直流残留 search_start = np.searchsorted(freqs, 2.0) peak_idx = np.argmax(power[search_start:]) + search_start fd = freqs[peak_idx] # 根据 HB100 波长换算速度 v = fd * 0.0285 / 2 print(f"多普勒频移: {fd:.2f} Hz") print(f"目标速度: {v:.3f} m/s")这段代码做了四件事:读取数据、去直流、加窗、频谱寻峰。去直流这一步非常关键,因为模块近距离的静态反射会造成 0Hz 附近一个非常大的谱峰,如果不滤掉,峰值搜索很容易搜到 0Hz。加汉宁窗是为了抑制旁瓣泄漏,让真正的多普勒峰更干净。
实际使用时,peak_idx 搜索区间可以进一步缩小。如果目标是人,搜索 2Hz 到 1000Hz 足够;如果是车或滑轨上的金属板,范围可以放宽到 2000Hz。把搜索范围收窄,可以有效避开电源纹波引起的尖峰。
4.3 三个必调参数:采样率、窗长、去直流
参数调对了,实验就成功了一半。这三个参数我几乎每次都要确认一遍。
采样率:多普勒频移通常不会超过 3kHz,采样率设 8kHz 已经足够。过高的采样率不会带来更多信息,反而让 FFT 数据量变大,低频段噪声堆积更明显。过低则会出现混叠,比如 1kHz 的信号被折叠成其他频率,测出来的速度完全错误。我一般设 fs = 8000,奈奎斯特频率 4kHz,留足余量。
窗长:FFT 的频率分辨率为 fs / N,N 是样本点数。采样率 8kHz、采样 1 秒,分辨率就是 1Hz,对应速度分辨率约为 0.014m/s。这个精度足够观察步速差异。如果采样时间太短,比如 0.1 秒,分辨率变成 10Hz,速度误差会达到 0.14m/s,测试结果就很粗糙。
去直流:很多人做 FFT 前只做了均值相减,但如果目标长时间静止,信号里还有缓慢漂移,这会让 0Hz 附近的谱峰带着“裙边”,把几赫兹的真实慢速信号盖住。我习惯在代码里先减均值,再加高通滤波,或者干脆把搜索起点跳过 2Hz 以下区域。这个细节能让低速目标的识别率大幅提升。
把这段处理流程跑通之后,你已经能从 HB100 的波形里算出一个数值速度。但实验还没完,因为还有很多情况会让测出来的速度明显不对,比如目标静止时有人走过、放大电路削顶、电源纹波干扰。这些翻车点都集中在下一章。
5. 信号处理里最容易翻车的几个坑
做雷达信号处理,最容易出问题的往往不是算法,而是你不知道信号已经被什么环节污染了。这里列五个我踩过或见过别人踩的坑,每一个都是先写现象,再说原因和解决办法,照着排查能省下很多时间。
5.1 模块不动也输出“信号”,其实是直流偏置和上电毛刺
现象:目标完全静止,RCWL0516 的 OUT 却偶尔拉高;HB100 经过 FFT 后 0Hz 附近出现很大的谱峰,甚至把整个频谱图都压成一条线。
原因:RCWL0516 上电瞬间会有一段自检或复位过程,输出默认拉高几百毫秒;如果程序一上电就读 IO,很容易把这段毛刺当成人存在。HB100 方面,IF 信号里有天线馈通和静态反射产生的直流分量,FFT 里 0Hz 能量巨大是正常的,说明积分噪声全部集中在直流附近。
解决:RCWL0516 的程序里延时 3 秒再读初始状态,或者连续读三次,取多数值作为底数。HB100 的 FFT 处理必须做去直流,并且频谱搜索从 2Hz 以后开始。还有一个笨办法:先用固定目标(比如一本书)压在模块正面,观察频谱峰值是否会移动。如果峰值稳定在 0Hz,说明链路正常;如果出现其他固定峰,则优先怀疑供电噪声。
5.2 HB100 的 IF 输出被万用表压死,误判为坏件
现象:用万用表直流档量 HB100 的 IF 引脚,读数接近 0V,于是断定模块坏了,直接扔掉。
原因:IF 输出是交流基带信号,直流分量本来就接近 0V,万用表测不出有效值。更重要的是,IF 引脚是高阻抗输出,万用表表笔本身会引入相当大的电容和负载,把微弱信号直接“吸”掉。
解决:万用表只用来量供电电压是否正常,不要用来测 IF。判断 HB100 有没有信号,用耳机听最直接:IF 接高阻耳机,手掌快速挥过模块前方,能听到明显的频移声音,就说明模块是好的。没有耳机就用示波器,探头设 AC 耦合,量程放到 50mV 左右,能看到不规则的小幅波形。
5.3 RCWL0516 的 C-M 模式被悬空/接地搞错,触发方式完全相反
现象:人已经离开感应区域,OUT 引脚仍然输出高电平,灯一直亮着,程序怎么重置都没用。
原因:RCWL0516 板子上有一个 C-M 引脚,悬空时是重复触发模式,也就是有人时输出高,人走一段时间后自动恢复低电平;但如果 C-M 引脚被拉低,模块会进入锁存模式,一旦触发就保持高电平,直到断电。
解决:先确认 C-M 引脚有没有被焊盘或飞线意外接地。很多模块默认没有焊接 C-M,悬空即可;如果要做灯控,还可以外接一个跳线控制模式。程序里读 OUT 时,最好设一个“连续 10 次读到低电平才算人离开”的条件,避免信号抖动导致误判。
5.4 电源纹波导致误触发和频谱固定尖峰
现象:FFT 频谱里出现一个不随目标移动变化的固定尖峰,比如 100Hz 或 120Hz;RCWL0516 在无人区偶尔触发。
原因:开关稳压器输出的纹波频率会直接混进放大链路,HB100 的运放增益高达 60dB,几毫伏的纹波会被放大成几百毫伏的假信号。RCWL0516 内部有阈值比较器,电源纹波一旦超过阈值,就会产生误触发。
解决:把 HB100 和运放单独用 LDO 供电,不要和舵机、电机共用电源。RCWL0516 和 HB100 的电源入口各加一个 10Ω 电阻再加 100μF 电容滤波,形成一个简单的低通滤波。示波器看电源纹波时,如果纹波超过 50mV,就优先处理电源,再去调信号链路。
5.5 信号放大后削顶,FFT 出现一堆谐波
现象:FFT 主峰旁边出现 2 倍、3 倍频的小峰,比如目标产生 100Hz 频移,谱图上还有 200Hz、300Hz 的峰;速度读数的绝对值总是偏大。
原因:放大倍数过高,信号正负半周在运放或 ADC 端被削平,原本正弦波变成了近似方波,方波含有大量奇次谐波。FFT 寻峰找到的第一个峰仍然是基频,但如果基频幅度不如谐波,程序就搜到了倍频。
解决:用示波器看放大后的波形,调低增益直到波形完整不削顶。ADC 采样时打印原始值,如果最小值贴着 0、最大值贴着满量程,说明偏置或增益过冲,要把增益至少降三分之一。FFT 寻峰之后做一个合理性检查:从基频往下找 1/2 倍、1/3 倍频处是否也有峰,如果有,大概率是谐波干扰。
这五个坑排完之后,测试台基本稳定了。接下来可以做一些更有意思的验证:用另一个测频方法对比 FFT 结果,再拿已知速度目标做标定。这样测出来的速度才不是“看着像”,而是经得起验证的数据。
6. 更进一步:用过零检测做实时测速对比
FFT 适合离线和整段数据分析,但它的缺点是延迟高,需要攒够一段数据才能算一次。如果你想把测速结果实时用起来,比如控制小车或触发动作,更常用的方法是过零检测。
6.1 过零检测原理
把 HB100 放大后的信号送入比较器,得到一个频率相同的方波,然后用单片机定时器捕获相邻上升沿或下降沿的时间间隔。每个完整周期对应一个多普勒频移周期,周期 T 的倒数就是频率 fd。速度公式仍然是:
v = λ * fd / 2 = λ / (2 * T)
对 HB100 来说,λ 约 0.0285m,如果测得周期 T = 0.01s,频率 100Hz,速度就是 1.43m/s。这个方法的优势是实时性强,一个周期就能算一次,不需要等 FFT 那 1 秒数据。下面是一段常见单片机定时器捕获的流程示意:
// 假设定时器输入捕获,检测到上升沿进入中断 volatile uint32_t last_edge = 0; volatile uint32_t period_us = 0; void input_capture_isr(void) { uint32_t now = timer_get_counter(); // 获取当前计数值 uint32_t diff = now - last_edge; // 计算与前一个上升沿的间隔 last_edge = now; period_us = diff / (timer_clock_hz / 1000000); // 换算成微秒 } // 主循环里直接计算速度 double frequency = 1000000.0 / period_us; double velocity = frequency * 0.0285 / 2.0;这段代码里最关键的是定时器频率要足够高,至少要能分辨 0.1μs 量级,否则低速目标误差会很大。过零检测的坑在于噪声会造成过零抖动,一个周期里可能出现多个毛刺,所以比较器最好加上滞回,或者软件里检测到异常短周期就丢弃。
6.2 低速标定方法:拿已知速度的目标对照验证
不管用 FFT 还是过零检测,都需要一个可信的参考源来验证结果。最省事的标定方法是用一个转盘或者风扇叶片:把一块金属片贴在转盘边缘,转速已知,线速度就是:
v = π * D * RPM / 60
比如直径 0.2m 的转盘,转速 300RPM,边缘线速度约为 3.14 * 0.2 * 300 / 60 = 3.14m/s。把 HB100 对准转盘边缘移动方向,FFT 或过零检测算出的 fd 应该在 220Hz 左右,对应速度 3.14m/s。
实际测试时还要注意夹角。波束轴和运动方向必须基本平行,如果斜着照,速度会偏低,这时候可以用公式里的 cos(θ) 反推实际夹角。室内多径反射会带来峰值分裂,测试环境越空旷越好;如果谱峰出现两个接近的峰,取幅度更大的那个,或者用抛物线插值把峰顶位置修得更准。
过零检测和 FFT 各有用处:FFT 适合分析多个目标或低速目标,过零检测适合实时性要求高的场景。两个方法交叉验证后,再回去看 RCWL0516 的触发,你会对“多普勒信号处理”这件事有很直观的理解。我在这块测试上吃过亏,最开始总嫌弃 HB100 信号小,拼命加增益,结果 FFT 满屏谐波,速度读数忽大忽小。后来老老实实把放大链路调到波形不削顶、电源纹波压到 30mV 以内,算法几乎没有改动,数据就干净了。做雷达信号处理,硬件链路的底子比算法漂亮更重要。希望帮到你。
本文还有配套的精品资源,点击获取