2、硬件同步基础:硬件触发信号(GPIO、PWM)、同步信号时序要求、主从模式设计

各位同学,咱们接着聊。上一章我讲了多摄像头同步的「为什么」,这一章咱们来啃硬骨头——硬件同步到底怎么搞。

说实话,我刚入行那会儿,觉得同步不就是给个信号嘛,有啥难的?结果第一次调双摄,画面就是错位的,一个快一个慢,气得我差点摔开发板。后来才明白,硬件同步这事儿,细节决定成败。

2.1 硬件触发信号:GPIO 与 PWM

多摄像头同步,最基础的手段就是硬件触发信号。说白了,就是主芯片给每个摄像头发一个「开始干活」的脉冲。

常用的有两种:GPIO 电平触发PWM 脉冲触发

2.1.1 GPIO 触发

GPIO 触发最简单。主控拉高一个 GPIO 引脚,摄像头检测到上升沿,就开始曝光。

我个人习惯用 GPIO 做帧同步。为什么?因为它延迟低,而且每个 SoC 都有大量 GPIO,不占其他资源。

但要注意一个问题:GPIO 的抖动。我在项目中遇到过,GPIO 从软件拉高到硬件引脚实际输出,中间有几十纳秒的偏差。单摄无所谓,多摄同步时,这几十纳秒就能让画面错位。

避坑指南: 我曾经在某个项目里,直接用 CPU 的 GPIO 做同步触发,结果发现不同摄像头收到的触发时刻差了 200ns。后来改用硬件定时器直连 GPIO,才把抖动压到 5ns 以内。

2.1.2 PWM 触发

PWM 触发更灵活。你可以通过调节占空比和频率,控制摄像头的曝光时间和帧率。

举个例子,你要做 30fps 的同步,PWM 频率就设 30Hz。每个周期的高电平时间,就是摄像头的曝光窗口。

我建议用 PWM 的场景是:需要动态调整帧率。比如在暗光下降低帧率提亮度,亮光下提高帧率抓细节。改一下 PWM 参数就行,不用动硬件连线。

触发方式 延迟 抖动 灵活性 推荐场景
GPIO 电平 中等 固定帧率同步
PWM 脉冲 中等 动态帧率、多模式切换

2.2 同步信号时序要求

有了触发信号,不等于就能同步。时序要求才是真正的坑。

你想想看,两个摄像头同时收到触发信号,但它们内部处理需要时间。有的传感器从收到信号到开始曝光,要等几十行扫描时间。这个时间差,就叫响应延迟

我一般会看三个关键时序参数:

  • 触发到曝光开始延迟:传感器收到信号后,多久开始积分
  • 曝光时间窗口:传感器实际曝光的时间长度
  • 读出时间:曝光结束后,数据从像素读出到输出需要多久

这三个参数,不同型号的传感器差异很大。我记得有一次,把 Sony 和 Omnivision 的传感器混用,Sony 的延迟是 2 行时间,Omnivision 是 5 行。结果画面始终差 3 行,怎么调都调不好。

核心原则: 同步信号的时序,必须满足所有传感器中最严格的那个。说白了,就是「木桶效应」——最慢的传感器决定了整个系统的同步精度。

具体到数值,我给大家一个参考:

  • 消费级多摄:同步误差 < 1 行时间(约 30μs @ 1080p)
  • 车载环视:同步误差 < 100μs
  • 机器视觉:同步误差 < 10μs

嗯,这里要注意:温度会影响时序。传感器温度升高,内部 PLL 会漂移,导致延迟变化。我在做车载项目时,夏天暴晒后,两个摄像头的同步误差从 50μs 漂到了 200μs。后来加了温度补偿,才稳住。

2.3 主从模式设计

讲完信号和时序,咱们聊聊架构。多摄像头同步,最经典的设计就是主从模式

主从模式,说白了就是:一个摄像头当「老大」,其他摄像头当「小弟」。老大发出同步信号,小弟们跟着老大的节奏走。

为什么用主从?因为简单可靠。你想想看,如果每个摄像头都独立运行,那得靠软件去对齐时间戳,精度根本不够。硬件主从,直接物理连线,延迟是纳秒级的。

2.3.1 主从模式的两种实现

我常用的主从模式有两种:

  1. 硬件主从:主摄像头的 VSYNC(帧同步)信号直接连到从摄像头的 TRIGGER 引脚。主摄每完成一帧,就触发从摄开始下一帧。
  2. 外部主控模式:SoC 或 FPGA 作为主控,统一给所有摄像头发触发信号。所有摄像头都是「从」,主控是唯一的「主」。

我个人更推荐第二种。为什么?因为硬件主从有个问题:如果主摄像头坏了,所有从摄像头都瘫痪。外部主控模式,主控坏了可以热切换。

实战技巧: 我在做三摄方案时,用了外部主控模式。主控是一个小 FPGA,专门负责发同步信号。FPGA 的延迟可以精确到 1 个时钟周期,比 SoC 的 GPIO 稳定得多。

2.3.2 主从模式的配置要点

配置主从模式时,有几个坑必须注意:

  • 上电顺序:先给主摄像头供电,再给从摄像头供电。否则从摄像头可能检测不到主信号,进入错误状态。
  • 信号电平匹配:主摄像头输出 1.8V,从摄像头输入 3.3V,中间要加电平转换。我曾经直接连,烧了一个从摄像头的 IO 口。
  • 信号完整性:同步信号线要短,最好控制在 5cm 以内。长了会有反射,导致误触发。

嗯,说到信号完整性,我再啰嗦一句。同步信号线最好走 PCB 内层,两边包地。我见过有人用杜邦线飞线调试,结果 30fps 的同步信号,示波器一看全是毛刺。

2.3.3 主从模式的代码示例

最后,给一段我常用的主从配置代码。这是基于 V4L2 和 GPIO 控制的简化版:

// 主摄像头配置
struct v4l2_ext_controls ctrls;
struct v4l2_ext_control ctrl;

ctrl.id = V4L2_CID_TRIGGER_MODE;
ctrl.value = V4L2_TRIGGER_MODE_MASTER;  // 设为主模式
ctrls.controls = &ctrl;
ioctl(fd_master, VIDIOC_S_EXT_CTRLS, &ctrls);

// 从摄像头配置
ctrl.id = V4L2_CID_TRIGGER_MODE;
ctrl.value = V4L2_TRIGGER_MODE_SLAVE;   // 设为从模式
ctrls.controls = &ctrl;
ioctl(fd_slave, VIDIOC_S_EXT_CTRLS, &ctrls);

// 设置同步信号 GPIO
gpio_set_value(SYNC_GPIO, 1);  // 拉高触发
usleep(10);                     // 保持 10μs
gpio_set_value(SYNC_GPIO, 0);  // 拉低结束

这段代码看着简单,但实际调试时,我花了整整两天才跑通。问题出在 GPIO 的驱动能力上——默认的 GPIO 驱动电流不够,信号上升沿太缓,从摄像头检测不到。后来把 GPIO 的 drive strength 调到 8mA,才解决问题。

好了,这一章的内容就这些。硬件同步是基础,基础不牢,地动山摇。下一章咱们聊软件同步,那又是另一番天地了。