4、硬件同步方案设计:GPIO直连方案、FPGA/CPLD时序发生器、微控制器(STM32)PWM输出方案、外部信号发生器方案

做结构光系统,最头疼的问题是什么?

我个人觉得,不是算法调不好,也不是光机选不对。而是——相机和投影仪「各干各的」。你想想看,投影仪在那刷120帧,相机也在那拼命拍,但两者之间差了那么几毫秒的相位偏移。结果呢?重建出来的点云全是重影和条纹。

嗯,这就是同步没做好。

这一章,我就把四种最常用的硬件同步方案掰开揉碎了讲。每种方案我都踩过坑,有些坑现在想起来还肉疼。

核心观点:硬件同步的本质,就是给相机和投影仪一个共同的「心跳」。谁发这个心跳,怎么发,决定了你的系统能跑多快、多稳。

4.1 GPIO直连方案——最简单,也最容易翻车

GPIO直连,说白了就是拿一根杜邦线,把投影仪的触发输出脚和相机的触发输入脚连起来。投影仪每刷一帧,输出一个高电平脉冲,相机收到这个脉冲就拍一张。

听起来是不是很简单?我刚开始做结构光的时候,第一个原型就是这么干的。结果呢?拍出来的图像一会儿亮一会儿暗,相位图全是噪点。

为什么会这样?

问题出在电平匹配上。很多投影仪的触发输出是3.3V,但工业相机有的要5V,有的要12V。直接连,轻则触发不稳定,重则烧IO口。

避坑指南:我曾经在一个项目里直接用3.3V的GPIO去触发一个5V的相机,结果相机偶尔触发、偶尔不触发。查了两天,最后发现是电平阈值的问题。加个电平转换芯片(比如TXB0104)就解决了。

适用场景:

  • 帧率不高(30fps以下)
  • 对时序精度要求不苛刻(允许±1ms误差)
  • 原型验证阶段

接线方式:

投影仪 Trigger Out → 电平转换 → 相机 Trigger In
投影仪 GND → 相机 GND(共地必须做)

小技巧:共地这件事很多人会忘。不共地的话,两个设备的地电位不一样,触发信号上会叠加共模噪声。我习惯在连接器旁边留一个GND焊盘,专门用来接共地线。

4.2 FPGA/CPLD时序发生器方案——精度之王

如果你需要微秒级的同步精度,那FPGA或CPLD就是你的不二之选。

我记得有一次做高速结构光,投影仪要跑240fps,相机要跟着拍。GPIO直连根本扛不住,抖动大到没法看。后来换了个小CPLD,自己写时序发生器,问题一下就解决了。

为什么FPGA/CPLD这么强?

说白了,它们是硬件逻辑,没有操作系统的中断延迟。你写一个计数器,从0数到N,每到某个值就翻转一次IO。这个精度只取决于晶振,能做到纳秒级。

典型架构:

// Verilog示例:产生40kHz的触发信号
reg [15:0] counter;
reg trigger_out;

