← 返回实战项目

桌面机械臂:多舵机协调抓取小物件

最后更新 2026-07-01
⏱ 约 20 分钟 🟡 涉接线/强电
你将学到
  • 做出一台四到六自由度、能抓起橡皮/瓶盖这类小物的桌面机械臂
  • 把多舵机驱动(PCA9685)和角度控制两个单练的知识点接成一条完整的“抓取动作链”
  • 学会正确接线:PCA9685 走 I2C、舵机走独立 5V、全系统共地,避开供电拖垮主控的坑
  • 用 ESP-IDF 分三步长出代码:控单舵机 → 多舵机协调插值 → 摇杆/预设动作抓取
  • 想清一台多舵机设备“同时要动几个关节”时,动作该怎么组织、怎么排上电顺序
🛒 器材清单
器材数量参考
4-6 自由度机械臂支架(金属或亚克力套件,含舵机位)1 套约 50-120 元(以商城实际为准)
舵机(SG90 小力矩练手,或 MG996R 金属齿带得动负载)4-6SG90 约 5-10 元/个、MG996R 约 15-30 元/个(以商城实际为准)
PCA9685 16 路 PWM/舵机驱动模块1约 8-18 元(以商城实际为准)
独立 5V 大电流电源(适配器 5V/3A 以上,或足够的电池组)1约 15-40 元(以商城实际为准)
电位器或双轴摇杆模块(做手动遥控用)1-2约 2-8 元(以商城实际为准)
ESP32-S3 开发板 + 杜邦线若干1 套约 25-45 元(以商城实际为准)

价格随渠道波动,以购买页实时为准。

桌上摆着一只巴掌高的小机械臂。你推一下摇杆,它的底座缓缓转过去,大臂放下、小臂探出,夹爪张开对准一块橡皮,轻轻一合——夹住了;你再一推,它把橡皮拎起来、转个方向、松开,稳稳放到另一边。没有电脑连着,没有 App,一根摇杆就把六个关节指挥明白了。这就是这个项目要带你做出来的东西。

它不是玩具展示,是你第一次把两件事真正拧成一股绳:用 PCA9685 一次驱动一堆舵机,和让这些舵机按先后、按节奏协调着动出一个有意义的抓取。之前你在 舵机入门让单个舵机听话地转到某个角度,在 用 PCA9685 一次驱动 16 个舵机解决了“多舵机怎么接、怎么供电不重启”,但那还只是让它们“一个个轮流动”。这一篇把它们组织成一台能干活的机械臂——这个“组织”,就是 project 比前面那些知识点多出来的一层功夫。

这篇不重复讲 PCA9685 的 I2C 原理、脉宽换算——那些 robot-servo-pca9685 已经讲透,这里默认你跑通过“让多个舵机依次扫动”那一步。我们只干一件事:把它拼成一台会抓东西的机械臂,讲清拼的过程里那些单看一个舵机时看不到的坑。

⚠️ 安全

多舵机机械臂,电和手是两条命门,先钉死再动手:

  • 舵机电源必须走独立 5V,绝不从开发板取电。 一个 MG996R 堵转(转不动还硬顶)瞬时电流能冲过 1A,四到六个同时启动或同时堵转就是好几安培。你要是图省事把舵机正极接到板子的 5V/VIN,稳压器供不出这么大电流,电压被瞬间拉垮,主控欠压复位——现象就是机械臂一动板子就重启,查一晚上代码其实一行没错,是电不够。容量按「舵机数 × 单个堵转电流」估,六个 MG996R 至少备 5V/6A。
  • 独立 5V 电源的地,必须和 ESP32 的 GND 接到一起(共地)。 不共地,I2C 电平没有共同参考,命令根本发不进 PCA9685,舵机不动,严重时还会烧逻辑。
  • 机械臂运动会夹手、会甩。 上电瞬间通道是随机历史值,臂会猛弹一下,别把手、脸、桌上易碎物放在扫动范围里;调试时把电源开关攥在手边,一见姿态失控立刻断电。夹爪合拢力气不小,别拿它夹手指试。
  • 别让舵机长时间硬顶机械极限。 堵转既烧舵机也烧驱动板,代码里务必给每个关节做角度钳位,别让它撞到结构死点还在使劲。

