
1. 这个项目的由来PLFM_RADAR到底解决什么问题最开始动这个念头其实是源自一次挺尴尬的踩坑。当时我一直在做室内人体存在检测的嵌入式方案先用了PIR红外传感器结果夏天室温一上来人体辐射和背景温差区分度骤降人坐在工位上一动不动超过十分钟输出就飘了后来又试了摄像头方案识别率倒是上去了但隐私问题在办公环境实在绕不开——没有人喜欢自己工位上方的角落挂着一个一直“睁着眼睛”的东西。折腾一圈之后我把目光转向了雷达也就是后来被命名为PLFM_RADAR的这个项目。PLFM其实是Platform的缩写这个项目从一开始就不是想只做一个能用就行的原型而是把它当成一套可复用的雷达感知平台来设计用来完成室内人员的定位、测距、存在状态检测还有最基础的微动感知。整块板子基于调频连续波体制FMCW探测范围设定在10米以内距离分辨力做到了厘米级输出帧率10Hz。这个参数组合不是随手定的而是根据实际应用场景反推出来的室内房间的对角线距离一般不会超过10米人体走动速度低于3m/s呼吸带来的胸腔起伏幅度大约在几毫米到十几毫米之间如果连这个级别微动都要能捕捉到那么距离分辨力和多普勒解算就得按对应的量级来设计。这个项目适合谁参考如果你是做嵌入式感知、智能家居里的存在检测、或者是想在低成本方案里引入毫米波雷达做人员感知那么这套设计思路和踩坑记录应该有挺大的参考价值。因为市面上雷达模组和开发板有不少但大多数资料要么过于偏重理论推导要么只给了API调用示例真正讲清楚中间信号处理链路怎么落地到单片机上、以及实测会遇到哪些问题的内容很少。这篇文章我打算从头梳理PLFM_RADAR的完整设计过程包括硬件选型、信号处理链路、嵌入式移植以及实际测试中的数据和那些让我熬夜排查的bug。2. 硬件架构设计为什么最终选了“雷达前端模组 MCU”而不是射频自研硬件部分的决策过程比我想象中要长主要纠结的点是要不要自己画射频收发链路。坦白说以我的能力做60GHz的射频前端设计不是不可能但风险和成本都太高了一片毫米波收发芯片的BOM成本、PCB板材要求和调试设备门槛都不是小数目。最终我选择了市售的60GHz雷达前端模组作为核心感知器件配合一颗主控MCU来完成数据采集和算法处理。2.1 模组选型数据接口比指标参数更要紧选模组的时候很多人的第一反应是看探测距离和多普勒灵敏度但实际上对于嵌入式集成来说数据接口的友好程度才是最影响开发进度的因素。同样是60GHz毫米波前端有的模组直接输出原始中频ADC数据需要通过外部处理器做距离FFT、速度FFT这些算法有的模组则内置了部分处理直接输出目标点迹。PLFM_RADAR最终选的是一颗输出原始I/Q数据的模组理由有两个第一原始数据意味着算法完全可控。我可以根据自己的需求自由调整距离分辨力、检测门限、目标判定逻辑不受模组内置策略的限制。第二这颗模组通过SPI接口输出数据带宽约12Mbps对主控来说完全吃得下不需要昂贵的高速接口。这里要提醒一个容易踩的坑模组的天线方向图和雷达截面RCS的关系。FMCW雷达检测人体的能力和天线波束宽度密切相关波束太窄会导致靠近雷达两侧的区域有盲区太宽又会拉低增益。我选的是90度方位角、约30度俯仰角的微带阵列天线这个配置在普通室内场景下比较均衡天花板安装和桌面放置都能覆盖合理的范围。2.2 主控MCU的算力估算为什么STM32H7够用然后是主控选型。很多人一听说雷达信号处理第一反应是上FPGA或者DSP其实对于单路FMCW雷达、点数不多的场景一颗带浮点单元的高性能MCU完全够用。PLFM_RADAR的主控用的是STM32H750主频480MHz带双精度FPU板载32MB外部SDRAM用来存中频数据帧。我做了个很粗略的算力估算以单帧为例中频采样率4MSPS一个chirp采样点数是512点一次快扫包含128个chirp那么一帧的原始数据量是512×128×2I/Q两路×2字节大约256KB。距离FFT要做128次每个chirp一次512点复数FFT速度FFT要在距离维基础上再做128点FFT总共256次FFT。以Cortex-M7的FFT库效率来估算512点复数FFT大约需要50~80微秒128点FFT大约12微秒左右整帧处理耗时可以控制在15毫秒以内加上CFAR检测和目标提取一帧总时间预算在40毫秒以内而10Hz帧率要求是100毫秒一帧所以算力有明显的余量。这个结论就是选MCU而不选FPGA的直接依据明明单核MCU就能跑完没有必要给自己增加FPGA开发的复杂度。2.3 板级布局和电源的几条实践经验硬件布局方面有几点实际经验值得写下来。首先是电源噪声雷达前端对电源纹波非常敏感尤其是本振的相位噪声会直接影响中频信噪比。实测下来直接用DC-DC给雷达模组供电底噪会比用LDO供电高出大约6dB这个差距在近距离检测时不太明显但一旦目标距离超过6米检测概率就会明显下降。所以PLFM_RADAR上单独用了一路低噪声LDO给雷达模组供电与主控的数字电源严格分开PCB上做了开槽隔离。其次是晶振的问题。雷达模组和MCU如果共用同一颗参考时钟在某些频段会产生串扰表现为中频信号里出现固定的谱线。我的处理方式是让雷达模组使用独立的25MHz温补晶振MCU的时钟系统完全独立实测这种固定干扰谱线基本消失了。如果你的设计里只能用一颗晶振那么在PCB布局上至少要把时钟走线做包地处理并远离中频输出走线。3. 雷达信号处理的完整链路从ADC数据到目标坐标的每一步信号处理是PLFM_RADAR的核心也是最容易让初学者一头雾水的部分。这一节我按数据流向逐步拆解整条链路每步都说明“为什么这么做”而不是只贴公式。3.1 FMCW测距的第一性原理一个容易被忽略的换算FMCW雷达发射的是频率随时间线性升高的chirp信号回波信号与本地发射信号混频后得到的中频信号频率正比于目标距离。换算关系是中频频率 距离 × 距离分辨率因子。对于带宽B3GHz的60GHz FMCW雷达扫频时间Tchirp 128微秒距离分辨率是c/(2B)5cm中频频率与距离的对应关系大约是每米约6.7kHz。为什么要自己算这个因为很多模组手册只给原始ADC数据你需要自己确定频率轴到距离轴的映射系数这一步算错的话后面所有距离读数都是错的。我在调初始版本的时候犯过一个错误直接用模组示例代码里的默认距离分辨率参数结果测出来1.5米处的目标显示成1.62米排查很久才发现是厂商固件里把有效带宽标成了2.7GHz而不是实际扫频范围3GHz。从那以后我坚持自己用已知距离的强反射目标来标定距离轴偏移量固定放置一个金属板在2米和5米处记录峰位反算系数。3.2 距离FFT和速度FFT数据组织方式是关键原始中频数据在内存中的排列方式是[chirp序][采样点序]做距离FFT时对每一个chirp按采样点维度做512点FFT得到的是距离-慢时间二维数据再做速度FFT时对同一个距离单元、跨chirp做128点FFT得到的就是速度维信息。两维FFT的顺序不能反这也是很多初次接触雷达信号处理的人最容易搞错的地方。距离FFT之后目标的能量会汇聚到对应的距离单元上速度FFT之后运动目标的能量会转移到对应的多普勒单元。静止目标的多普勒频率为零因此落在速度轴的中心点上。这个特性后面会结合静止目标检测问题再展开。3.3 CFAR检测固定门限为什么不可靠FFT做完之后理论上在频谱图上找峰就行了但实际环境里不可能这么理想。比如5米处有一面墙墙的反射能量可能比远处的人体回波还强再比如雷达正下方放了一个金属垃圾桶它产生的固定杂波可能一直霸占某个距离单元。如果使用固定门限要么误报多要么漏检多。PLFM_RADAR里实现的是单元平均恒虚警检测CA-CFAR每个待测距离单元的周围取左右各8个参考单元计算平均值后乘以一个门限系数再与待测单元能量比较。门限系数的选择需要平衡检测率和虚警率。我最终采用的系数是12dB也就是参考平均能量的约4倍。经过半年的室外加室内实测这个值在10米范围内虚警率约为每小时1次而在强反射目标附近误报的概率也很低。需要指出的是CFAR最怕两个目标距离很近比如两个人并肩站在距离分辨单元5厘米以内这种情况下参考单元里会混入目标自身的能量导致门限被抬高弱目标被淹没。室内部署时要接受这个物理限制没有算法能在距离分辨率之内把两个目标稳定区分开。3.4 目标角度估计单通道雷达的极限PLFM_RADAR的前端模组是单发单收1T1R天线配置这意味着它本质上没有测角能力只有距离和速度信息。那么怎么得到目标在房间内的二维位置我的方案是利用距离-多普勒数据辅以应用层逻辑来近似定位单纯径向距离只能告诉你目标在雷达前方多远不能告诉你在左边还是右边。如果期望获得真正的方位角信息硬件上要换1T2R或2T4R的多通道模组用相位干涉法测角。这个改动会显著提升定位能力但也会带来更大的数据量和校准复杂度。PLFM_RADAR保持单通道是有意为之——项目定位是检测“人存在与否”和“大致距离、移动状态”而不是做精准空间定位。这里必须诚实说明硬件边界不然后续应用开发会被“为什么没有方位角”反复质问。4. 嵌入式端的系统工程缓存、时序与实时性优化算法在PC上跑通只是第一步真正让PLFM_RADAR成为一套可用系统的是把它搬到MCU上的过程。这一章记录几个关键工程决策。4.1 DMA乒乓缓存谁也别想阻塞雷达数据流模组通过SPI以突发模式输出一帧原始数据的时候速度接近每秒4MB如果让CPU在中断里逐字节搬运那么整个系统基本腾不出时间做算法。PLFM_RADAR使用的是两个DMA缓冲区交替接收当DMA写满缓冲区A时自动切换到缓冲区B继续接收同时给CPU发出完成中断CPU处理缓冲区A里的数据等下次中断到来时处理缓冲区B。这就是标准的乒乓缓冲结构它能保证数据采集不丢帧、算法处理不吃力。实际调试这个部分的时候有个细节特别容易忽略DMA中断服务函数里要尽快清除标志位但不要做任何复杂操作只做缓冲区指针切换和置一个事件标志真正的处理放到主循环或者RTOS任务里去。如果把FFT放到中断里跑一旦FFT耗时超过相邻SPI传输间隔下一次DMA完成中断就会丢失整个链路就像堵车一样越来越乱。4.2 帧同步和时间戳数据对了才有意义雷达数据只有配合时间戳才真正有价值。单个帧本身可以算出目标的径向距离和速度但如果不知道这一帧对应哪个时刻那么跨帧的轨迹关联、速度平滑、目标计数就都无从谈起。PLFM_RADAR在每个数据帧的头部打上MCU的64位微秒级时间戳同步基准用RTC和系统时钟交叉校准。这样后续做目标追踪或者与摄像头等其他传感器做时间对齐时才有一个可靠的公共时钟参照。其实这里还有一个容易忽略的点模组输出的每一次SPI突发数据并不一定对齐物理帧的边界。有的模组设计上是分片传输比如一帧分成8次SPI读操作。你必须根据模组手册里的帧头字段来拼接数据而不是默认“每次中断一帧”。我最初版本里就犯了想当然的错误导致数据拼接错位CFAR检测到的“目标”实际上是拼接出来的虚假频谱峰。4.3 实时性预算表每一毫秒都算得明明白白为了让系统稳定运行在10Hz帧率我把每一帧的处理耗时做了明确预算通过逐段计时不断优化。处理阶段耗时说明数据搬移与预处理窗函数、去直流4.2ms512×128点浮点乘加开启FPU后很快距离FFT128次512点6.5ms使用STM32H7的硬件三角函数加速器速度FFT512次128点3.1ms距离-多普勒图生成CFAR检测与目标提取1.2ms遍历所有多普勒通道的峰值数据打包与输出0.8ms通过UART以JSON格式输出目标列表合计15.8ms低于100ms的帧周期预算做完优化后整帧耗时16ms左右CPU占用率约15%剩余算力可以留给上层应用比如后期加微多普勒手势识别或者房间占用状态机。不要一开始就上RTOS的多任务设计先把裸机主循环跑通用时间戳打印每一阶段的耗时找到瓶颈之后再决定要不要上多线程架构。5. 实测数据与踩坑记录真实性能往往和手册不一样这一章是偏差最大的部分也是我认为这篇文章最有价值的部分。理论计算再准确实测环境的总会带来一些书本上没说的事。以下数据都是在普通办公室/会议室环境中测得没有经过任何实验室级隔音、吸波处理。5.1 测距精度与稳定性实测目标是一个人从1米处匀速走向7米再返回共5个来回统计每帧输出的距离值与真实位置的偏差真实距离平均测量距离标准差最大偏差1.0m1.03m1.8cm4cm2.0m2.01m1.5cm3cm3.0m3.05m2.2cm6cm5.0m5.04m3.0cm8cm7.0m7.11m4.5cm12cm远距离偏差增大主要来自两个因素一是随着距离变远回波信噪比下降CFAR门限波动导致峰值对应的距离单元发生偏移二是多径效应在5米以上更容易让峰值展宽重心计算受到干扰。实际使用中如果只做存在检测这个精度完全够用如果要做跌倒检测里的距离判断建议配合多帧平滑滤波可以进一步压到3厘米以内。5.2 静止目标检测失败一个经典的“挂尸”问题FMCW雷达的原始输出对完全静止的目标不敏感因为速度FFT上静止目标的多普勒频率为零其能量与墙壁等静态杂波混在一起。如果直接把静态杂波滤除高通滤波那么静止的人也会跟着消失。这就导致一个局面房间里安安静静坐了一个小时的人在雷达看来可能“不存在”。解决这个问题有两种实用的路线。第一种是短时驻留检测利用人体微动——哪怕保持静坐呼吸带来的胸腔起伏依然会产生微小的多普勒调制虽然幅度比运动目标小得多但在距离FFT上对应距离单元的能量会出现周期性起伏。处理方法是观察距离单元的慢时间序列做能量方差统计如果某个距离单元在几秒内的能量波动幅度超过一定阈值就认为有活体存在。PLFM_RADAR把这个阈值设为0.8dB实测在3米内静坐呼吸检测成功率约95%。第二种路线是相位差分检测利用相邻chirp之间的相位变化来放大微小位移。这种方法灵敏度极高但实现复杂、容易受低频抖动干扰。我的建议是如果应用场景就是“检测人是否在房间”用第一种路线足够还能省下不少算力。5.3 多径反射和误报排查一次让我怀疑人生的调试有一阵PLFM_RADAR在会议室里持续在2.5米处报出一个“目标”但实际上那个位置空无一人。排查过程让我深刻体会到多径反射的麻烦。那个会议室的一角放了一根朝天的不锈钢旗杆雷达的电磁波打到旗杆上形成强反射反射波再经由地面二次反射回到雷达等效路径长度恰好比真实距离多出一截形成幽灵目标。后来我把旗杆挪走后误报立刻消失。这说明一个现实强反射体加二次反射路径随时可能生成假目标。针对这类问题我在算法里增加了一个多帧连续性校验——只有同一个距离单元连续超过3帧都存在目标才上报为有效目标瞬时出现的孤立峰值一律丢弃。同时部署时要尽量避免雷达前方存在大面积的金属物体特别是灯架、不锈钢装饰件、玻璃幕墙框架这类东西。5.4 温度漂移不可忽略的系统性误差60GHz雷达对温度比较敏感特别是本振频率随温度漂移会引起中频频率偏移测出来的距离随之缓慢变化。PLFM_RADAR在北方冬天的室内和夏天没有空调的房间里同样的2米距离读数能差出近40厘米。这个漂移是温度的函数不是随机噪声所以可以通过查表校准。我在固件里内置了一个温度-距离补偿表每隔30秒读取一次雷达模组的温度传感器对距离读数做线性修正。校准之后不同温度条件下的测距误差重新回落到了5.1节表格里的水平。6. 后续可以继续深挖的几个方向PLFM_RADAR的上限不止于此项目运行稳定之后我开始考虑那些“加了会显著增值”的方向。这里列出的三个方向都基于同一个判断硬件平台本身不需要大的改动主要是算法层面的升级。6.1 微多普勒分析从“检测到人”升级到“识别人”微多普勒是目标在整体运动之外身体部位微小振动产生的附加多普勒调制。人体的呼吸、心跳、手臂轻微晃动都会在速度谱上留下不同于整体运动的边带特征。PLFM_RADAR现有的10Hz帧率对呼吸检测够用但心跳检测需要20Hz以上的有效帧率所以要升级的话第一件事是把chirp周期缩短、帧率提高然后对慢时间序列做带通滤波提取呼吸和心跳频率成分。这个方向非常适合做成室内体征监测的基础模块。6.2 多雷达协同把“有存在”变成“在哪”单个单通道雷达只能测径向距离。要想得到房间平面的二维定位效果可以用两个PLFM_RADAR分别放在房间的两个角通过通讯协议交换各自的目标距离然后用双基地交汇的方式解算出平面坐标。关键在于两个雷达的时间同步和距离数据标注的对应关系。实测两个雷达协同解算出来的定位精度大约在30~50厘米对于“人躺在卧室的床上还是站在窗边”这种粒度的判断足够用了。6.3 与摄像头系统的多模态融合雷达虽然不怕黑、不侵犯隐私但它的输出分辨率低分辨不了“坐着的是人还是两个抱在一起的娃娃”。摄像头恰恰反之。把雷达检测到目标距离和运动信息作为触发条件引导摄像头只在对准雷达目标区域时进行抓拍识别可以最大程度减少摄像头持续工作的隐私争议也大幅降低视觉算法的算力消耗。这种融合策略目前已经在一些高端安防产品里出现PLFM_RADAR的上位机协议里从一开始就预留了目标坐标输出接口对接这套方案会比较顺手。7. 一些实际使用中的经验之谈算上最初的原型验证板PLFM_RADAR前前后后改了三版硬件、重写了四次固件。有个体会值得说一下这个项目真正难的从来不是单个算法而是把算法放到一颗单片机上稳定跑起来还要应对真实环境中各种不规则的东西——墙上的金属画框、桌上的保温杯、雨天窗玻璃上的水膜这些都会变成雷达眼前“看不见的妖怪”。如果你也打算做类似的产品我的建议是先把需求里“到底要检测什么目标、目标多大会动多大范围、允许误报几次”这三件事想得非常具体再去选硬件。因为雷达的参数设计几乎全是由这三个问题推导出来的。设备部署位置也要提前定是吸顶还是壁挂、高度多少会直接影响天线俯仰角和检测盲区这些在软件里虽然能通过调门限补救一部分但补救程度有限。最后分享一个小技巧在调试算法的时候不要只盯着实时输出的目标列表建议把距离-多普勒谱的二维可视化图也截下来存着。很多时候实时跑出来的结果看起来是“反正不准”但到底为什么不准只有回头看谱图才能发现——是峰值展宽、是CFAR门限抬升、还是静态杂波残留一眼就能分辨。PLFM_RADAR的上位机工具里就一直保留着谱图回放功能这个习惯省掉了我大量的重复实验时间。