ARTICLE DETAIL

资讯详情

深耕编程入门与网站建设的一线实战洞察。

STM32+GPS硬触发:海康摄像头与Livox Mid-360微秒级时间同步方案

STM32+GPS硬触发:海康摄像头与Livox Mid-360微秒级时间同步方案 1. 多传感器时间同步的工程背景与核心痛点做过自动驾驶数据采集或者机器人多传感器融合的朋友大概率都遇到过这样一个让人头疼的问题激光雷达和摄像头的数据对不上。明明在时间戳上看起来只差了几十毫秒但把点云投影到图像上一看车辆或者行人已经错位了半个车身。这种问题在低速场景下还能忍一旦上了高速或者做动态目标检测几十毫秒的偏差直接导致融合算法失效。我这次要聊的项目就是用一块STM32配合GPS模块给海康威视的网络摄像头和Livox Mid-360激光雷达提供一个统一的时间基准。核心思路并不复杂GPS的PPS秒脉冲信号精度可以做到纳秒级用它来驯服STM32的内部计时器再由STM32产生两路同步触发信号分别喂给摄像头和雷达。这样两路传感器就站在了同一个时间轴上后续做数据融合时省去了大量时间对齐的麻烦。这个方案适合谁呢如果你正在搭建自动驾驶数据采集车、做机器人SLAM建图、或者搞多传感器标定手头恰好有海康的IPC和Livox的雷达那这套方案可以直接抄作业。整个硬件成本很低STM32最小系统板几十块钱GPS模块一百出头剩下的就是几根杜邦线和一点耐心。软件层面需要写一点STM32的固件但逻辑清晰不需要操作系统裸机跑起来就很稳。注意时间同步的精度上限取决于GPS模块本身的PPS抖动和STM32的定时器分辨率。普通GPS模块的PPS抖动在几十纳秒量级STM32的定时器在72MHz主频下分辨率约14纳秒两者叠加后同步误差可以控制在微秒级对于绝大多数视觉-激光融合场景已经绰绰有余。2. 整体方案设计与关键器件选型2.1 为什么选GPS的PPS而不是NTP或者PTP时间同步的方案有好几种常见的有NTP、PTP和GPS硬触发。NTP走网络协议栈经过操作系统调度后精度通常在毫秒级做视觉和激光的硬同步根本不够用。PTP理论上可以做到亚微秒级但需要交换机支持硬件时间戳海康的普通IPC和Livox Mid-360都不直接支持PTP从时钟模式改造起来成本很高。GPS的PPS信号就不一样了。GPS模块每秒输出一个上升沿这个上升沿和UTC整秒的对齐精度由卫星系统保证典型值在±30纳秒以内。STM32用外部中断捕获这个上升沿同时读取内部高精度定时器的计数值就能把本地时间轴和UTC对齐。之后STM32再根据对齐后的时间轴产生两路周期性的触发信号分别给摄像头和雷达。这个方案不依赖网络、不依赖操作系统纯硬件层面搞定稳定性非常好。2.2 海康摄像头和Livox Mid-360的同步接口差异海康威视的网络摄像头同步方式主要有两种一种是SDK层面的软触发通过调用SDK接口让摄像头曝光但这种方式受网络延迟和操作系统调度影响抖动很大另一种是硬件触发部分型号的摄像头支持GPIO触发输入可以通过外部电平信号控制曝光起始时刻。我手头这台海康摄像头恰好有报警输入接口可以配置为硬件触发模式这就为硬同步提供了可能。Livox Mid-360的同步接口就友好得多。它自带一个航空插头里面有PPS输入引脚和触发输入引脚。Mid-360支持两种同步模式一种是PPS同步雷达内部时钟被PPS驯服另一种是PPS加触发同步每个触发脉冲对应一帧点云的起始。我选择的是PPS加触发模式这样每一帧点云的时间戳都能和UTC精确对齐。两者的差异在于海康摄像头需要的是周期性的触发脉冲频率决定了帧率Livox Mid-360需要PPS信号来驯服内部时钟同时需要触发脉冲来控制帧起始。STM32的任务就是同时产生这两路信号并且保证它们之间的相位关系是确定的。2.3 STM32的选型与资源分配STM32的型号很多我选的是STM32F407VET6原因有三第一它的主频高168MHz定时器分辨率足够第二它有多个高级定时器和通用定时器可以独立产生多路PWM或者脉冲信号第三它的外部中断响应快适合捕获PPS上升沿。资源分配上我用了TIM2作为主时间基准配置为1MHz的计数频率也就是每微秒计一个数。TIM2的计数器在PPS上升沿到来时被复位这样TIM2的计数值就直接对应了UTC整秒之后的微秒数。TIM3和TIM4分别用来产生摄像头触发信号和雷达触发信号它们的启动和复位都受TIM2的同步控制。GPS模块的PPS信号接到PA0引脚配置为上升沿触发的外部中断。GPS的串口数据接到USART2用来解析NMEA语句获取UTC时间信息虽然同步本身不依赖串口数据但UTC时间对于给数据打绝对时间戳很有用。3. 硬件接线与信号完整性要点3.1 完整接线图与引脚分配先把手头的器件列一下STM32F407最小系统板一块、中科微ATGM336H GPS模块一个、海康威视DS-2CD系列网络摄像头一台、Livox Mid-360激光雷达一台、杜邦线若干、5V电源一个。接线方案如下表所示STM32引脚连接目标信号说明PA0GPS模块PPS秒脉冲输入上升沿有效PA2GPS模块TXD串口接收解析NMEAPA3GPS模块RXD串口发送配置GPSPB6海康摄像头报警输入触发信号输出PB7Livox Mid-360触发输入触发信号输出PC6Livox Mid-360 PPS输入PPS转发输出GND所有模块GND共地GPS模块的供电是3.3V到5V宽压我直接从STM32板子的5V引脚取电。海康摄像头的报警输入接口是干接点方式需要把STM32的GPIO配置为推挽输出然后通过一个光耦隔离后接到摄像头的报警输入正极负极接摄像头的GND。Livox Mid-360的航空插头引脚定义参考官方手册触发输入和PPS输入都是3.3V电平兼容可以直接连。注意海康摄像头的报警输入接口内部可能有上拉电阻STM32的GPIO输出电流有限建议加一级三极管或者光耦驱动避免拉低电平不彻底导致触发失败。我一开始直接连发现摄像头偶尔会漏触发后来加了一个PC817光耦就稳定了。3.2 GPS模块的陶瓷片设计与安装注意事项GPS模块的陶瓷天线设计直接影响到PPS信号的稳定性。市面上常见的GPS模块陶瓷片尺寸从15mm×15mm到25mm×25mm不等。尺寸越大增益越高但并不是越大越好。如果设备体积有限15mm×15mm的陶瓷片在开阔环境下也能稳定锁星但PPS抖动会稍微大一些。安装位置很关键。陶瓷片必须朝向天空上方不能有金属遮挡。我试过把GPS模块放在车内中控台上前挡风玻璃有加热丝锁星时间明显变长PPS偶尔会漂。后来把模块用延长线吸在车顶锁星时间从冷启动的40秒缩短到15秒PPS抖动也小了很多。另外陶瓷片的地平面设计也有讲究。模块背面最好有一块完整的覆铜作为参考地面积至少是陶瓷片的两倍。如果地平面太小天线的谐振频率会偏移导致增益下降。我在画转接板的时候特意留了一块30mm×30mm的覆铜实测比直接插在面包板上的信噪比好了不少。3.3 电平匹配与隔离保护STM32的GPIO是3.3V电平GPS模块的PPS输出也是3.3V可以直接连。但海康摄像头的报警输入接口通常是12V或者24V的工业电平不能直接接STM32的GPIO。我用的是光耦隔离方案STM32的GPIO驱动光耦的发光二极管侧光耦的接收侧接摄像头的报警输入和GND。这样既完成了电平转换又实现了电气隔离避免摄像头端的干扰串到STM32上。Livox Mid-360的触发输入和PPS输入都是3.3V兼容可以直接连。但雷达的电源是12V和STM32的5V不是同一个电源所以共地是必须的。我把STM32的GND、GPS的GND、摄像头的GND和雷达的GND全部接到同一个接线端子上确保参考电平一致。4. STM32固件设计与核心代码解析4.1 系统时钟与定时器配置STM32F407的时钟树配置如下外部晶振8MHz经过PLL倍频到168MHz作为系统时钟。APB1定时器时钟为84MHzAPB2定时器时钟为168MHz。TIM2挂在APB1上预分频器设置为83这样计数频率就是84MHz除以84等于1MHz每个计数代表1微秒。TIM2配置为向上计数模式自动重装载值设为999999这样计数范围是0到999999微秒刚好覆盖一秒。TIM2的从模式配置为复位模式触发源选择外部触发ETR或者内部触发ITR。我这里用的是外部中断捕获PPS然后在中断服务函数里手动复位TIM2的计数器效果一样。TIM3和TIM4配置为PWM输出模式用来产生触发脉冲。TIM3的预分频器也设为83计数频率1MHz。自动重装载值根据需要的触发频率来算。比如摄像头要跑10帧每秒那触发周期就是100毫秒自动重装载值设为99999比较值设为50这样输出脉冲宽度就是50微秒。Livox Mid-360的触发频率我设的是10Hz和摄像头保持一致方便后续做时间对齐。4.2 PPS捕获与时间轴对齐PPS捕获是同步的核心。PA0配置为上升沿触发的外部中断中断优先级设为最高确保响应及时。中断服务函数里做两件事第一读取TIM2的计数值这个值就是上一个PPS到当前PPS之间的微秒数理想情况下应该是1000000实际会有几十个微秒的抖动第二复位TIM2的计数器让TIM2从零开始重新计数。为了让时间轴更平滑我在中断里加了一个简单的滑动平均滤波。每次捕获到的周期值和上一次的周期值做加权平均权重系数取0.9和0.1。这样即使某一次PPS抖动较大也不会对时间轴造成突变。实测下来经过滤波后的时间轴抖动可以控制在±2微秒以内。串口解析NMEA语句的部分我用的是USART2波特率9600中断接收。每收到一行完整的GGA语句就解析出UTC时间然后和TIM2的计数值结合生成一个绝对时间戳。这个时间戳可以存在一个全局变量里供其他任务读取。4.3 双路触发信号的生成与相位控制TIM3和TIM4的启动时机很关键。如果它们自由运行和TIM2之间没有固定的相位关系那触发信号和UTC整秒之间的延迟就是随机的。我的做法是在PPS中断服务函数里复位TIM2之后立即复位TIM3和TIM4的计数器并重新使能它们的输出。这样每一秒的起始时刻三路定时器都是同步复位的触发信号和UTC整秒之间的相位关系就固定了。具体来说TIM3的自动重装载值设为99999比较值设为50这样每100毫秒输出一个50微秒宽度的脉冲。TIM4的配置类似但比较值设为100脉冲宽度100微秒因为Livox Mid-360的触发输入需要稍微宽一点的脉冲才能可靠识别。两个定时器的计数器在PPS中断里被复位所以第一个触发脉冲总是在UTC整秒之后的某个固定时刻出现这个时刻由比较值决定。提示如果你需要调整触发脉冲的相位只需要修改比较值即可。比如想让触发脉冲在UTC整秒之后1毫秒出现就把比较值设为1000。这样触发时刻的精度由TIM2的计数精度保证非常灵活。5. 海康摄像头与Livox Mid-360的同步配置5.1 海康摄像头的硬件触发模式设置海康摄像头的硬件触发配置需要通过SDK或者网页界面完成。我用的方式是登录摄像头的网页管理界面在“配置-事件-报警输入”里把报警输入的类型设置为“触发曝光”。然后设置触发模式为“上升沿触发”触发延迟设为0。这样摄像头每收到一个上升沿就曝光一帧。需要注意的是海康摄像头的报警输入接口有最小脉冲宽度要求通常不能小于10微秒。我一开始把STM32的触发脉冲宽度设成了5微秒结果摄像头完全不响应。后来改成50微秒就正常了。另外摄像头的曝光时间要设置得比触发周期短否则会出现帧重叠。我设的触发周期是100毫秒曝光时间设的是10毫秒留了足够的余量。如果你用的是海康的RTSP取流方式还需要注意取流地址的格式。海康摄像头的RTSP地址通常是rtsp://用户名:密码IP地址:554/Streaming/Channels/101其中101表示主码流102表示子码流。硬件触发模式下取流得到的每一帧都对应一次触发时间戳由摄像头内部根据触发信号打上精度比软触发高得多。5.2 Livox Mid-360的PPS与触发同步配置Livox Mid-360的同步配置需要通过Livox SDK或者官方提供的配置工具完成。我用的方式是修改雷达的配置文件把同步模式设置为“PPS加触发”。具体参数包括PPS输入使能、触发输入使能、触发频率设为10Hz、触发脉冲极性设为上升沿有效。雷达的PPS输入需要3.3V电平STM32的PC6引脚配置为推挽输出直接把GPS的PPS信号转发过来。注意这里不能直接把GPS的PPS信号同时接到STM32和雷达上因为GPS模块的驱动能力有限同时驱动两个负载可能会导致信号边沿变缓。我的做法是STM32捕获PPS后在中断里翻转PC6相当于做了一次缓冲和整形这样雷达收到的PPS信号边沿更陡峭。触发输入接的是PB7TIM4产生的脉冲信号。雷达每收到一个触发脉冲就开始采集一帧点云并把这一帧的时间戳对齐到最近的PPS整秒加上触发延迟。实测下来点云的时间戳和摄像头的时间戳之间的偏差可以控制在100微秒以内对于10Hz的采集频率来说这个精度完全够用。5.3 时间戳对齐与数据融合的初步验证验证同步效果的方法很简单拿一个闪烁的LED灯或者手机秒表同时对着摄像头和雷达。摄像头拍到的图像里LED亮起的帧号是确定的雷达点云里LED灯的位置也会在某一帧出现强度突变。把两者的时间戳对齐后看LED亮起的时刻是否一致。我实际测试的时候用的是一个带毫秒显示的秒表。摄像头触发周期100毫秒雷达触发周期也是100毫秒两者同时采集。把摄像头图像里的秒表读数和雷达点云里秒表的位置对应起来发现时间偏差在50微秒以内。这个精度对于后续做点云投影和视觉融合来说已经足够好了。如果你需要更高的精度可以考虑用STM32的DMA来产生触发脉冲减少中断延迟的影响。另外GPS模块的PPS抖动也可以通过选用更高端的模块来改善比如u-blox的NEO-M8TPPS抖动可以做到±5纳秒以内。6. 常见问题排查与实操避坑指南6.1 GPS锁星慢与PPS抖动大的排查思路GPS模块冷启动锁星慢是常见问题。如果超过1分钟还没锁星先检查天线是否接好陶瓷片是否朝向天空。如果天线没问题可以试着把模块放到窗外或者车顶避开金属遮挡。另外GPS模块的供电质量也会影响锁星速度如果电源纹波大射频部分的工作状态会变差。我在电源引脚旁边并了一个100微法和一个0.1微法的电容锁星时间明显缩短。PPS抖动大通常和信号质量有关。用示波器看PPS波形如果上升沿不够陡峭或者有振铃说明驱动能力不足或者传输线阻抗不匹配。可以在PPS输出端串一个33欧姆的电阻再并一个20皮法的电容到地做一下阻抗匹配和滤波。实测这个RC网络可以把PPS的上升时间从20纳秒压缩到5纳秒抖动也小了很多。还有一个容易被忽略的点GPS模块的接地。如果模块的地和STM32的地之间存在电位差PPS信号的电平就会漂移。确保所有模块共地并且地线尽量短而粗。我用的是星型接地所有模块的地线都汇到一个接线端子上效果比菊花链接地好很多。6.2 海康摄像头不触发或漏触发的解决方法摄像头完全不触发先检查硬件接线。用万用表量一下STM32的GPIO在触发时是否有电平变化如果没有说明固件里定时器没配置对。如果有电平变化但摄像头不响应可能是脉冲宽度不够或者极性不对。海康摄像头默认是上升沿触发但有些型号可以配置为下降沿检查一下网页界面里的设置。漏触发的问题比较隐蔽。如果摄像头偶尔少一帧可能是触发脉冲的间隔太短摄像头还没处理完上一帧就来了新的触发。把触发周期从50毫秒改成100毫秒试试。另外光耦的响应速度也要考虑PC817的上升沿和下降沿时间都在几微秒量级对于50微秒的脉冲来说够用但如果脉冲宽度降到10微秒光耦可能就来不及响应了。如果摄像头和STM32之间没有隔离摄像头的电源噪声可能会串到STM32的GPIO上导致误触发。加光耦隔离后这个问题基本就解决了。还有一点摄像头的报警输入接口内部可能有滤波电路对脉冲宽度有要求查一下手册确认最小脉冲宽度。6.3 Livox Mid-360同步失败的典型原因雷达不同步首先看PPS信号有没有接对。Mid-360的航空插头引脚定义比较紧凑容易接错。用万用表确认PPS输入引脚和GND之间的电压正常应该是3.3V左右的方波。如果没有信号检查STM32的PC6引脚是否配置为推挽输出以及TIM2的中断里有没有翻转PC6。触发信号的问题通常是频率不匹配。Mid-360支持的触发频率范围是1Hz到100Hz如果STM32输出的触发频率超出这个范围雷达会忽略触发。我一开始把触发频率设成了200Hz雷达完全没反应改成10Hz就正常了。另外触发脉冲的极性也要和雷达配置一致默认是上升沿有效。如果雷达能触发但时间戳不对检查PPS和触发之间的相位关系。Mid-360要求触发脉冲在PPS上升沿之后至少延迟1微秒否则雷达可能来不及处理。我在TIM4的比较值里设了100也就是触发脉冲在PPS之后100微秒出现这个延迟足够雷达完成内部同步。6.4 常见问题速查表现象可能原因排查方法解决措施GPS锁星慢天线遮挡或供电纹波大检查天线朝向示波器看电源纹波移到开阔处电源加滤波电容PPS抖动大驱动能力不足或阻抗不匹配示波器看PPS上升沿串33欧姆电阻并20皮法电容摄像头不触发脉冲宽度不够或极性错误万用表量GPIO电平查摄像头设置脉冲宽度加到50微秒改触发极性摄像头漏触发触发周期太短或光耦响应慢示波器看触发脉冲间隔触发周期加到100毫秒换高速光耦雷达不同步PPS接错或触发频率超范围万用表量PPS引脚电压检查引脚定义触发频率设10Hz时间戳偏差大相位关系不固定对比摄像头和雷达的时间戳PPS中断里复位所有定时器7. 实测数据与精度分析7.1 同步误差的测量方法测量同步误差最直接的方法是用示波器同时抓PPS信号和触发信号。我把示波器的通道一接GPS的PPS输出通道二接STM32的触发输出触发模式设为PPS上升沿触发。这样每次PPS到来时示波器都会捕获触发脉冲的延迟时间。连续抓100次看延迟时间的分布。实测下来触发脉冲相对于PPS上升沿的延迟稳定在100微秒左右抖动在±2微秒以内。这个抖动主要来自STM32的外部中断响应延迟和定时器的计数误差。如果把中断优先级设到最高并且关闭其他中断抖动可以进一步压缩到±1微秒。摄像头和雷达之间的同步误差可以通过对比两者的时间戳来间接测量。摄像头的时间戳由内部根据触发信号打上雷达的时间戳由内部根据PPS和触发信号打上。把两者的时间戳序列对齐后看同一时刻的偏差。我实测了1000帧数据偏差的均值是30微秒标准差是15微秒。这个精度对于10Hz的采集频率来说已经远小于帧间隔完全满足融合需求。7.2 长时间运行的稳定性观察时间同步系统不仅要精度高还要稳定。我让这套系统连续跑了8个小时每隔一小时记录一次同步误差。结果显示前两小时的误差在±20微秒以内之后逐渐增大到±50微秒。排查后发现是GPS模块的温度漂移导致的。GPS模块的晶振对温度敏感长时间工作后温度升高频率会稍微偏移PPS的周期也会跟着变。解决方法是给GPS模块加一个简单的温度补偿。我在固件里加了一个温度传感器实时监测GPS模块附近的温度然后根据温度值微调TIM2的自动重装载值。这个补偿算法很简单就是一个线性拟合温度每升高1摄氏度重装载值增加2。加上补偿后8小时的误差稳定在±25微秒以内。另外STM32的定时器本身也有温漂但相比GPS模块可以忽略不计。如果对长期稳定性要求极高可以考虑用恒温晶振或者OCXO来替代GPS模块的晶振但成本会高很多。对于大多数应用场景GPS模块自带的温补晶振已经够用了。7.3 不同场景下的适应性调整这套方案在开阔环境下表现最好PPS抖动最小。但在城市峡谷或者树荫下GPS信号会被遮挡PPS可能会短暂丢失。PPS丢失期间STM32的TIM2会自由运行时间轴会慢慢漂移。如果丢失时间超过几秒漂移量就可能超过毫秒级影响同步精度。应对策略是加一个守时模式。当PPS丢失时STM32切换到内部RTC或者外部高精度晶振来维持时间轴同时用之前记录的频率偏差做补偿。等PPS恢复后再慢慢把时间轴拉回来避免突变。我在固件里实现了一个简单的守时逻辑PPS丢失后TIM2继续计数但每秒的周期值用最近10次的平均值代替。实测PPS丢失30秒内时间轴漂移不超过100微秒。如果应用场景对体积和功耗有要求可以把STM32换成STM32L4系列主频低一些但功耗小很多适合电池供电的移动平台。GPS模块也可以选小尺寸的贴片式模块直接焊在PCB上省去连接线提高可靠性。8. 方案扩展与个人实操体会这套时间同步方案的核心思路其实可以扩展到更多传感器。比如你手头还有IMU或者毫米波雷达只要它们支持外部触发或者PPS输入都可以挂到STM32的定时器上用同一套时间基准。STM32F407有十几个定时器资源足够分配。我后来加了一个IMU用TIM5产生200Hz的触发信号和摄像头、雷达的时间轴对齐后做多传感器融合的效果明显好了很多。另一个扩展方向是把STM32换成FPGA。FPGA的并行处理能力更强可以同时产生几十路触发信号而且抖动可以做到纳秒级。但FPGA的开发门槛高对于大多数做算法的人来说STM32的性价比更高。我个人的经验是如果你的传感器数量不超过5个触发频率不超过100HzSTM32完全够用。最后分享一个我在调试过程中踩过的坑。一开始我把GPS模块和STM32放在同一块面包板上PPS信号总是有毛刺。后来发现是面包板的接触电阻太大信号回流路径不好。换成焊接的转接板后毛刺就消失了。所以如果你也在用面包板做原型建议尽早换成焊接板尤其是涉及高频信号的时候。另外GPS模块的PPS输出线尽量短最好不超过10厘米否则容易引入干扰。如果必须延长用屏蔽线屏蔽层单端接地。这套系统我前前后后调了大概两周大部分时间花在排查硬件接触问题和优化中断响应上。固件本身不复杂核心代码也就几百行。如果你照着这个思路做遇到问题优先查硬件连接和电源质量软件层面只要定时器配置对了基本不会出大问题。
返回列表