第一步:想清楚要做成什么样,再定选型

动手前先把“成品长什么样”钉死,选型才有依据。我们的机械臂就一条主线行为:把一个小物件从 A 点抓起、搬到 B 点、放下。 拆开来是四个自由度起步:

  • 底座旋转:整条臂左右转,决定抓取方向。
  • 大臂俯仰:控制臂伸出去的远近高低。
  • 小臂俯仰:配合大臂让末端够到目标。
  • 夹爪开合:张开对准、合拢夹住。

想更灵活可以加到六个(多一个手腕俯仰、一个手腕旋转),但先用四个把整条链路跑通,多的自由度是锦上添花,不是入门必需。行为定了,选型每一步就都有理由。

舵机:SG90 还是 MG996R?

这是你要做的第一个取舍:

SG90(塑料齿) MG996R(金属齿)
力矩 小,约 1.5kg·cm 大,约 10kg·cm
带负载 只能带很轻的臂和小物 能带得动金属臂+像样的负载
价格 便宜一半以上 略贵
发热/堵转 堵转电流小些 堵转电流大,供电要求更高
适合 纯练手、轻质亚克力臂 想真抓点有分量的东西

一句话决策:纯练逻辑、臂很轻,用 SG90 便宜省事;想让它真夹起有点分量的东西、臂是金属的,底座和大臂这两个吃力的关节至少上 MG996R。 常见做法是混搭——吃力的大臂、底座用 MG996R,末端的小臂、夹爪用 SG90 减重。它们的控制接口完全一样(都是 50Hz PWM、脉宽定角度),代码一个字不用改,只是脉宽边界可能各自微调。

为什么必须用 PCA9685,不直接用 ESP32 的 GPIO

你可能想:ESP32-S3 的 LEDC 不是有 PWM 吗,直接生成四路舵机信号不行?会撞两堵墙,这也是 robot-servo-pca9685 讲透的:

  1. 通道和定时器排布别扭。LEDC 要给每路都配 50Hz 低频又保证脉宽分辨率,四路以上排起来乱,还要占用宝贵的定时器资源。
  2. 更致命的是供电——但这堵墙其实不是 PCA9685 “算力”解决的,是它把舵机电源引到独立的 V+ 端子、和逻辑电源彻底分家解决的。

PCA9685 的真正价值是把「控制」和「供电」分了家:控制走 I2C 两根线(主控只发命令),供电走独立 5V 灌进 V+。主控只动嘴皮子,重活它不碰。做机械臂、六足、人形,这是标准做法,不是可选项。


第二步:接线——四类线,避开雷区

这是整个项目最容易翻车的地方,照着来。分四类:控制线、逻辑供电、舵机独立供电、舵机信号。

控制侧(ESP32-S3 ↔ PCA9685,走 I2C):

PCA9685 引脚 接到 ESP32-S3 作用
VCC 3.3V 芯片逻辑供电,不是给舵机的
GND GND 逻辑地
SDA GPIO8(以你板子丝印为准) I2C 数据
SCL GPIO9(以你板子丝印为准) I2C 时钟
🚧 避坑

ESP32-S3 的 I2C 引脚可以软件指定,但选脚仍有雷区,接线前对照排除:

  • GPIO0 / 3 / 45 / 46:strapping 脚,上电电平决定启动模式,接了外设可能刷不进、起不来;
  • GPIO26-37:绝大多数模组内部连着 SPI flash / PSRAM,动了直接死机;
  • GPIO19 / 20:默认 USB D-/D+,占用会断掉 USB 串口,日志都看不到;
  • GPIO22 / 23 / 24 / 25:S3 上根本不存在这几个号(GPIO 号从 21 直接跳到 26,中间是空的),写了编译不报错、运行时行为诡异。