always @(posedge clk_40MHz) begin
    if (counter == 16'd999) begin
        counter <= 16'd0;
        trigger_out <= ~trigger_out;
    end else begin
        counter <= counter + 1;
    end
end

优点:

  • 精度高:抖动通常小于10ns
  • 灵活:可以同时输出多路不同频率、不同相位的信号
  • 独立:不依赖主控芯片,上电即运行

缺点:

  • 开发门槛高:需要懂硬件描述语言
  • 成本:小批量的话,一颗CPLD大概十几块钱
  • 调试麻烦:改一次逻辑要重新烧录

我的经验:如果你只是做产品原型,不建议一上来就上FPGA。先用微控制器方案跑通,等确定时序参数了,再移植到CPLD上做固化。这样开发效率最高。

4.3 微控制器(STM32)PWM输出方案——性价比之选

这是目前市面上最流行的方案。STM32的定时器模块非常强大,可以输出多路独立的PWM波,频率、占空比、相位都能调。

我做过一个手持式结构光扫描仪,就是用STM32F407做主控。一个定时器输出两路PWM:一路给投影仪做帧同步,一路给相机做曝光触发。两路之间可以调相位偏移,用来补偿投影仪的响应延迟。

关键配置:

// 使用STM32 HAL库配置PWM输出
TIM_HandleTypeDef htim2;
TIM_OC_InitTypeDef sConfigOC;

htim2.Instance = TIM2;
htim2.Init.Prescaler = 84 - 1;      // 84MHz / 84 = 1MHz
htim2.Init.Period = 1000 - 1;       // 1MHz / 1000 = 1kHz
HAL_TIM_PWM_Init(&htim2);

sConfigOC.OCMode = TIM_OCMODE_PWM1;
sConfigOC.Pulse = 500;              // 50%占空比
sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;
HAL_TIM_PWM_ConfigChannel(&htim2, &sConfigOC, TIM_CHANNEL_1);
HAL_TIM_PWM_Start(&htim2, TIM_CHANNEL_1);

优点:

  • 成本低:一颗STM32F103只要几块钱
  • 开发快:用CubeMX配置,几分钟就能出波形
  • 灵活:可以在运行时动态调整频率和相位

缺点:

  • 精度受限于主频:一般能做到微秒级,但纳秒级就别想了
  • 受中断影响:如果主控在忙别的事,PWM输出可能会有抖动

注意:我曾经在一个项目里用STM32的PWM同时驱动投影仪和相机,结果发现相机的曝光时间长了之后,PWM的占空比会漂。后来查了半天,发现是定时器的重载值更新时机没处理好。解决办法是用「影子寄存器」模式,让更新发生在定时器溢出时刻,而不是立即更新。

4.4 外部信号发生器方案——实验室专用

这个方案听起来有点「笨」,但在某些场景下特别好用。

我记得有一次帮客户调试一个多相机系统,四台相机要严格同步曝光。用微控制器方案,四路PWM的相位一致性怎么调都调不好。后来直接上了个四通道的信号发生器,每路独立设延迟,十分钟就搞定了。

怎么用?

  1. 信号发生器输出方波,频率设为投影仪的帧率
  2. 用BNC转接头分路,一路给投影仪,一路给相机
  3. 如果需要多路不同相位,用多通道信号发生器

优点:

  • 零开发:买来就能用
  • 精度高:专业信号发生器的抖动通常在1ns以内
  • 调试方便:旋钮一拧,频率、幅度、偏置随便调

缺点:

  • 成本高:一台四通道信号发生器要几千块
  • 体积大:不适合做产品,只适合实验室验证
  • 无法集成:不能嵌入到最终产品里

我的建议:如果你在做算法验证阶段,别犹豫,直接上信号发生器。省下来的开发时间,够你调好几个月的算法了。等算法稳定了,再考虑用微控制器或CPLD方案做产品化。

4.5 四种方案对比总结

方案 精度 成本 开发难度 适用阶段
GPIO直连 ±1ms 几乎为零 原型验证
FPGA/CPLD ±10ns 中(10-50元) 量产产品
STM32 PWM ±1μs 低(5-20元) 产品原型/小批量
信号发生器 ±1ns 高(数千元) 实验室验证

4.6 核心逻辑图

下面这张图展示了四种方案在结构光系统中的位置关系。你可以看到,无论哪种方案,最终都是要给投影仪和相机提供同步信号。

结构光系统硬件同步方案架构 GPIO直连 精度±1ms FPGA/CPLD 精度±10ns STM32 PWM 精度±1μs 信号发生器 精度±1ns 同步信号 投影仪 DLP/LCoS 光机 相机 工业相机/全局快门 四种方案均可产生同步信号,区别在于精度、成本和开发难度 选择时需综合考虑帧率要求、预算和团队技术栈

4.7 怎么选?我的建议

说实话,没有完美的方案。每个项目都有自己的约束条件。

如果你问我个人习惯,我会这样选:

  • 实验室验证阶段:信号发生器 + GPIO直连。快速验证算法,别在硬件上浪费时间。
  • 产品原型阶段:STM32 PWM。性价比最高,出了问题也好改。
  • 量产产品阶段:FPGA/CPLD。稳定、可靠、精度高,客户不会因为同步问题投诉你。

最后说一句:不管选哪种方案,一定要在原理图阶段就把同步信号的测试点留出来。我见过太多工程师,板子打回来才发现同步信号没地方测,只能用示波器探头在芯片引脚上戳,那叫一个痛苦。


公众号:蓝海资料掘金营,微信deep3321