尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

70元自制3自由度机械臂:Arduino与舵机控制入门实践

70元自制3自由度机械臂:Arduino与舵机控制入门实践 在嵌入式开发、机器人教育和创客项目中机械臂是一个经典且极具吸引力的课题。它融合了结构设计、电子控制、编程逻辑和运动算法等多个领域。然而市面上成品的桌面级机械臂价格不菲动辄上千元让许多初学者望而却步。实际上利用常见的开源硬件和低成本材料完全可以在百元预算内打造一个功能完整的迷你机械臂这不仅成本极低更能让你透彻理解从机械结构到控制代码的每一个环节。本文将带你从零开始用大约70元的预算手搓一个三自由度3-DOF的迷你桌面机械臂。这个机械臂将具备基本的抓取和定点移动能力你可以通过编程控制它在二维平面上移动并抓取小物件。我们将使用Arduino作为主控SG90舵机作为关节执行器亚克力板或3D打印件作为结构主体。整个过程会涵盖机械结构的设计与组装、电子电路的连接、Arduino程序的编写以及最终的运动调试。无论你是电子爱好者、机器人初学者还是想带孩子一起完成一个STEM项目的家长都能按照本文的步骤亲手实现这个有趣的项目。1. 核心部件选型与成本核算在开始动手之前我们需要明确整个机械臂由哪些部分组成并精确计算成本。一个最基本的舵机机械臂通常包括结构件、执行器、控制器和电源。1.1 机械结构件骨架与连接机械臂的“身体”需要坚固且轻便。对于低成本项目我们有几种选择激光切割亚克力板这是最推荐的方式。你可以在设计软件如Fusion 360, SolidWorks中画好零件图然后导出DXF文件在淘宝或本地加工店进行切割。优点是精度高、外观整洁、成本可控。本项目所需亚克力板面积很小成本约15-20元。3D打印如果你有3D打印机这是最方便的选择。需要下载或设计STL模型文件进行打印。使用PLA材料成本主要在于耗材约10-15元。手工材料备选如冰棒棍、轻木条、甚至乐高积木。这些材料易于获取和修改适合快速原型验证但精度和强度较差不适合长期运行。成本估算我们按亚克力板方案计算取中间值18元。1.2 执行器舵机的选择与参数舵机Servo是机械臂的“肌肉”它接收控制信号精确地转动到指定角度。型号SG90 微型舵机。这是最常用、最廉价的9克舵机。工作电压4.8V ~ 6.0V通常使用5V供电。扭矩约1.5kg/cm在5V时。对于小型轻量机械臂这个扭矩足够。控制信号PWM脉冲宽度调制信号。标准周期为20ms脉冲宽度在0.5ms到2.5ms之间对应0度到180度的位置。数量一个三自由度机械臂至少需要3个舵机。分别控制底座旋转水平面。大臂抬起/放下垂直面。小臂抬起/放下垂直面。可选第四个舵机用于末端夹持器的开合。成本估算SG90舵机单价约8-12元。我们按3个计算取单价10元共30元。1.3 控制器与电路大脑与神经网络主控板Arduino Uno R3 兼容板。它是创客项目的核心拥有丰富的库和社区支持易于编程。兼容板价格非常低廉。扩展板舵机扩展板或PCA9685 PWM舵机驱动板。直接连接多个舵机到Arduino可能会因电流过大而损坏主板或导致供电不足。使用扩展板可以解决供电和信号隔离问题。对于本项目一个简单的舵机扩展板或使用PCA9685模块是更好的选择。杜邦线用于连接电路公对公、公对母都需要一些。电源舵机对电流需求较大特别是多个同时运动时。不能依赖电脑USB口的5V/500mA供电。需要一个独立的5V/2A以上的电源适配器或者使用一组7.4V锂电池配合5V降压模块。成本估算Arduino Uno 兼容板15元PCA9685 舵机驱动模块8元杜邦线一包5元5V/2A电源适配器可用旧手机充电器改造0元假设自有小计28元1.4 其他辅材螺丝螺母包M2或M3规格用于固定舵机和结构件。约5元。热熔胶枪及胶棒用于辅助固定和绝缘。约10元可多次使用按比例分摊成本算2元。夹持器可以直接购买一个舵机夹子约5元或者用亚克力板自己设计一个简单的两指夹持器。成本估算螺丝包5元 胶棒分摊2元 夹持器5元 12元1.5 总成本汇总表部件类别具体物品数量单价元小计元备注结构件亚克力激光切割1套1818也可3D打印成本类似执行器SG90 舵机3个1030控制底座、大臂、小臂控制器Arduino Uno 兼容板1个1515主控大脑电路PCA9685 舵机驱动板1个88提供稳定PWM信号和电源电路杜邦线混合包1包55连接线路电源5V/2A电源适配器1个00利用旧手机充电器辅材M3螺丝螺母包1包55固定结构辅材热熔胶棒分摊-22辅助固定末端舵机夹持器1个55完成抓取动作总计88元注意上表总计88元略微超出70元目标。实际上Arduino板、杜邦线、螺丝、胶枪等工具属于一次性投资可用于多个项目。如果严格限定在本项目消耗且使用更便宜的舵机约8元和自有充电器成本可以轻松控制在70元以内。核心在于舵机、结构件和主控这三项。2. 机械结构设计与组装机械结构决定了机械臂的稳定性、运动范围和负载能力。我们设计一个简单的三自由度旋转关节RRR机械臂。2.1 设计要点与尺寸规划自由度分配关节1J1底座旋转负责机械臂在水平面上的左右运动。舵机轴垂直安装。关节2J2肩部关节负责大臂的抬起和放下。舵机轴水平安装。关节3J3肘部关节负责小臂的抬起和放下。舵机轴水平安装。可选关节4J4腕部夹持器负责抓取。臂长设计为了保持舵机扭矩足够臂长不宜过长。建议大臂长度80-100mm小臂长度70-90mm。过长的力臂需要更大的扭矩容易导致舵机堵转、发热甚至损坏。重心与配重机械臂抬起时重心会前移给肩部舵机J2带来很大负载。在设计时应尽量让电机、电池等较重部件靠近底座或者通过结构设计平衡前臂的重量。舵机安装舵机通常通过其自带的安装耳用螺丝固定在结构件上。舵机的输出轴需要与连接件舵盘固定连接件再与下一级臂杆连接。确保连接牢固无晃动。2.2 使用Fusion 360进行简单设计你可以使用任何熟悉的CAD软件。这里以Fusion 360对个人免费为例简述流程绘制草图在“草图”模式下根据规划的尺寸如底座100x100mm大臂长90mm宽15mm绘制出各个零件的轮廓。拉伸成型使用“拉伸”命令将草图变成有厚度的3D实体。亚克力板厚度通常为3mm。打孔在需要安装舵机、连接轴和螺丝的位置绘制圆形草图并“拉伸切割”出孔洞。舵机安装孔的间距和孔径需要与你使用的舵机型号匹配SG90通常为M2螺丝。装配在“装配”工作区将各个零件导入通过“关节”工具定义它们之间的运动关系如旋转关节。导出工程图将每个零件的草图或面导出为DXF格式用于激光切割。给新手的建议如果从未接触过CAD设计可以直接在开源社区如Thingiverse, GrabCAD搜索“SG90 Robot Arm”或“3 DOF Robotic Arm”下载现成的STL3D打印或DXF激光切割文件。这是快速入门的好方法。2.3 物理组装步骤假设你已经拿到了激光切割好的亚克力零件包。准备工具小螺丝刀十字、尖嘴钳、热熔胶枪。组装底座与关节1J1将J1舵机用螺丝固定在底座板的下面输出轴向上穿过底座板。将一个大号舵盘通常随舵机附送用自攻螺丝固定在舵机输出轴上。将“腰部转盘”零件用螺丝锁定到这个舵盘上。这样舵机转动就能带动整个上半身旋转。组装大臂与关节2J2将J2舵机用螺丝固定在“腰部转盘”的侧面输出轴水平向前。将一个舵盘固定在J2舵机输出轴上。将“大臂”零件的一端与这个舵盘连接固定。确保连接紧固无松动。组装小臂与关节3J3将J3舵机用螺丝固定在“大臂”的另一端输出轴水平与J2平行。将一个舵盘固定在J3舵机输出轴上。将“小臂”零件的一端与这个舵盘连接固定。安装末端夹持器如果你购买了成品舵机夹子通常它自带一个舵盘。直接将这个舵盘固定在J3舵机或另一个专用于夹持的J4舵机的输出轴上即可。如果是自制的亚克力夹持器需要设计一个连杆结构将舵机的旋转运动转化为夹爪的开合。走线与固定用扎带或热熔胶将舵机的信号线、电源线沿着机械臂的骨架进行整理和固定避免线路在运动中被拉扯或缠绕。组装完成后用手轻轻转动各个关节检查是否有卡滞、过紧或松动的地方。机械结构应该运动顺滑没有明显的阻力。3. 电路连接与供电系统可靠的电路连接是机械臂稳定工作的基础。核心原则是动力电源给舵机供电与控制电源给Arduino供电最好分离并通过共地连接。3.1 使用PCA9685舵机驱动模块Arduino Uno的IO口可以直接输出PWM信号控制一个舵机但驱动多个舵机时PCA9685模块是更优选择。它是一个I2C通信的16通道PWM控制器可以独立控制16个舵机并且由外部电源供电不消耗Arduino主板电力。连接步骤供电部分准备一个5V/2A以上的电源适配器如旧手机充电器。剪掉USB头剥出红线正极V和黑线负极GND。将电源适配器的正极V连接到PCA9685模块的VCC引脚。将电源适配器的负极GND连接到PCA9685模块的GND引脚。同时将这条GND线也连接到Arduino Uno的GND引脚。这是关键确保控制器和驱动器共地否则信号无法正确识别。信号与控制部分用4根杜邦线母对母连接Arduino Uno和PCA9685模块Arduino5V- PCA9685V(可选为模块内部逻辑供电如果外部电源是5V可接否则接Arduino 5V)ArduinoGND- PCA9685GNDArduinoA4(SDA) - PCA9685SDAArduinoA5(SCL) - PCA9685SCL舵机连接将舵机的三根线棕色-GND红色-V橙色-信号连接到PCA9685模块的对应通道上。例如底座舵机J1 - 通道0大臂舵机J2 - 通道1小臂舵机J3 - 通道2夹持器舵机J4 - 通道3注意舵机插头的方向通常棕色线朝向PCB板上标有“GND”或“-”的一侧。电路连接示意图文字描述外部5V/2A电源 --- PCA9685 VCC GND | | (GND also to Arduino GND) | Arduino Uno ---I2C--- PCA9685 (SDA-A4, SCL-A5) | 通道0 --- J1舵机 通道1 --- J2舵机 通道2 --- J3舵机 通道3 --- J4舵机可选3.2 供电不足的典型现象与解决如果供电不足你会遇到以下问题舵机运动缓慢、无力。多个舵机同时运动时Arduino板自动重启。舵机发出“吱吱”声并发热但不动或抖动。解决与预防绝对不要仅靠电脑USB口给整个系统供电。使用足额电流至少2A的5V电源。电源线要足够粗以减少压降。如果使用锂电池充满电电压可能达8.4V2S必须通过降压模块稳定到5V后再给PCA9685供电。4. Arduino程序编写与运动控制电路连接好后我们通过Arduino IDE编写程序来控制机械臂。我们将使用Adafruit_PWMServoDriver库来方便地操作PCA9685。4.1 环境准备与库安装安装Arduino IDE。打开IDE点击工具-管理库...。在库管理器中搜索“Adafruit PWM Servo Driver”找到并安装Adafruit PWMServoDriver库。安装时它会提示安装依赖库Adafruit BusIO一并确认安装。4.2 基础测试程序让每个舵机动起来首先我们写一个简单的程序让每个舵机依次从0度转到180度再转回来以测试硬件连接和安装是否正确。#include Wire.h #include Adafruit_PWMServoDriver.h // 创建PCA9685对象默认I2C地址为0x40 Adafruit_PWMServoDriver pwm Adafruit_PWMServoDriver(); // 定义舵机连接的通道 #define SERVO_CH_BASE 0 // 底座舵机 - 通道0 #define SERVO_CH_SHOULDER 1 // 大臂舵机 - 通道1 #define SERVO_CH_ELBOW 2 // 小臂舵机 - 通道2 #define SERVO_CH_GRIP 3 // 夹持器舵机 - 通道3 // SG90舵机的脉宽范围单位微秒 // 对应0度和180度。不同舵机可能有细微差异需要校准。 #define SERVOMIN 500 // 0度时的脉宽~500us #define SERVOMAX 2500 // 180度时的脉宽~2500us // 将角度0-180转换为PCA9685所需的脉宽计数值0-4095 // PCA9685工作在50Hz周期20ms分辨率12位4096 uint16_t angleToPulse(uint16_t ang) { // 将角度映射到脉宽微秒 uint16_t pulse map(ang, 0, 180, SERVOMIN, SERVOMAX); // 将脉宽微秒转换为PCA9685的计数值 // 公式计数值 脉宽(us) / (1e6 / 频率(Hz)) / 4096 // 简化后计数值 脉宽(us) * 4096 / 20000 return map(pulse, SERVOMIN, SERVOMAX, 0, 4095); } void setup() { Serial.begin(9600); Serial.println(Mini Robotic Arm Test Start!); pwm.begin(); pwm.setPWMFreq(50); // 设置PWM频率为50Hz这是标准舵机频率 // 初始化舵机到中间位置90度 pwm.setPWM(SERVO_CH_BASE, 0, angleToPulse(90)); pwm.setPWM(SERVO_CH_SHOULDER, 0, angleToPulse(90)); pwm.setPWM(SERVO_CH_ELBOW, 0, angleToPulse(90)); pwm.setPWM(SERVO_CH_GRIP, 0, angleToPulse(90)); delay(2000); // 等待舵机就位 } void loop() { Serial.println(Moving Base...); for (uint16_t ang 0; ang 180; ang 10) { pwm.setPWM(SERVO_CH_BASE, 0, angleToPulse(ang)); delay(50); } for (uint16_t ang 180; ang 0; ang - 10) { pwm.setPWM(SERVO_CH_BASE, 0, angleToPulse(ang)); delay(50); } // 类似地可以添加 SHOULDER, ELBOW, GRIP 的测试循环 // 为了简洁这里省略。你可以复制上面的for循环修改通道号。 delay(2000); // 等待2秒后重新开始 }关键代码解释angleToPulse函数核心转换函数。它将我们直观的“角度”概念转换为PCA9685模块能理解的“脉宽计数值”。map函数在这里进行了两次映射。pwm.setPWMFreq(50)必须设置为50Hz这是标准模拟舵机的工作频率。pwm.setPWM(channel, 0, pulse)这是驱动舵机的关键函数。channel是通道号pulse是计算出的计数值。第二个参数通常为0。在setup中先将所有舵机归中是一个好习惯可以避免上电时舵机乱转。将代码上传到Arduino后你应该能看到机械臂的各个关节依次开始运动。如果某个舵机不动或运动方向相反检查接线和通道号是否正确。4.3 舵机校准解决角度不准问题你可能会发现设置90度时舵机臂并没有垂直向上。这是因为每个舵机存在制造公差。我们需要进行校准。在程序中定义每个舵机的校准偏移量。int offset_base 0; int offset_shoulder 5; // 例如大臂舵机实际90度需要设置为95度 int offset_elbow -3; // 例如小臂舵机实际90度需要设置为87度修改angleToPulse的调用加入偏移量pwm.setPWM(SERVO_CH_SHOULDER, 0, angleToPulse(90 offset_shoulder));通过串口监视器发送指令交互式地调整偏移量直到机械臂达到理想位置。可以写一个简单的串口控制程序来辅助校准。4.4 实现坐标控制从(X,Y)到关节角度让机械臂直接运动到某个空间坐标点比单独控制每个关节角度更直观。这需要用到逆运动学计算。对于我们的三自由度平面机械臂假设夹持器始终垂直向下逆运动学有解析解。正运动学已知各关节角度求末端位置。逆运动学已知末端位置求各关节角度。假设大臂长度L1小臂长度L2末端目标坐标为(x, y)。// 逆运动学计算函数 // 输入目标坐标 (x, y) 臂长 L1, L2 // 输出关节角度 shoulder_angle, elbow_angle (单位度) // 注意此计算基于简化模型且返回的角度是相对于前一个连杆的夹角关节角。 bool inverseKinematics(float x, float y, float L1, float L2, float shoulder_angle, float elbow_angle) { float distance sqrt(x*x y*y); // 判断目标点是否在可达工作空间内 if (distance (L1 L2) || distance fabs(L1 - L2)) { Serial.println(Error: Target point out of reach!); return false; // 不可达 } // 计算肘部关节角度 (余弦定理) float cos_elbow (x*x y*y - L1*L1 - L2*L2) / (2 * L1 * L2); // 防止浮点数误差导致acos参数超出[-1,1] cos_elbow constrain(cos_elbow, -1.0, 1.0); elbow_angle acos(cos_elbow) * 180.0 / PI; // 弧度转角度 // 计算肩部关节角度 float alpha atan2(y, x); float beta acos((L1*L1 distance*distance - L2*L2) / (2 * L1 * distance)); beta constrain(beta, -1.0, 1.0); shoulder_angle (alpha - beta) * 180.0 / PI; // 弧度转角度 // 注意计算出的角度可能是相对于世界坐标系的需要根据你的机械臂零点定义进行转换。 // 例如你的舵机安装方向可能使得0度是水平或垂直。 // 这里需要根据实际机械结构进行调整和偏移。 return true; }在实际程序中你需要测量并定义你的L1和L2单位毫米或厘米保持一致即可。调用inverseKinematics函数计算关节角度。将计算出的关节角度加上校准偏移量再通过angleToPulse函数转换为PWM信号驱动舵机。底座角度base_angle通常直接用atan2(y, x)计算但我们的机械臂是平面臂底座旋转直接对应极坐标下的θ。对于三维点需要更复杂的计算。重要逆运动学是机器人学的核心内容之一。上述公式是一个简化版本适用于所有关节轴平行的平面机械臂。你的实际机械臂结构如舵机0度的朝向会严重影响角度的计算可能需要添加一个固定的偏移量进行转换。这需要通过实验来调整。5. 调试、优化与功能扩展让机械臂基本动起来只是第一步稳定、精准、可控才是目标。5.1 常见问题与排查问题现象可能原因检查与解决方法上电后舵机乱转/抖动1. 电源功率不足。2. PWM信号不稳定或频率不对。3. 舵机中位未校准。1. 使用独立足额电源供电。2. 确认pwm.setPWMFreq(50)已设置。3. 在setup()中先设置所有舵机到中间角度。某个舵机完全不动1. 接线错误通道、VCC、GND。2. 舵机损坏。3. 程序通道号设置错误。1. 用万用表检查该通道电压或换一个通道测试。2. 单独给该舵机接5V和GND信号线接Arduino PWM引脚如9号测试。3. 核对程序中的#define通道号。舵机运动到某个位置卡住并发热1. 机械结构卡死干涉、过紧。2. 负载过重超出舵机扭矩。3. 目标角度超出物理限位。1. 断电后手动转动关节检查是否顺滑。2. 减轻末端负载或缩短力臂。3. 在程序中限制舵机的运动范围如10-170度。逆运动学计算的位置不准1. 臂长L1,L2测量不准。2. 舵机零点未校准。3. 运动学模型简化过度未考虑关节偏移。1. 精确测量实际臂长从旋转中心到下一个中心。2. 进行细致的舵机校准记录每个舵机0度和180度的实际脉冲值。3. 采用更精确的运动学模型或通过“示教学习”方式记录位置点。Arduino通过串口接收指令时程序卡死1. 串口缓冲区处理不当。2. 字符串解析代码有bug。1. 使用Serial.available()和Serial.readStringUntil()稳健地读取数据。2. 在串口通信代码中加入超时和错误处理。5.2 运动平滑与轨迹规划直接让舵机从一个角度跳到另一个角度动作会显得生硬、抖动且对齿轮冲击大。我们需要轨迹规划。最简单的办法是插值。例如从当前角度currentAngle运动到目标角度targetAngle用10步完成。void smoothMove(uint8_t channel, uint16_t startAngle, uint16_t endAngle, uint16_t steps, uint16_t stepDelay) { for (int i 0; i steps; i) { float ratio (float)i / steps; uint16_t intermediateAngle startAngle ratio * (endAngle - startAngle); pwm.setPWM(channel, 0, angleToPulse(intermediateAngle)); delay(stepDelay); } }更高级的规划可以使用加速减速曲线如S曲线使运动更柔和。5.3 功能扩展方向你的迷你机械臂平台可以扩展很多有趣的功能增加自由度增加一个旋转腕关节或一个俯仰腕关节使夹持器能改变姿态。更换末端执行器将夹持器换成电磁铁、吸盘、笔架变成绘图机、激光头变成激光雕刻机。引入传感器限位开关防止机械臂运动超限损坏自身。电流传感器检测舵机堵转实现过载保护。摄像头OpenCV让机械臂具备视觉识别能力实现“看到-抓取”的自动化流程。这需要连接树莓派等更强大的上位机。改进控制方式电位器控制用几个旋钮电位器实时控制每个关节的角度实现“示教”功能。蓝牙/无线控制通过手机APP或电脑软件无线控制机械臂。编程轨迹让机械臂自动完成一系列动作如搬运、排序、写字。升级主控使用STM32、ESP32等性能更强的控制器可以运行更复杂的算法如闭环PID控制并连接更多传感器。6. 项目总结与最佳实践通过这个70元迷你机械臂项目你实践了从机械设计、电子电路到软件编程的完整机器人开发流程。回顾整个过程以下几点对于成功至关重要机械是基础结构件的精度和刚性直接决定最终性能。在设计和组装阶段多花时间确保转动顺滑、连接牢固、重心合理。使用轴承、垫片等可以大幅提升运动品质。供电是保障舵机是“电老虎”独立、足额、稳定的电源是系统稳定运行的前提。切勿在供电上妥协。校准是关键舵机的“0度”和“180度”是理论值必须通过物理校准找到对应的精确脉冲宽度。为每个舵机建立校准参数表并保存在程序或EEPROM中。软件要稳健在程序开头进行全面的初始化舵机归中、设置频率。为所有关节角度设置软件限位防止物理碰撞。实现平滑的运动轨迹保护舵机齿轮。添加串口指令解析和错误处理方便调试和控制。从简单开始迭代升级不要一开始就追求复杂的多自由度和视觉识别。先让三自由度机械臂稳定地完成平面抓取然后再逐步增加传感器、改进算法、更换执行器。每完成一个小的功能迭代都能带来巨大的成就感并加深对原理的理解。这个项目最大的价值不在于做出了一个多么强大的机械臂而在于你亲手打通了“想法 - 设计 - 制造 - 控制 - 调试”的完整链路。这套方法论和实践中积累的经验是任何现成玩具都无法给予的。接下来你可以尝试为它编写一个图形化控制界面或者挑战让它完成一个简单的自动化任务例如将散落的积木块分类放到不同的区域。
返回列表