GPIO8 / GPIO9 都在安全区,本项目用它俩做 I2C。你板子丝印标了别的 SDA/SCL 就跟丝印走,代码里 i2c_master 初始化时填对应号即可。

舵机独立供电侧(关键,别接错):

  • PCA9685 的 V+ 端子接独立 5V 电源正极(5V/3A 以上适配器,或足够的电池组)。这路专喂舵机。
  • 这个 5V 电源的地,必须和 ESP32 的 GND 接到一起——这就是共地。不共地 I2C 不工作。
  • 别把 V+ 和 VCC 搞混:VCC 是给芯片逻辑的 3.3V,V+ 才是给舵机的 5V 大电流。接反了要么舵机不动,要么烧板。

舵机信号侧:

  • 每个舵机的三根线(信号/正/负)直接插 PCA9685 对应通道的排针,有防呆方向,黑(或棕)线朝 GND 那一侧,别插反。
  • 通道分配建议固定下来,代码里对应:底座=0、大臂=1、小臂=2、夹爪=3(加自由度就 4、5 顺延)。

接线拓扑一眼图:

ESP32-S3 ──GPIO8(SDA)/GPIO9(SCL)──▶ PCA9685 (VCC←3.3V, GND←共地)
                                        │
独立 5V 电源 ──(+)──▶ V+ 端子           ├─ 通道0 ── 底座舵机
             ──(−)──┐                   ├─ 通道1 ── 大臂舵机
                    │                   ├─ 通道2 ── 小臂舵机
ESP32-S3 GND ───────┴─ 共地             └─ 通道3 ── 夹爪舵机

记住这条铁律:舵机的电永远从 V+ 那路独立电源来,绝不从主控取;所有地必须共到一起。


第三步:分步把代码写出来

我们不一次甩一大段,而是分三步长出来,每步都能单独烧进去看到效果——出问题时你才知道是哪一步坏的。这里用 ESP-IDF 原生的 i2c_master 直接跟 PCA9685 通信(不依赖 Arduino 库),把寄存器怎么配讲清楚。

步 1:先让一个舵机通过 PCA9685 转起来

第一步只验证一件事:I2C 通了、PCA9685 认到了、50Hz 配对了、单个舵机能到位。PCA9685 的核心就三步:设分频得到 50Hz、往某通道的 4 个寄存器写“开始/结束计数”、角度换算成计数值。

#include "driver/i2c_master.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_log.h"

static const char *TAG = "arm";

#define I2C_PORT     I2C_NUM_0
#define PIN_SDA      GPIO_NUM_8      // 避开雷区,以丝印为准
#define PIN_SCL      GPIO_NUM_9
#define PCA9685_ADDR 0x40            // 一块板不焊地址跳线就是 0x40

// PCA9685 寄存器
#define REG_MODE1      0x00
#define REG_PRESCALE   0xFE
#define REG_LED0_ON_L  0x06         // 通道 0 的第一个寄存器,每通道占 4 个

// 舵机参数:50Hz 周期 20ms;脉宽 500us=0°,2500us=180°(不同舵机后面校准)
#define SERVO_FREQ    50
#define SERVO_MIN_US  500
#define SERVO_MAX_US  2500

static i2c_master_dev_handle_t s_dev;

static void pca_write(uint8_t reg, uint8_t val)
{
    uint8_t buf[2] = { reg, val };
    ESP_ERROR_CHECK(i2c_master_transmit(s_dev, buf, sizeof(buf), 100));
}

// 设某通道的 PWM:on 一般给 0,off 是脉宽对应的计数值(0~4095)
static void pca_set_pwm(uint8_t ch, uint16_t off)
{
    uint8_t base = REG_LED0_ON_L + 4 * ch;
    uint8_t buf[5] = { base, 0x00, 0x00, (uint8_t)(off & 0xFF), (uint8_t)(off >> 8) };
    ESP_ERROR_CHECK(i2c_master_transmit(s_dev, buf, sizeof(buf), 100));
}

