OpenRig 这名字,我最早是在一个开源硬件群里看到的。当时有人在晒自己做的电控滑轨,轨身直接用铝合金型材加 3D 打印件拼起来,手机浏览器打开就能控制滑块走位和云台旋转。项目没有官方量产,但所有结构件图纸、电路接线和固件都公开,任何人都能照着搓一套。说白了,OpenRig 就是一套开源电动拍摄支架系统,核心就三件事:滑轨、云台、无线控制。今天我把它从设计思路到踩坑记录完整捋一遍,想自己动手做一套的朋友可以直接抄作业。
如果你手里有一台微单、运动相机或者手机稳定器,又经常觉得拍摄推拉镜头、延时横移要靠手推滑轨容易抖动,那这个项目就特别合适。它不追求大厂产品的承重和做工,更强调“能自己修改”:轨道长度可以按你的桌面宽度切,云台旋转范围可以按镜头视角调,甚至能通过串口把传感器数据接进来,让滑轨跟快门联动。这不是一套纯玩具,也不是商用级设备,而是介于两者之间、最适合折腾的开源方案。
1. OpenRig 到底解决什么问题
1.1 名字拆解与定位
OpenRig 拆开看就是 Open + Rig。Rig 这个词在摄影圈里的含义非常广,可以是相机支架、机身笼、跟焦器,也可以是整个拍摄附件系统。加上 Open,强调的是“开放”:开放结构图纸、开放固件、开放通信协议。它不是某个厂商的成品型号,而是一套可以参考、复制、修改的设计。我做这套系统的初衷也很简单,想要一台能拍匀速横移和自动云台追踪的拍摄装置,但市面上的成品电控滑轨价格实在太离谱,干脆自己用常见的硬件组合一套。
这套系统的定位很明确:适合桌面级拍摄,负载不超过两公斤,拍摄距离在 0.3 到 1 米这个区间。它解决的是短视频拍摄里最常用的几个机位动作:镜头从左边滑到右边、云台从俯视慢慢转平视、产品展示时前后往返移动。这些动作用手推滑轨也能做,但速度不均匀,画面会一顿一顿的;用 OpenRig 之后,步进电机做匀速驱动,画面流畅度完全是另一个档次。
1.2 目标用户与适用场景
什么人适合做一套 OpenRig?我自己总结了一下,大概三类。第一类是独立视频创作者,经常拍产品测评、桌面好物、美食制作这类固定场景,需要稳定、可复现的镜头运动;第二类是创客和硬件爱好者,手里有电烙铁、3D 打印机,想玩步进电机控制和无线通信;第三类是学校或培训机构的电子、自动化课程,拿一套开源硬件给学生做综合实践,比枯燥的理论课有意思得多。
场景上也很好举例。手机直播间里,一台 OpenRig 带着手机从产品左边滑到右边,云台同时从特写拉到全景,整个展示过程不需要人手动干预;拍摄延时摄影时,滑块以极低速度匀速移动,每走一小段触发一次快门,能拍出云层流动配合地面横移的效果;拍定格动画时,每次步进 0.1 毫米然后拍摄,配合云台微调角度,动画的流畅度比手动摆 Pose 要稳定得多。这些都是实际能落地的用途,不是堆参数的空话。
1.3 为什么不做成品而是开源
有人会问,既然核心功能就是滑轨加云台,为什么不直接买成品?答案很简单:成品的扩展性太差了。电控滑轨的机械长度是固定的,换了更大的台面就得换整机,两台不同品牌之间也不能互相通信。OpenRig 的轨道长度由铝型材切多长决定,滑块皮带长度跟着改就行;云台用的步进电机型号开源,坏了可以直接买同样规格的换上去,不用等厂家售后。更关键的是固件和通信协议都开放,这就意味着你可以把开关量信号引出来控制相机快门,也可以把编码器的数据上报给上位机做运动记录。
开源的另一个好处是社区互相“抄作业”。我在实际做的时候,滑轨端板的最初版设计有问题,轴承座和同步带轮在一条线上对不准,后来参考另一位开发者改成张紧轮结构才解决。这种问题在说明书里永远不会写,但在开源社区里一翻 Issue 记录全都能找到。对我来说,开源的意义不是免费,而是踩坑经验可以共享。
2. 整体架构与方案选型
2.1 机械结构:滑轨加云台的一体化设计
OpenRig 的机械结构拆成两层来看。底层是一条一字滑轨,两根 2020 铝合金型材平行固定,中间留出皮带槽,滑块底部通过直线轴承卡在型材的槽里。同步带固定在滑轨两端,滑块则固定在皮带的上侧或下侧,电机一转,皮带带动滑块移动。这个结构非常像打印机或者数控雕刻机的 X 轴,只是尺寸和负载都小很多。上层是云台,我采用的是两轴设计:一个旋转轴负责水平摇摄,一个俯仰轴负责镜头上下角度。云台的底部通过 3D 打印件锁在滑块顶部,两个步进电机分别放在云台两侧对称位置,避免镜头重心偏移。
选这个结构不是因为复杂好看,而是模块化程度高。滑轨部分和云台部分是分开的,调试时可以先把滑轨跑通,再接云台。两轴云台单独拿出来还能改成小型机械臂的关节;反过来,如果只需要滑轨,云台那一层可以直接不装。这种分层设计让我在后来改造时省了很多事,比如我想在滑块上加一个激光测距传感器做自动跟焦,只需要在滑块顶板上重新开几个孔,不用动云台部分。
2.2 控制核心:选 Arduino/ESP32 而不是 PLC
控制部分我最后选的是 Arduino Nano + ESP32 的组合,而不是 PLC 或者 Raspberry Pi。为什么不选 PLC?因为 PLC 的编程生态太封闭,梯形图写运动控制虽然稳定,但改参数和加界面都比较麻烦,不适合个人项目。为什么不选树莓派?树莓派性能确实强,但需要跑系统,开机慢、还要处理掉电文件损坏的问题,放在一套以实时运动控制为主的小系统里有点杀鸡用牛刀。Arduino 的优点是实时性稳定、外设库成熟,步进电机的脉冲输出可以直接靠定时器实现;ESP32 则负责无线通信,把控制指令交给 Arduino,两者通过串口通信各干各的。
这个分工也是一种经验。最开始我试图用 ESP32 直接控制步进电机,但状态请求一多,脉冲间隔就会出现抖动。后来改为 Arduino 生成脉冲,ESP32 只解析指令,问题立刻消失。稳定的运动控制需要把“网络”和“步进”隔离,这是 OpenRig 架构里我认为最重要的一点。
2.3 无线控制链路:BLE、Wi-Fi 还是 433MHz
无线方案我在项目里测过三种:2.4G 无线模块、蓝牙 BLE 和 Wi-Fi。2.4G 模块(比如 NRF24L01)延迟最低,但需要配一个遥控手柄,而且天线对安装位置要求高;BLE 的好处是手机原生支持,功耗低,但连接和配对流程偶尔会掉链子;Wi-Fi 方案延迟稍大,但优势在于控制端不用装 App,直接用手机浏览器打开网页就行。
我最终选的是 ESP32 的 Wi-Fi 软 AP 模式,也就是 OpenRig 自己开一个热点,手机连上热点后访问 192.168.4.1 页面控制。这个选择有几个直接好处:跨平台零成本,iPhone 和 Android 都一样用;页面可以用 WebSocket 实时显示滑块位置和速度;热点的名称和密码可以在 Web 配置里改,以后还能把它接到家里路由器的局域网,用电脑坐远一点控制。代价是电池续航会受影响,但我本来就需要在户外和室内都通用,Wi-Fi 的通用性超过了那一点点功耗损失。
3. 关键部件与参数计算
3.1 滑轨长度与同步带传动计算
先聊滑轨的传动计算。OpenRig 用的是 GT2 同步带,齿距 2 毫米,配 20 齿的同步轮,所以同步轮转一圈带动皮带的直线距离是 40 毫米。电机的步距角是 1.8 度,也就是说电机要走 200 整步才能转一圈。如果驱动器设置 32 细分,那么电机每收到一个脉冲,实际转过的角度是 1.8 / 32 = 0.05625 度,滑块移动的距离就是 40 / (200 * 32) = 0.00625 毫米。
这个数值叫脉冲当量,是后面所有速度、位置参数的基础。举个例子,如果想让滑块以每秒 100 毫米的速度匀速移动,需要的脉冲频率就是 100 / 0.00625 = 16000 脉冲每秒。Arduino 的 AVR 芯片在 16MHz 主频下,配合 AccelStepper 库,跑 16kHz 的脉冲输出完全没有问题。但如果你一心追求速度把它提到每秒 500 毫米,脉冲频率就是 80kHz,普通 Arduino 的 digitalWrite 方式会力不从心,必须改用定时器中断或更高主频的芯片。
同步带的预紧也很关键。太松的话,滑块启动时皮带会在轮子上打滑,造成丢步;太紧的话,电机负载变大,整机噪音明显增加。我的判断标准是:装好皮带后,用两指在滑块两端中间位置按压皮带,能压下 2 到 3 毫米就说明松紧合适。普通的 3D 打印端板可以在电机座一侧留一个长条孔,用螺丝调节张紧轮位置。这些参数看着琐碎,但直接影响拍摄时画面有没有抖动,值得在装配时多花十分钟。
3.2 步进电机细分与扭矩匹配
电机选择上,滑轨和云台我都用了 NEMA17 42 步进电机,保持扭矩标称 0.4 牛米左右。为什么不用更小的 28BYJ-48?因为它虽然是便宜步进电机,但带减速箱、转速低,而且扭矩响应不够线性,用在滑轨上会明显感觉启停有迟滞。NEMA17 的扭矩匹配可以简单估算:如果滑轨上放一台两公斤的相机组合,负载重力约 20 牛,驱动滑块所需的牵引力主要是摩擦力和启动时的惯性力,取个系数算 30 牛已经很大了。20 齿同步轮的节圆半径约 6.37 毫米,电机需要输出的扭矩约 30 × 0.00637 = 0.191 牛米,所以 0.4 牛米的保持扭矩是够用的。
云台俯仰轴的情况要复杂一点,因为镜头重心不完全在旋转轴线上。比如镜头加云台板总重 1.5 公斤,重心偏离旋转轴 3 厘米,需要的扭矩就是 1.5 × 9.8 × 0.03 ≈ 0.44 牛米,这就有点悬了。我实际的做法是让云台俯仰电机的轴心尽量对准镜头重心,再在电机尾部加一块配重块,把静不平衡降到最低。如果你不想算这些,直接记住“滑轨可以稍微过载,俯仰轴必须做动平衡”这句话,能省掉后面很多麻烦。
细分设置在 OpenRig 里我建议至少 16 细分,最好 32 细分。细分越高,低速时电机运行越平稳,噪音也越小,但代价是同样的转速需要更高的脉冲频率,而且超过 32 细分之后平滑度提升就不明显了。我用的是 DRV8825 驱动器,最高支持 32 细分,日常就固定在 32 细分。如果你用 TMC2200 或 TMC2209,还有静音模式加持,拍摄时即使靠近设备也听不到电机声,对视频录音特别有利。
3.3 电池容量与续航估算
OpenRig 的供电我设计成两种模式:室内用 12V 电源适配器,户外用 3S 锂电池。3S 电池包就是三节 18650 串联,标称电压 11.1V,满电 12.6V,容量可以按你手头的电芯来选。续航估算公式并不复杂:设备总电流等于两个步进电机驱动器电流加上 ESP32 和 Arduino 的电流。驱动器如果设为每相 1A,两个电机满负载时电流大概 1.5 到 2A,控制板加 Wi-Fi 大概 0.3A,整机平均下来按 1.5A 算。3S 2200mAh 电池理论续航约 1.47 小时,实际打六折约 55 分钟;换成 3S 5000mAh 就能跑两个多小时。
这里有个容易踩的坑:不要把 18650 直接并联给电机驱动器供电。电机启停瞬间电流变化很大,如果共用一根细线,控制板会被拉低电压导致重启。我的做法是电源先接到一个 T 型分线器,一路粗线(18AWG 或更粗)给驱动器供电,另一路经过 LM2596 降压模块降到 5V 给 Arduino 和 ESP32。降压模块的输出电容也建议加大到 470 微法以上,避免 Wi-Fi 瞬态电流造成重启。电池电量显示不要依赖 ESP32 的 ADC 直读,因为参考电压不稳会非常不准,我用的是一个外置的电压比较器模块,低电量时输出信号让网页弹警告。
4. 从零搭建实操记录
4.1 3D 打印件与装配顺序
机械件我用 PLA+ 打印,层高 0.2 毫米,壁厚 4 层。整套零件大概包括:两个滑轨端板、一个滑块底板、一个电机座、两个云台旋转支架、两个电机法兰和若干皮带张紧块。打印方向要特别注意:滑块底板是承力件,打印时把最大平面贴在热床上,层间结合强度会好很多;端板上用于安装轴承的孔必须水平方向打印,否则孔洞会因为层纹收缩而不圆。我一开始图方便把端板竖着打,装轴承时发现孔径偏小,电烙铁扩孔后同心度也差了。
装配顺序建议从滑轨开始。先把两根 2020 型材切到同样长度,端面打磨毛刺,放到大理石平台或玻璃板上检查平行度。然后固定端板,用螺栓把型材锁紧,再用卡尺量两端距离确认没有锥形。接下来装滑块:直线轴承可以先涂一层锂基脂,再装进滑块底板,让滑块能在这两根型材上顺滑滑动。最后装同步带和电机,由手转动同步轮检查是否卡顿,确认没有干涉之后再接电测试。记住一条铁律:机械部分不顺畅之前,绝对不要给电机通电,否则摩擦阻力加上电机力矩可能把打印件拧裂。
云台部分我用了两个 608 轴承做旋转支撑,比直接让 3D 打印件之间摩擦转动要稳得多。水平旋转轴用了一个 5x25 毫米的不锈钢轴,穿过上下两块打印件;俯仰轴直接用电机输出轴和轴承座支撑。装配完成后,用手把所有可动关节都转一遍,应该有不大的阻力但没有任何咔哒声。每个螺丝都建议加一点螺纹胶,不然拍摄时电机的振动会让螺丝自己松掉,云台越拍越歪。
4.2 电路接线与防呆处理
接线不算复杂,但容易乱。我的核心板是一块 Arduino Nano,接 DRV8825 驱动器:DIR 接 D2,STEP 接 D3,ENABLE 接 D4,GND 和 5V 接好。云台的水平电机接另一个驱动器,DIR 接 D5,STEP 接 D6;俯仰电机再接第三个。三个驱动器的 VDD 接 5V,VMOT 接 12V,并在 VMOT 和 GND 之间加一个 100 微法电解电容吸收浪涌。ESP32 开发板的 TX 接 Nano 的 RX,RX 接 Nano 的 TX,共地必须连,不然串口通信会乱。
防呆处理上有三个建议。第一,所有接线端子都用带螺丝固定的插拔端子,不要直接焊死在板子上,因为调试阶段改线很频繁;第二,驱动器小板上有一个调节电机电流的电位器,通过旋转螺丝刀可以设定电流上限,具体换算关系是 Vref = 电流 × 0.5(DRV8825),比如 1A 对应 0.5V,测量时用万用表接在电位器触点和 GND 之间,边测边调;第三,电源输入加一个自恢复保险丝,串在 12V 正极线上,万一电机堵转短路,保险丝会断开保护控制板,冷却后恢复,能避免烧掉一片驱动器。
说到驱动器我就多说一句。DRV8825 的散热片在芯片正面的小铜片,实际工作一段时间后会烫手,不能直接贴在 3D 打印件上,热量散不出去会触发过热保护。我是在每个驱动器和打印件之间加了一小块铝散热片,再在芯片表面贴一个微型风扇,拍摄时温度稳定在五十度左右。如果你用 TMC2209,发热会低很多,但一样不要完全封闭。
4.3 固件烧录与运动参数标定
固件我分成两层写。底层的 Arduino 程序负责运动控制,核心逻辑是接收串口指令并转换成步进脉冲。指令格式我定义得很简单,例如MOVE 10000 1200表示滑块移动到 10000 个脉冲的位置,速度 1200 脉冲每秒;PAN 8000表示水平云台转到指定脉冲位置。所有指令以换行符结束,超时没收到就停止当前运动。用 AccelStepper 库实现加减速,代码量不大:
#include <AccelStepper.h> const int sliderEnablePin = 4; AccelStepper slider(1, 3, 2); // STEP, DIR void setup() { pinMode(sliderEnablePin, OUTPUT); digitalWrite(sliderEnablePin, LOW); slider.setMaxSpeed(16000); slider.setAcceleration(8000); Serial.begin(115200); } void loop() { if (Serial.available()) { String cmd = Serial.readStringUntil('\n'); cmd.trim(); if (cmd.startsWith("MOVE")) { long target = cmd.substring(5).toInt(); slider.moveTo(target); } } slider.run(); }这只是演示代码。实际工程里我会加限位开关回零逻辑:上电后滑块先往负方向移动,碰到限位开关后停住,把当前位置设为零点。回零非常重要,否则每次开机滑块位置都不知道,手机端显示的位置就是假的。标定的过程是:用尺子量滑块移动的真实距离,和程序收到的脉冲数对比,生成一个误差系数。比如程序发 160000 个脉冲,滑块实际走了 90 厘米而不是理论上的 100 厘米,那么系数就是 0.9,以后实际目标 = 理论目标 × 0.9。这个误差主要来自皮带实际节距和同步轮齿数的误差,每个装置都不同,必须实测标定。
4.4 手机端/手柄端控制逻辑
ESP32 端我跑了一个轻量 Web 服务器,提供三个东西:一个 HTML 控制页面、一组 REST 接口、一路 WebSocket。控制页面用最普通的 HTML + JavaScript 实现,滑块部分是一个进度条加速度输入框,云台部分是两个旋转按钮,还有一个自动往返模式。页面代码不多,但能说明问题:
function moveSlider(target, speed) { socket.send(`MOVE ${target} ${speed}`); } function startLoop(distance, speed) { socket.send(`LOOP ${distance} ${speed}`); }WebSocket 收到 Arduino 汇报的位置后,再通过连接回传给浏览器,实时刷新进度条。这里有个细节:ESP32 和 Arduino 之间的串口波特率我用 115200,Arduino 每 100 毫秒上报一次位置。太快会让串口占满,太慢则手机界面看起来卡顿,100 毫秒是我实测下来兼顾实时性和稳定性的值。如果你不想写前端,也可以用现成的开源库搭一个简单遥控手柄,用两个摇杆模块分别控制滑轨和云台,优先级比 Wi-Fi 网页更高一点,适合在现场快速操作。
自动往返模式是 OpenRig 比较常用的功能。在网页里设置两个端点 A 和 B,以及运行速度、暂停时间、循环次数,系统会自动在两端之间往返。实现方式并不复杂:滑块到达端点后先减速停止,短暂暂停,再反向加速。暂停时间用来给相机快门触发留窗口,比如配合相机间隔拍摄,就能实现“每到一个位置拍一张,然后移动”的产品图批量拍摄流程。这个功能对手动滑轨来说是噩梦,但对步进电机来说只是一个小的状态机。
5. 调参经验与常见问题排查
5.1 抖动、丢步、过热:三个高频问题
我调试 OpenRig 过程中遇到的三个高频问题,分别是画面抖动、电机丢步和驱动器过热。先说话面抖动。滑块在移动过程中如果出现微小顿挫,最直接的原因是速度曲线太突兀,启停加速度过大。AccelStepper 的加速度参数默认值可能偏高,我建议从 4000 脉冲每平方秒开始往上调,找到不丢步的临界值,再留 30% 余量。另一个原因就是皮带张力不足,滑块在电机换向时会有回差,这个只能通过机械调整解决,跟代码无关。
电机丢步的现象通常是滑块移动距离和设定值对不上,或者云台转到一半歪了。丢步的原因按概率排:驱动器电流不够、加速度过大、皮带打滑、电机电缆接触不良。第一次排查不要动代码,先用手按住滑块感觉一下有没有明显的冲击感;如果是瞬间启动太猛,把加速度减半;如果每次都在同一个位置丢步,大概率是皮带在那个位置有一个磨损点或毛刺。此外,NEMA17 电机在低速时会有一小段共振区间,大概在 200 到 400 整步每秒,如果不幸落在这个区间,画面会明显麻点,解决方法是调细分或者干脆避开这个速度范围。
驱动器过热是最容易被忽视的。DRV8825 正面那个小铝片温度超过 80 度就会触发保护,表现为电机突然停止但 Arduino 还在运行。我一开始以为是程序死循环,查了很久才发现是过热。解决思路除了加散热之外,还要检查电流设置是不是过高。很多教程让你调到电机标称电流,但实际负载没那么大,完全可以降到 0.8A 甚至更低,只要不丢步就行。温度每下降十度,系统稳定性上一个台阶,这句话一点不夸张。
5.2 常见问题速查表
我把 OpenRig 调试期最常碰到的问题整理成一个速查表,方便对照排查。
| 现象 | 优先排查方向 | 处理方法 |
|---|---|---|
| 滑块不走,电机有嗡嗡声 | 驱动器电流太低 | 调高 Vref,检查电机接线没有缺相 |
| 滑块不走,电机完全无声 | 使能信号没生效 | 检查 ENABLE 脚电平,驱动器和控制板共地 |
| 滑块走但位置偏差越来越大 | 丢步或皮带打滑 | 降低加速度、增大电流、张紧皮带 |
| 云台水平轴抖动 | 共振区间或细分低 | 提高细分,避开特定速度段 |
| Wi-Fi 页面卡顿 | 同频干扰或串口上报过快 | 调整热点信道,串口上报间隔改成 200ms |
| 电池供电时控制板重启 | 电源压降 | 加大降压电容,驱动器单独粗线供电 |
| 打印件孔位不匹配 | 打印收缩 | 孔位模型预留 0.2 到 0.4mm 余量,用铰刀修正 |
这个表不是用来背的,而是提醒你排查要有顺序。先机械后电气,先电源后信号,不要一上来就改程序。因为 OpenRig 这种项目,硬件和软件变量非常多,盲目改代码会把问题搞得更复杂。
5.3 我踩过的坑和最后留下的经验
最后分享几个我反复踩过的坑。第一个是关于限位开关的安装。我刚开始用的是机械微动开关,固定方式是用热熔胶粘在端板上,结果滑块高速回零时直接把它撞飞了。后来改成带滚轮臂的微动开关,并在滑块上设计一个斜角撞块,让滑块碰到开关时是渐进式触发而不是硬撞,才稳定下来。另一个坑是串口通信的共地问题。ESP32 和 Arduino 分开供电时,如果两个电源不共地,串口数据会出现随机乱码,表现为指令响应迟缓或完全无响应,你可能以为代码有问题,其实只差一根杜邦线。
根据我自己的经验,OpenRig 这类项目能顺利跑起来的关键,不是某个原件多贵,而是每一步都留足调试空间。给皮带加张紧轮、给步进电机配独立的散热片、给电源线留粗线径、给螺丝上螺纹胶,这些看起来不起眼的小改动,最后决定整机能不能稳定拍摄 30 分钟。如果你打算复刻一套,我建议第一版不要追求高性能,先把滑轨 100 毫米每秒、云台 30 度每秒这种保守参数跑通,再逐步提速。由慢到快,你会更清楚每一次速度提升背后牺牲了哪些东西。
最后再分享一个小技巧:在 OpenRig 的滑块上贴一张反射贴纸,用对射式光电传感器做成一个外部硬触发输入,每次滑块经过中点时触发相机快门。这个玩法让我拍出了很多以前用稳定器做不出来的机位镜头,而且它只需要多花几块钱和几行代码。设备做到这个程度,才真正算得上“Open”——不只是打开图纸,而是打开新的拍摄思路。