ESP32 5自由度机械臂制作实录:从硬件到代码的完整旅程

前言

最近我完成了一个基于ESP32的5自由度机械臂控制系统,这个项目结合了硬件设计和软件开发,让我深入学习了ESP-IDF框架、舵机控制、运动学计算以及Web界面开发等多方面知识。今天想和大家分享这个项目的制作过程和关键技术点。

项目概述

这是一个基于ESP32-WROOM和PCA9685的5自由度机械臂控制系统,使用ESP-IDF框架开发。机械臂结构参考了一个开源项目,系统支持Web界面控制、学习模式和路径管理功能。

硬件准备

主要组件

  • ESP32-WROOM开发板(大脑)
  • PCA9685 16通道PWM控制器(控制舵机)
  • 5个舵机(1个MG996R底座舵机,3个关节舵机,1个SG90夹爪舵机)
  • 5V/2A电源(舵机需要足够电流)
  • 结构件(开源项目 https://www.youtube.com/watch?v=5toNqaGsGYs)

组装过程

  1. 首先组装机械臂结构,将各关节舵机固定到相应位置
  2. 连接ESP32和PCA9685:GPIO21→SDA,GPIO22→SCL
  3. 将舵机按顺序连接到PCA9685的通道0-4
  4. 为舵机提供单独的5V电源(舵机耗电大,不能直接使用ESP32供电)

软件架构设计

项目采用组件化设计,主要包含以下几个组件:

  1. pca9685:负责与PCA9685芯片通信,生成PWM信号
  2. servo_controller:舵机控制抽象层,处理角度转换和平滑移动
  3. robotic_arm:机械臂控制核心,包含运动学计算
  4. learning_controller:实现路径学习和回放功能
  5. web_controller:提供Web界面和WiFi连接功能

关键技术点解析

1. I2C通信与PCA9685驱动

PCA9685是通过I2C总线控制的,ESP32作为主机需要初始化I2C总线并与PCA9685通信:

// I2C初始化
i2c_config_t conf = {
    .mode = I2C_MODE_MASTER,
    .sda_io_num = I2C_SDA_PIN,
    .scl_io_num = I2C_SCL_PIN,
    .sda_pullup_en = GPIO_PULLUP_ENABLE,
    .scl_pullup_en = GPIO_PULLUP_ENABLE,
    .master.clk_speed = I2C_FREQ_HZ
};
i2c_param_config(I2C_NUM_0, &conf);
i2c_driver_install(I2C_NUM_0, conf.mode, 0, 0, 0);

2. 舵机控制算法

舵机控制需要将角度转换为适当的PWM脉冲宽度,并实现平滑移动:

// 角度到脉冲宽度的转换
uint16_t servo_angle_to_pulse(servo_config_t *config, float angle) {
    if (angle < config->min_angle) angle = config->min_angle;
    if (angle > config->max_angle) angle = config->max_angle;
    
    return config->min_pulse + (angle - config->min_angle) * 
           (config->max_pulse - config->min_pulse) / 
           (config->max_angle - config->min_angle);
}

3. 正逆运动学计算

机械臂的运动学计算是核心难点,需要实现:

  • 正运动学:根据关节角度计算末端位置
  • 逆运动学:根据末端位置计算各关节角度
// 逆运动学示例(简化版)
bool inverse_kinematics(float x, float y, float z, float *base, float *shoulder, float *elbow) {
    // 计算底座角度
    *base = atan2(y, x) * RAD_TO_DEG;
    
    // 计算到末端的距离
    float r = sqrt(x*x + y*y) - WRIST_LENGTH;
    float d = sqrt(r*r + (z-BASE_HEIGHT)*(z-BASE_HEIGHT));
    
    // 检查是否超出机械臂的工作范围
    if (d > ARM_LENGTH + FOREARM_LENGTH || d < fabs(ARM_LENGTH - FOREARM_LENGTH)) {
        return false; // 位置不可达
    }
    
    // 使用余弦定理计算肩部和肘部角度
    float cos_elbow = (ARM_LENGTH*ARM_LENGTH + FOREARM_LENGTH*FOREARM_LENGTH - d*d) / 
                      (2 * ARM_LENGTH * FOREARM_LENGTH);
    *elbow = (180.0f - acos(cos_elbow) * RAD_TO_DEG);
    
    // 计算肩部角度
    float beta = acos((ARM_LENGTH*ARM_LENGTH + d*d - FOREARM_LENGTH*FOREARM_LENGTH) / 
                     (2 * ARM_LENGTH * d)) * RAD_TO_DEG;
    *shoulder = atan2(z-BASE_HEIGHT, r) * RAD_TO_DEG + beta;
    
    return true;
}

4. Web界面与WebSocket实时通信

Web界面使用HTML/CSS/JavaScript实现,与ESP32通过WebSocket通信,实现实时控制:

// WebSocket连接示例
const socket = new WebSocket(`ws://${window.location.hostname}/ws`);
socket.onopen = function() {
    console.log("WebSocket连接已建立");
};
socket.onmessage = function(event) {
    const data = JSON.parse(event.data);
    updateServoPositions(data);
};

// 发送控制命令
function sendServoCommand(servoId, angle) {
    socket.send(JSON.stringify({
        type: "servo_control",
        servo: servoId,
        angle: angle
    }));
}

5. 学习模式与路径存储

学习模式使用NVS(Non-Volatile Storage)保存路径数据:

// 将路径保存到NVS
esp_err_t save_path_to_nvs(int path_index, servo_path_t *path) {
    nvs_handle_t nvs_handle;
    esp_err_t err = nvs_open("servo_paths", NVS_READWRITE, &nvs_handle);
    if (err != ESP_OK) return err;
    
    char key[16];
    sprintf(key, "path_%d", path_index);
    
    // 保存路径元数据
    nvs_set_u16(nvs_handle, key, path->point_count);
    
    // 保存各个路径点
    for (int i = 0; i < path->point_count; i++) {
        char point_key[32];
        sprintf(point_key, "path_%d_p%d", path_index, i);
        nvs_set_blob(nvs_handle, point_key, &path->points[i], sizeof(servo_point_t));
    }
    
    nvs_commit(nvs_handle);
    nvs_close(nvs_handle);
    return ESP_OK;
}

制作过程中的挑战与解决方案

1. 舵机抖动问题

舵机在静止状态下仍有抖动,影响精度。

解决方案

  • 调整PWM频率至50Hz
  • 实现舵机平滑移动算法,通过小步进移动
  • 添加死区判断,微小角度变化不驱动舵机

2. 运动学计算精度问题

初期机械臂运动不精确,特别是在某些位置。

解决方案

  • 精确测量每个连杆的实际长度
  • 对舵机进行校准,确定实际的最小/最大脉宽
  • 修正运动学模型中的偏移量

后续改进计划

  1. 添加基于摄像头的视觉识别功能
  2. 实现更复杂的路径规划算法
  3. 开发手机APP控制界面
  4. 添加语音控制功能

这个项目既有挑战性又很有成就感,希望我的分享能对有兴趣开发类似项目的朋友有所帮助!
开源地址:https://github.com/1730490023/ESP32_WROOM_IDF_Rebot_wifi.git

Logo

DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。

更多推荐