// 微秒脉宽 → 12 位计数:一个 20000us 周期切成 4096 份
static uint16_t us_to_ticks(int us)
{
    return (uint16_t)((long)us * 4096 / 20000);
}

// 给某通道设角度(带钳位,防止顶到机械极限)
static void set_angle(uint8_t ch, int deg)
{
    if (deg < 0)   deg = 0;
    if (deg > 180) deg = 180;
    int us = SERVO_MIN_US + (SERVO_MAX_US - SERVO_MIN_US) * deg / 180;
    pca_set_pwm(ch, us_to_ticks(us));
}

static void pca_init(void)
{
    i2c_master_bus_config_t bus = {
        .i2c_port = I2C_PORT,
        .sda_io_num = PIN_SDA,
        .scl_io_num = PIN_SCL,
        .clk_source = I2C_CLK_SRC_DEFAULT,
        .glitch_ignore_cnt = 7,
        .flags.enable_internal_pullup = true,   // 模块通常自带上拉,这里再兜个底
    };
    i2c_master_bus_handle_t bus_h;
    ESP_ERROR_CHECK(i2c_new_master_bus(&bus, &bus_h));

    i2c_device_config_t dev = {
        .dev_addr_length = I2C_ADDR_BIT_LEN_7,
        .device_address = PCA9685_ADDR,
        .scl_speed_hz = 400000,      // 400kHz 快速模式
    };
    ESP_ERROR_CHECK(i2c_master_bus_add_device(bus_h, &dev, &s_dev));

    // 设 50Hz:prescale = round(25MHz / (4096 * 50)) - 1 = 121
    pca_write(REG_MODE1, 0x10);               // 先进 sleep 才能改 prescale
    pca_write(REG_PRESCALE, 121);             // 50Hz
    pca_write(REG_MODE1, 0x00);               // 唤醒
    vTaskDelay(pdMS_TO_TICKS(5));             // 唤醒后等振荡器稳
    pca_write(REG_MODE1, 0xA0);               // 开自动递增 + 重启
}

void app_main(void)
{
    pca_init();
    ESP_LOGI(TAG, "PCA9685 就绪,测试底座舵机(通道0)");

    while (1) {
        set_angle(0, 60);  vTaskDelay(pdMS_TO_TICKS(800));
        set_angle(0, 120); vTaskDelay(pdMS_TO_TICKS(800));
        set_angle(0, 90);  vTaskDelay(pdMS_TO_TICKS(800));
    }
}

烧进去 idf.py build flash monitor你应该看到:串口打出“PCA9685 就绪”,底座那个舵机在 60°、120°、90° 之间稳稳来回转,主控不重启。看到这个,说明 I2C 通路、50Hz 配置、供电分离三件事全对——这一步的意义就是把最容易错的地方先隔离验证掉。

这里把 set_angle(ch, deg) 封成一个函数,后面所有动作全靠它,不再到处手写换算。为什么?因为机械臂要在几十处改角度,每处都手写脉宽换算既啰嗦又容易错。封一次,后面只调 set_angle这就是从「跑通例子」到「写成品」的第一个思维转变:把易错、重复的换算收进函数。

步 2:多舵机协调——平滑插值,别一步到位

现在把四个舵机都接上,让它们协调地、平滑地动到一组目标角度,而不是各自“啪”地弹过去。机械臂最忌讳一步到位——猛地弹过去既甩得厉害、又容易撞坏结构、瞬时电流也大。做法是插值:把当前角度到目标角度分成很多小步,每步动一点点。

// 四个关节的当前角度,全局记着
static int g_pose[4] = {90, 90, 90, 90};   // 底座/大臂/小臂/夹爪,上电居中

