1. 项目缘起:从“吃灰”的Arduino Due到桌面机械臂
手头有一块Arduino Due开发板,性能比Uno强不少,但很多经典的扩展板(Shield)因为引脚定义和电压问题,并不能直接插上用。这板子就这么放着,总觉得有点浪费。正好,一直想搞个桌面机械臂玩玩,用来抓取小物件、写写字,或者单纯作为个酷炫的摆件。市面上成熟的桌面机械臂套件要么太贵,要么是封闭系统,可玩性不高。
这时,我注意到了Arduino官方出品的Braccio机械臂。它的设计很经典,结构清晰,有现成的库和教程。但问题是,Braccio的官方控制板(Shield)是为Arduino Uno或Mega设计的,无法直接兼容我的Due。官方的Braccio Shield使用了特定的引脚映射和PWM伺服控制芯片,而Due的引脚布局、工作电压(3.3V)和PWM生成方式都不同,直接插上不仅可能不工作,甚至可能损坏伺服电机或开发板。
于是,一个想法诞生了:为什么不自己动手,为Arduino Due量身打造一块Braccio机械臂扩展板呢?这不仅仅是简单的引脚转接,更涉及到电源管理、信号电平转换、以及如何利用Due更强大的性能(比如更多的PWM输出、更快的处理速度)来提升机械臂的控制精度和流畅度。这个DIY过程,既能彻底“盘活”手头的Due,又能深入理解机械臂控制的核心硬件原理,比直接买套件有成就感得多。
2. 核心需求分析与方案选型
为Arduino Due设计一块Braccio兼容盾,不能是简单的“照葫芦画瓢”。我们需要先彻底理解原版Braccio Shield的工作原理,然后针对Due的特性进行重新设计。
2.1 原版Braccio Shield拆解
原版Braccio Shield的核心功能可以概括为三点:
- 伺服电机驱动:控制6个舵机(通常4个用于底座、肩、肘、腕部俯仰,1个用于腕部旋转,1个用于夹爪)。它使用了一片PCA9685 PWM伺服驱动芯片。这片芯片通过I2C与Arduino通信,可以独立产生16路12位精度的PWM信号,完美解决了Uno/Mega原生PWM输出不足且精度控制麻烦的问题。
- 电源管理:机械臂的舵机,尤其是大扭矩的舵机,工作电流很大(单个堵转电流可能超过1A)。原版Shield设计了一个外接电源接口(常用7-12V DC),并包含一个开关和一路5V稳压(例如通过LM7805)给Arduino板供电,同时另一路电源(通常经过一个二极管)直接供给PCA9685芯片和舵机。这里的关键是舵机电源与Arduino逻辑电源的分离与共地,避免电机噪声干扰核心控制。
- 引脚映射与扩展:Shield将Uno的特定引脚(如SDA, SCL用于I2C,某些数字引脚用于预留功能)引出,并保留了其他引脚供用户使用。
2.2 Arduino Due的特殊性与挑战
Due与Uno/Mega的主要差异构成了我们设计的挑战与机遇:
- 工作电压:Due的逻辑电平是3.3V,而绝大多数舵机(包括Braccio常用的)控制信号是5V TTL电平。直接用Due的IO口驱动5V舵机,可能存在信号识别不可靠的问题,长期使用也可能对Due的引脚造成压力。
- 引脚布局:Due的引脚排列与Uno完全不同,因此原版Shield的物理接口无法兼容。
- PWM能力:Due拥有多达12路原生PWM输出(引脚2-13),且精度更高。这让我们思考:是否还需要PCA9685?直接用Due的PWM驱动舵机是否可行?
- 性能:Due基于32位ARM Cortex-M3内核,84MHz主频,性能远超8位的AVR。这意味着我们可以运行更复杂的运动学算法、轨迹规划,甚至未来接入计算机视觉库。
2.3 DIY方案决策
基于以上分析,我制定了两个主要方案:
方案A(保守兼容方案):复刻核心,适配接口
- 核心:继续使用PCA9685伺服驱动芯片。这是最稳定、最接近原版体验的方案。PCA9685本身由5V供电,其输出信号是5V,完美匹配舵机。
- 关键改造:
- 电平转换:Due的3.3V I2C(SDA1, SCL1)需要经过双向电平转换模块(如TXS0108E)后再连接PCA9685,确保通信可靠。
- 电源设计:保留外接电源输入(7-12V),一路通过DC-DC降压模块(如LM2596)得到稳定的5V,供给PCA9685和舵机;另一路通过低压差稳压器(LDO)得到3.3V,单独给Due供电。两路电源共地。这里一个重要的经验是:即使Due可以通过USB供电,也强烈建议使用Shield上的独立电源为Due供电,以确保系统稳定,避免因USB供电能力不足导致的重启。
- 接口定义:重新设计PCB,使排针孔位与Due的引脚布局完全匹配。
方案B(激进性能方案:Due直驱)
- 核心:摒弃PCA9685,直接利用Due的12路原生PWM输出引脚驱动舵机。
- 优势:简化硬件,降低成本,并且由于Due的PWM由软件直接控制,理论上响应更快,更易于实现高级控制算法。
- 巨大挑战:
- 电平不匹配:必须为每一路PWM信号增加3.3V转5V的电平转换电路(例如使用74HCT245这样的缓冲器,其输入兼容3.3V,输出为5V)。
- 电流考虑:Due的单个IO口驱动能力有限,虽然驱动舵机信号线(输入阻抗高)通常没问题,但经过缓冲器更保险。
- 软件负担:需要自己编写或移植舵机控制库,管理多达6路PWM的精度和角度映射,这比使用现成的Adafruit_PWMServoDriver库(针对PCA9685)要复杂。
我的选择与理由: 我最终选择了方案A。原因在于,DIY的首要目标是“可靠实现功能”,PCA9685是经过市场验证的专用方案,其16路独立12位PWM输出能提供非常平稳的舵机运动,软件上有成熟的库支持,极大降低了开发门槛。而方案B虽然硬件更简洁,但电平转换电路设计、软件驱动稳定性都需要大量调试,不确定性高。先追求稳定可用,再考虑优化升级,这是硬件DIY中的一个重要原则。我们可以把Due的强大算力留给上层运动控制,而不是底层PWM生成。
3. 硬件设计与核心电路详解
确定了方案A,就可以开始具体的电路设计。我使用立创EDA进行原理图绘制和PCB布局。
3.1 核心电路模块拆解
3.1.1 电源模块
这是整个盾板的“心脏”,设计不当会导致系统不稳定、舵机无力甚至损坏控制器。
- 输入接口:采用标准的5.5*2.1mm DC插座,输入电压范围7-12V。并联一个电源开关,方便断电。
- 舵机电源通路:输入电压经过一个肖特基二极管(如1N5822)防止反接后,直接连接到一片大电流的DC-DC降压模块(例如LM2596可调模块的固定5V版本)。这一步将7-12V降至稳定的5V/3A以上输出,专门用于驱动6个舵机。务必注意:舵机在启动和堵转时电流极大,电源必须留有充足余量。建议选择持续输出电流不低于3A的降压模块,并在电源输入和输出端并联大容量电解电容(如470uF-1000uF)以缓冲电流冲击。
- 控制板电源通路:从上述5V舵机电源后,再接入一片低压差稳压器(LDO),如AMS1117-3.3,将其转换为3.3V,为Arduino Due供电。这样设计保证了Due和舵机系统共地,且Due的电源相对干净。一个关键细节:在AMS1117的输入和输出端,都需要紧贴引脚放置0.1uF和10uF的陶瓷电容进行滤波,这是保证3.3V电源纯净、系统稳定的关键。
3.1.2 主控与信号转换模块
- Arduino Due接口:设计两组双排排母,严格按照Due的引脚顺序(包括两侧的电源引脚)进行定义。确保物理上可以严丝合缝地插上。
- I2C电平转换:Due的I2C1引脚(SDA1-引脚20, SCL1-引脚21)连接到一个双向电平转换芯片,如TXB0108或TXS0108E。这类芯片可以自动识别方向,将3.3V信号转换为5V信号与PCA9685通信,反之亦然。注意:TXB0108系列对上下拉电阻有要求,需严格按照数据手册设计。
- PCA9685电路:按照其数据手册设计。核心包括:
- 连接转换后的I2C信号(SDA, SCL)。
- 外接一个精度较高的晶振(通常25MHz)以获得稳定的PWM频率。
- 设置I2C地址的跳线(A0-A5),默认全为0,地址是0x40。
- VCC接5V舵机电源,V+也接5V舵机电源(如果舵机工作电压是5V)。
- OE(输出使能)引脚可以接一个Due的GPIO,方便软件全局禁用舵机输出,这是一个安全特性。
- 16路PWM输出引脚(PWM0-PWM15)通过排针引出,我们只需要前6路。
3.1.3 舵机接口与保护
- 接口定义:使用标准的3针舵机接口(信号Signal, 电源VCC, 地GND)。将6个接口整齐排列,并清晰标注对应关节(如Base, Shoulder, Elbow, Wrist Vert, Wrist Rot, Gripper)。
- 保护电路:在每个舵机信号线与地之间,可以串联一个220-470欧姆的电阻,作为轻微的限流保护。更重要的保护是在电源线上。强烈建议为每个舵机接口的VCC引脚增加一个自恢复保险丝(PPTC),例如500mA的规格。当某个舵机卡死导致电流激增时,保险丝会断开,保护整个电源网络,故障排除后又能自动恢复。这是从多次烧毁元件的教训中学来的宝贵经验。
3.2 PCB布局与布线要点
原理图正确只是第一步,PCB布局布线决定了最终板的性能和抗干扰能力。
- 电源路径优先:首先规划电源的走线。从DC输入插座到降压模块,再到舵机接口排针,这条路径上的走线要尽可能短、尽可能宽。我会使用至少40mil(约1mm)的线宽来承载大电流。5V电源网络最好在PCB的底层或顶层进行铺铜,以降低阻抗。
- 数字与模拟/电源分离:将PCA9685及其晶振、I2C线路等数字部分,与DC-DC降压模块这类开关电源部件在布局上适当远离。如果空间允许,可以在它们之间留出一定间隙或用地线进行隔离。
- 去耦电容就近放置:给AMS1117、PCA9685、Due的3.3V输入引脚附近放置的0.1uF陶瓷电容,必须紧贴芯片的电源和地引脚,回路面积最小化。这是抑制高频噪声最有效的措施之一。
- 接口位置人性化:DC电源插座、开关、舵机接口的位置要考虑到实际组装和使用时的方便性。例如,舵机接口最好放在板子边缘,方便插拔线缆。
完成布局布线后,生成Gerber文件,就可以发送给PCB制板厂(如JLCPCB)进行生产了。为了美观和耐用,可以选择沉金工艺,并涂上阻焊层。
4. 软件配置与机械臂库移植
硬件焊接组装完成后,就进入了软件环节。目标是让Arduino Due通过我们自制的Shield,像原版Braccio一样控制机械臂。
4.1 基础库安装与I2C通信测试
- 安装必要的库:在Arduino IDE中,通过库管理器安装
Adafruit PWM Servo Driver Library。这个库用于控制PCA9685。 - 编写I2C扫描程序:由于我们使用了电平转换芯片,第一步是确认Due能否正确识别到PCA9685。上传一个简单的I2C扫描程序到Due,查看串口监视器。如果一切正常,应该能看到地址
0x40(或其他你设置的地址)被扫描到。如果扫描不到,首先检查:焊接有无短路/虚焊;电平转换芯片是否正常工作(测量输入输出电平);PCA9685的电源和地是否接好;I2C上拉电阻(通常PCA9685内部已集成,但外部加4.7k上拉到5V也可能需要)是否合适。
4.2 适配Braccio库
原版Braccio库(Braccio.h/Braccio.cpp)是直接针对使用特定引脚映射的Uno和Mega的,它内部可能直接操作了某些硬件寄存器。对于Due+PCA9685的方案,我们需要进行“软”适配。
核心思路是:创建一个新的“BraccioDue”库,或者修改原库,将其底层控制舵机的部分,替换为通过Adafruit_PWMServoDriver库向PCA9685发送指令。
具体步骤:
- 理解原库结构:原版
Braccio.begin()函数会初始化各舵机引脚和初始位置。我们需要新建一个初始化函数,例如BraccioDue.begin(addr),其中addr是PCA9685的I2C地址。在这个函数里,初始化Adafruit_PWMServoDriver对象,并设置PWM频率(通常舵机为50Hz,即周期20ms)。 - 重写舵机控制函数:原库的核心是
Braccio.ServoMovement()或类似函数,它接受每个关节的角度值。我们需要重写这个函数,将角度值(例如0-180度)转换为PCA9685需要的“脉宽计数”值。- 公式通常是:
pulse = map(angle, 0, 180, SERVOMIN, SERVOMAX)。其中SERVOMIN和SERVOMAX是脉宽为0.5ms和2.5ms时对应的PCA9685计数器的值。由于PCA9685是12位精度(4096级),对应50Hz频率(每周期4096计数),计算如下:- 每计数时间 = 20ms / 4096 ≈ 4.88us。
- 0.5ms脉宽对应计数 = 0.5ms / 4.88us ≈ 102。
- 2.5ms脉宽对应计数 = 2.5ms / 4.88us ≈ 512。
- 实际上,不同舵机的中位和行程可能有细微差异,所以
SERVOMIN和SERVOMAX可能需要微调(例如设为100和500)。这里一个重要的技巧是:不要写死这些值,最好将它们定义为全局常量,方便在程序开头统一调整。
- 公式通常是:
- 提供角度到脉宽的映射函数:创建一个私有函数
writeAngle(int servo_num, int angle),它内部完成上述计算,并调用pwm.setPWM(servo_num, 0, pulse)来驱动指定通道的舵机。
4.3 示例代码与校准
完成库适配后,可以写一个简单的测试程序。
#include <Wire.h> #include <Adafruit_PWMServoDriver.h> #include "BraccioDue.h" // 你的适配库 Adafruit_PWMServoDriver pwm = Adafruit_PWMServoDriver(0x40); BraccioDue arm; // 假设你的类叫这个 void setup() { Serial.begin(9600); // 初始化PCA9685,设置频率50Hz pwm.begin(); pwm.setPWMFreq(50); // 初始化机械臂,设置初始角度 arm.begin(); delay(2000); // 等待舵机就位 } void loop() { // 示例:让机械臂执行一个简单动作 // 参数顺序可能是:底座,肩部,肘部,腕部俯仰,腕部旋转,夹爪 arm.move(90, 45, 180, 0, 90, 10); // 移动到某个姿势 delay(3000); arm.move(0, 90, 90, 90, 0, 73); // 移动到另一个姿势 delay(3000); }至关重要的校准过程: 上传程序后,机械臂可能不会精确地到达你期望的位置。这是因为:
- 舵机中位(90度)对应的实际脉宽可能不是严格的1.5ms。
- 舵机的运动范围可能不是标准的180度。
- 机械臂的物理安装可能存在零点偏移。
你需要一个校准程序:逐个驱动每个舵机,从0度到180度缓慢变化,观察机械臂的实际运动。记录下每个舵机在机械极限位置(不卡住)时对应的脉宽计数(即SERVOMIN和SERVOMAX),以及中间位置(如90度)的计数。将这些校准后的值更新到你的BraccioDue库中。切记:校准时要轻柔,避免舵机堵转。这是整个项目中最需要耐心的一步,但也是保证机械臂动作精准的基础。
5. 系统集成、测试与性能优化
当硬件和基础软件都跑通后,就可以进行系统集成和进阶测试了。
5.1 组装与静态测试
- 机械结构组装:按照Braccio的机械图纸或套件说明,将舵机、支架、连杆、夹爪等部件组装起来。注意螺丝不要拧得过紧导致塑料件开裂,也确保每个关节转动顺滑,没有明显的阻力。
- 电气连接:将组装好的机械臂各舵机线,对应插入自制Shield的接口。确保电源极性正确(棕色/黑色线通常是GND)。
- 上电前最后检查:万用表检查电源输入有无短路;确认Due已通过USB连接到电脑(用于上传程序和监控);Shield上的电源开关处于关闭状态。
- 分步上电测试:先打开Shield电源开关,观察Due是否正常启动(电源指示灯亮)。然后通过串口发送单个舵机控制命令,观察每个关节是否单独正常运动。此时应密切注意舵机是否有异响(抖动、吱吱声)、电源模块或芯片是否异常发热。
5.2 动态测试与问题排查
进行连贯动作测试时,可能会遇到以下典型问题及解决方案:
| 问题现象 | 可能原因 | 排查与解决方案 |
|---|---|---|
| 动作卡顿、不流畅 | 1. 电源功率不足,导致大负载时电压跌落。 2. PWM信号频率不稳定或有毛刺。 3. 舵机本身性能差或机械阻力大。 | 1.使用示波器或万用表监测5V电源线,在动作时看电压是否稳定在5V以上。如果跌落严重,需升级电源适配器或DC-DC模块。 2. 检查PCA9685的晶振电路,确保焊接良好。在代码中确认 setPWMFreq(50)已正确执行。3. 尝试单独驱动该关节舵机,如果仍然卡顿,可能是舵机质量问题或机械安装过紧。 |
| 舵机无法到达指定角度(到达即回弹) | 舵机扭矩不足,无法克服机械臂在某个姿势下的重力矩。 | 这是桌面机械臂的常见问题,尤其在肩部和肘部关节。解决方案:a) 更换更大扭矩的舵机(如从9g舵机换为20kg-cm的舵机)。b)优化动作轨迹:避免让机械臂长时间处于“力臂最长”的全伸展状态。在运动学控制中,可以规划更省力的路径。c) 减轻末端执行器(夹爪)的重量。 |
| 控制一段时间后,舵机位置出现漂移 | 1. 舵机在持续受力下产生位置误差。 2. PCA9685或Due因温度变化产生微小漂移。 3. 电源噪声导致PWM信号基准变化。 | 1. 这是廉价舵机的通病,对于精度要求不高的应用可以接受。如需高精度,需选用带位置反馈的数字化舵机。 2. 确保PCA9685和Due的电源滤波电容充足且靠近芯片。 3. 在控制逻辑中,可以加入周期性归零或位置反馈校正(如果使用带反馈舵机)。 |
| I2C通信偶尔失败 | 1. 电平转换电路不稳定。 2. I2C线路过长或受到干扰。 3. 电源噪声影响。 | 1. 检查电平转换芯片的电源和地是否稳定,尝试在I2C线(SDA, SCL)上加更小的上拉电阻(如2.2kΩ)以增强驱动能力。 2. 尽量缩短Shield与Due之间的连接。 3.在代码中加入错误重试机制,例如如果一次I2C写入失败,延迟几毫秒后重试一次。 |
5.3 利用Due性能进行进阶优化
硬件稳定后,就可以发挥Due的性能优势了:
- 更平滑的运动轨迹:原版Braccio库的运动可能比较“生硬”。我们可以利用Due强大的算力,在
move()函数中实现梯形速度规划或S曲线规划。不是直接让舵机从角度A跳到角度B,而是计算出一系列中间角度和每个角度之间的延时,让舵机以匀加速、匀速、匀减速的方式运动,这样动作看起来会非常柔和、专业。 - 逆运动学控制:不再直接控制每个关节的角度,而是告诉机械臂“把夹爪移动到空间中的某个坐标(x, y, z)”,Due自动计算出每个关节需要转动的角度。这需要编写或移植逆运动学算法。Due的浮点运算能力(通过软件FPU)使得这些计算可以快速完成。
- 外部通信与控制:通过Due额外的串口(Serial1, Serial2, Serial3)或USB Host功能,可以连接蓝牙模块、Wi-Fi模块,甚至直接与电脑上的Processing、Python程序通信,实现远程控制或更复杂的视觉伺服控制。
完成这个DIY项目后,你得到的不仅仅是一个能动的Arduino Due机械臂,更是一套完全由自己掌控的、从硬件电路到核心控制软件的机器人开发平台。它可能没有商业产品那样精致的外壳,但每一个细节你都了如指掌,后续的任何功能扩展和性能优化,你都知道从哪里入手。这种深度的掌控感和解决问题的能力,正是硬件DIY最大的乐趣所在。