4、PPS秒脉冲同步:GPS/北斗模块输出PPS信号,校准相机时钟,实现长时间漂移抑制

说到多相机长时间同步,很多朋友第一反应就是「用网线对时」或者「软件打时间戳」。嗯,这些方法在短时间、低精度场景下确实够用。但如果你做过连续录制几小时甚至几天的项目,就会发现问题——时钟漂移。

我有个项目,客户要求四台相机连续录制8小时,误差不能超过1帧(约33ms)。一开始用的NTP对时,结果跑了3小时后,最大偏差到了200多毫秒。后来换成PPS秒脉冲方案,问题才彻底解决。

说白了,PPS(Pulse Per Second)就是GPS或北斗模块每秒输出一个精准的脉冲信号。这个脉冲的上升沿,精度能达到纳秒级。用它来校准相机的本地时钟,就能把长时间漂移抑制住。

4.1 PPS同步的基本原理

PPS同步的核心思路很简单:

  • 外部参考源:GPS/北斗模块每秒输出一个高精度脉冲
  • 本地时钟校准:相机或采集卡检测到PPS上升沿后,修正自己的系统时钟
  • 时间戳对齐:所有相机都以这个校准后的时钟为基准打时间戳

你想想看,如果每秒钟都校准一次,时钟漂移根本积累不起来。这就是PPS方案最大的优势。

关键指标:PPS脉冲的精度通常在±50ns以内(取决于GPS模块质量),远优于NTP的毫秒级精度。

4.2 硬件连接方式

实际项目中,PPS信号的接入方式主要有三种。我根据经验整理了一下:

接入方式 适用场景 精度 注意事项
GPIO直接输入 嵌入式相机、FPGA采集卡 ±100ns 需要电平匹配(通常3.3V或5V)
串口+中断 工业相机、工控机 ±1μs 依赖操作系统中断响应速度
专用同步接口 高端工业相机(如Basler、FLIR) ±50ns 需相机支持PPS输入功能

我个人习惯用GPIO直接输入的方式。为什么?因为延迟最小,不受操作系统调度影响。我曾经在FPGA上做过测试,GPIO中断响应时间可以控制在100ns以内,而串口中断往往有1-2μs的抖动。

4.3 软件实现要点

硬件接好了,软件怎么处理?这里我给出一个典型的处理流程:

// 伪代码:PPS中断处理函数
void pps_interrupt_handler() {
    // 1. 记录当前系统时间(硬件计数器值)
    uint64_t current_tick = get_hardware_tick();
    
    // 2. 计算与上一个PPS脉冲的时间差
    uint64_t delta = current_tick - last_pps_tick;
    
    // 3. 如果delta偏离1秒(例如超过±1ms),进行时钟修正
    if (abs(delta - TICKS_PER_SECOND) > TICKS_PER_MS) {
        adjust_system_clock(delta);
    }
    
    // 4. 更新PPS时间戳
    last_pps_tick = current_tick;
    pps_timestamp++;
}

小技巧:不要每次PPS都大幅调整时钟。我建议采用「渐进式校准」——每次只修正偏差的10%-20%,避免时钟跳变导致时间戳不连续。

4.4 避坑指南

做PPS同步,有几个坑我踩过,分享给大家:

  • 天线位置:GPS天线一定要放在室外开阔处。我曾经把天线放在窗边,结果信号时断时续,PPS脉冲丢失了半小时,所有相机都失同步了。
  • 电平转换:GPS模块输出通常是3.3V,但有些相机GPIO只接受5V。不加电平转换直接连,轻则信号不稳定,重则烧坏接口。
  • 脉冲宽度:不同模块的PPS脉冲宽度不一样,从100μs到100ms都有。要确认相机能正确识别这个脉宽。
  • 首次锁定时间:GPS模块冷启动需要几十秒到几分钟才能输出稳定PPS。系统上电后要等待锁定再开始采集。

警告:PPS信号线必须使用屏蔽双绞线,且远离电源线和大功率设备。我遇到过因为线缆干扰导致PPS抖动达到几十微秒的情况,排查了整整两天才找到原因。

4.5 实测效果

最后说说实际效果。我在一个8相机系统中测试过:

  • 使用PPS同步前:8小时漂移约300ms
  • 使用PPS同步后:8小时漂移小于1ms

嗯,这个提升是质的飞跃。而且PPS方案成本很低——一个GPS模块几十块钱,比买高精度时钟发生器划算多了。

当然,PPS也有局限性。比如室内没有GPS信号的地方就用不了。这时候可以考虑用IRIG-B或者IEEE 1588(PTP)协议。不过那是后面章节的内容了。

总结一下:如果你需要长时间、高精度的多相机同步,PPS秒脉冲方案是性价比最高的选择。硬件简单、软件可控、效果可靠。我个人在多个项目中都用这个方案,从未出过问题。