// 把整条臂平滑移动到一组目标姿态。step 越小越顺滑,delay 越大越慢
static void move_to(const int target[4], int step, int delay_ms)
{
    bool moving = true;
    while (moving) {
        moving = false;
        for (int i = 0; i < 4; i++) {
            if (g_pose[i] < target[i]) {
                g_pose[i] += step;
                if (g_pose[i] > target[i]) g_pose[i] = target[i];
                moving = true;
            } else if (g_pose[i] > target[i]) {
                g_pose[i] -= step;
                if (g_pose[i] < target[i]) g_pose[i] = target[i];
                moving = true;
            }
            set_angle(i, g_pose[i]);
        }
        vTaskDelay(pdMS_TO_TICKS(delay_ms));
    }
}

void app_main(void)
{
    pca_init();
    // 上电先让每个关节都回到已知的居中姿态,避免从随机位置猛弹
    for (int i = 0; i < 4; i++) set_angle(i, g_pose[i]);
    vTaskDelay(pdMS_TO_TICKS(500));
    ESP_LOGI(TAG, "开始多关节协调动作");

    // 两组姿态之间来回:伸出去 / 收回来
    int reach[4] = {60,  120, 60,  90};   // 底座偏左、大臂放下、小臂探出、夹爪半开
    int home[4]  = {90,  90,  90,  90};

    while (1) {
        move_to(reach, 2, 15);   // 2° 一步、每步 15ms,肉眼看着很顺
        vTaskDelay(pdMS_TO_TICKS(600));
        move_to(home,  2, 15);
        vTaskDelay(pdMS_TO_TICKS(600));
    }
}

你应该看到:四个关节同时、平滑地从居中姿态过渡到“伸出去”那组角度,停一下再一起收回来,全程动作绵软不甩、主控不重启。step 调大动作更快更急,delay_ms 调大更慢更稳——想要什么手感自己试。

move_to 的精髓是让所有关节一起逼近各自的目标、谁先到谁停住。为什么不能一个关节动完再动下一个?那样臂是“折线式”地一节一节挪,既慢又难看,中间还可能撞到桌面。让它们并行插值,整条臂就是一个协调的整体在移动——这是多舵机设备的第二个成品级思维:多个执行器不是轮流动,是配着一起动。

步 3:接上摇杆,或跑预设动作,完成一次真抓取

最后一步把“抓取”做出来。给你两条路,任选或都做:

路 A:预设动作序列(无需额外硬件,先跑通抓取逻辑)。 把一次完整抓取拆成几帧姿态,按顺序 move_to 过去:

// 一次完整抓取:对准 → 下探 → 合爪 → 提起 → 转向 → 松爪 → 复位
static void grab_sequence(void)
{
    // 夹爪:60=张开,130=合拢夹紧(按你的夹爪结构调)
    int aim[4]    = {60, 100, 70, 60};    // 转向目标、探到物件上方、爪张开
    int down[4]   = {60, 120, 60, 60};    // 大臂再放下一点,够到物件
    int grip[4]   = {60, 120, 60, 130};   // 只动夹爪:合拢夹住
    int lift[4]   = {60, 90,  90, 130};   // 抬起来,夹着不松
    int turn[4]   = {120, 90, 90, 130};   // 底座转到 B 点上方
    int release[4]= {120, 90, 90, 60};    // 松爪放下
    int home[4]   = {90, 90, 90, 90};

    move_to(aim,    2, 15); vTaskDelay(pdMS_TO_TICKS(300));
    move_to(down,   1, 20); vTaskDelay(pdMS_TO_TICKS(300));  // 下探用更小步长,更稳
    move_to(grip,   2, 25); vTaskDelay(pdMS_TO_TICKS(400));  // 合爪慢一点,夹稳
    move_to(lift,   2, 15); vTaskDelay(pdMS_TO_TICKS(300));
    move_to(turn,   2, 15); vTaskDelay(pdMS_TO_TICKS(300));
    move_to(release,2, 20); vTaskDelay(pdMS_TO_TICKS(300));
    move_to(home,   2, 15); vTaskDelay(pdMS_TO_TICKS(800));
}

路 B:摇杆手动遥控。 用一个双轴摇杆(本质是两个电位器)控底座和大臂,另一个电位器或按键控夹爪。摇杆的两轴接 ESP32-S3 的 ADC 脚(选支持 ADC1 的安全脚,比如 GPIO4/5),读到的模拟值映射成角度:

#include "esp_adc/adc_oneshot.h"

// 假设摇杆 X 轴接 ADC1 通道,读值 0~4095 映射到底座 0~180°
static adc_oneshot_unit_handle_t s_adc;

static void joystick_init(void)
{
    adc_oneshot_unit_init_cfg_t ucfg = { .unit_id = ADC_UNIT_1 };
    ESP_ERROR_CHECK(adc_oneshot_new_unit(&ucfg, &s_adc));
    adc_oneshot_chan_cfg_t ccfg = { .atten = ADC_ATTEN_DB_12, .bitwidth = ADC_BITWIDTH_DEFAULT };
    ESP_ERROR_CHECK(adc_oneshot_config_channel(s_adc, ADC_CHANNEL_3, &ccfg)); // 以你的脚为准
}

static void joystick_task(void *arg)
{
    while (1) {
        int raw = 0;
        adc_oneshot_read(s_adc, ADC_CHANNEL_3, &raw);
        int deg = raw * 180 / 4095;          // 0~4095 线性映射到 0~180°
        // 加一点死区/平滑,摇杆中位附近别抖(这里从略,进阶再优化)
        set_angle(0, deg);                    // 实时控底座
        g_pose[0] = deg;
        vTaskDelay(pdMS_TO_TICKS(20));        // 50Hz 刷新,跟舵机节奏一致
    }
}

你应该看到:路 A 下,机械臂自己走完“对准→下探→夹住→提起→转向→松开→复位”一整套,真能把桌上一块橡皮从左边搬到右边;路 B 下,你推摇杆哪个方向,对应关节就跟着实时转,像遥控挖掘机那样手动去够、去夹。

到这里核心功能全齐了。回头看,你没写多少新东西:I2C 和脉宽换算是 robot-servo-pca9685 的,ADC 读摇杆是外设课的,你干的是用插值把多个舵机组织成协调动作、再把动作串成一次抓取——这个“组织动作”,就是机械臂比“驱动舵机”多出来的那层功夫。


第四步:调试——对不上就查这张表

分步烧的好处是,哪一步出问题你已经缩小了范围。真出了岔子,照这张表查:

现象 最可能的原因 怎么办
舵机抖动、嗡嗡响、不停微动 独立 5V 电流不足或电压不稳 / 共地不良 换更大电流的独立电源;确认独立电源地和主控地真的共到一起;线材太细换粗
一让多个关节动主控就重启 舵机在从主控取电,把主控拖欠压 舵机供电走独立 V+,绝不从主控 5V/VIN 取;确认共地;见 safety 框第一条
舵机完全不动、串口正常 V+ 没接独立电源,或接到了 VCC V+ 必须接独立 5V,VCC 只是 3.3V 逻辑供电,两者别搞混
串口报 I2C 找不到设备 / 卡住 SDA/SCL 接反、地址不对、没上拉 核对 SDA/SCL 和板子丝印;确认地址 0x40(没焊跳线);模块通常自带上拉,没有就补
某关节角度不准、0° 不到位或过头 该型号舵机脉宽边界和 500/2500us 不一致 微调该舵机的 SERVO_MIN_US/SERVO_MAX_US,逐个试到位;混装 SG90/MG996R 时更要分开校
上电瞬间机械臂猛甩一下 通道是随机历史值 pca_init 后先把每个关节 set_angle 到居中姿态再开始动作(步 2 已这么做)
动作到某处“咔咔”响、卡住 目标角度顶到了机械死点 缩小该关节的角度范围,别让它撞结构;给 set_angle 之外再加一层每关节的安全上下限
夹爪夹不住 / 夹太狠变形 合拢角度不对 逐度试出“刚好夹紧”那个角度,别直接给 180°,夹爪结构受力大
插值动作一顿一顿不平滑 step 太大或 delay_ms 太小被任务抢占 减小 step(如 1°)、适当加 delay_ms;别把重活塞进动作循环
💡 提示

一次只改一处再烧。同时改三个关节的角度、臂还是不对,你根本分不清是哪个改动的锅。分步烧、单点改,是硬件调试省时间的铁律。调机械臂尤其如此——先单独把每个关节的“到位角度”一个个校准好记下来,再拼进动作序列。


第五步:从“能抓”到“抓得准、抓得聪明”

到这它已经是台能抓东西的机械臂了。但“能抓”和“抓得准、抓得稳”之间还差几步——正好通向后面的阶梯,先给你指条路。

让它抓向空间里的某个点:逆运动学

现在你是手动一个个试关节角度凑出抓取姿态。真正的机械臂要的是:告诉它“去抓桌面上 (x, y, z) 那个点”,它自己算出每个关节该转多少度。这个“从末端位置反算关节角度”的过程叫逆运动学,是机械臂从“摆造型”升级到“按坐标干活”的分水岭。这块硬骨头单开了一篇:机械臂运动学,学完你就能让夹爪精确落到指定坐标,而不是手动试角度。

让动作更稳、更可控:进阶风控与冗余

多舵机、有机械运动的设备,一旦规模化或长时间运行,要考虑的就不只是“能动”了:舵机堵转保护、供电冗余、异常姿态的软件限位、断电保持。这些“让设备在意外情况下也不失控”的思路,属于 机器人专题卷 R 那条更深的线——机械臂正是把这些风控概念落到实处的好载体。等你多做几个动作项目、手感稳了,再顺着 R4 往下啃,把“能抓”做成“怎么抓都不出事”。

做成能天天用的实体

面包板一团线、电源裸接只能算原型。想变成能摆桌上、能演示、甚至能干点真活的东西,要走产品化那条路:稳定供电、走线收纳、给舵机加限位缓冲、外壳固定。这些经验在做过几个项目后自然会想补,机械臂是最值得留着反复打磨的一个。


小结 · 你做出了什么、下一步去哪

  • 你做出了一台四到六自由度、能把小物件从 A 抓到 B 的桌面机械臂,从舵机选型、独立供电避雷区接线、分步写 ESP-IDF 码到调试校准,走完了一件多舵机成品的全流程。
  • 你把 PCA9685 多舵机驱动robot-servo-pca9685)和单舵机角度控制l2-servo)两个知识点,用插值 + 姿态序列组织成了协调的抓取动作——这个“组织多个执行器一起动”的功夫,就是机械臂比“驱动舵机”多出来的那一层。
  • 你学到了几个从 demo 到成品的关键思维:把易错的换算封进函数、多关节并行插值而非轮流动、上电先回已知姿态、每个关节都做角度钳位防撞死点、供电永远独立且共地。

下一步:想让它“按坐标抓”而不是手动试角度,去啃 机械臂运动学;想让多舵机设备在意外下也不失控,顺着 机器人专题卷 R 往深走;想系统看这台机械臂和其它机器人项目的关系,去 机器人专题 逛一圈。回看全部实战项目见项目总览。这台机械臂是你所有硬件项目里最有“成就感落差”的一个——从一堆乱动的舵机,到它稳稳夹起第一块橡皮的那一刻,你会明白“组织”二字的分量。

📄 来源 / 自校链接

本文为公开资料整理,非亲测。关键参数与代码请结合实物与下列官方来源验证。

内容有错、看不懂、或想看下一期?告诉我们 →

本文为公开资料的学习整理,非亲测。涉接线/花钱/合规的步骤请结合实物与官方最新资料验证,风险自负。见免责声明