← 返回DIY实践首页

🚀 第四章:完整项目

Complete Projects — 从图纸到成品

三个实战项目,三个难度等级

💡 学习路径:不要一上来就做人形机器人。先从简单的机械臂开始,掌握基本原理,再逐步升级。每个项目都是前一个的进阶。

项目总览

项目难度预算时间学到的核心技能
🦾 桌面机械臂Level 1-2~300元1-2周舵机控制、逆运动学、串口通信
🦿 双足步行Level 2-3~800元2-4周步态规划、平衡控制、IMU使用
🤖 小型人形Level 3-4~3000元1-3个月系统集成、视觉、ROS、高级控制

🎯 选择建议

  • 学生入门:从桌面机械臂开始,预算低、周期短、成功率高
  • 有基础后:挑战双足步行,学习平衡控制
  • 工程师进阶:小型人形机器人,综合性最强

项目一:桌面机械臂 🦾

Level 1-2 · 入门级

4自由度桌面机械臂

一个经典的入门项目,使用4个舵机实现基座旋转、肩关节、肘关节、夹爪控制。通过串口或手机App控制,可完成抓取、搬运等任务。

项目特点

BOM清单(物料清单)

类别名称规格数量参考价备注
舵机MG996R20kg·cm扭矩3个15×3=45元肩/肘关节
SG901.8kg·cm1个3元夹爪
舵机支架铝合金U型4套20元连接舵机
舵机盘十字/圆盘4个5元随舵机附赠
控制Arduino UnoATmega328P1块25元主控
PCA968516路PWM扩展1块12元舵机驱动
HC-05蓝牙串口透传1个10元手机控制(可选)
电源5V开关电源5V/5A1个15元舵机供电
DC插座5.5×2.1mm1个1元电源接口
结构3D打印件PLA/PETG约200g~30元自行打印或淘宝代打
其他螺丝螺母M2/M3/M4若干5元紧固
总计~170元不含3D打印机

机械设计

自由度分配

机械臂自由度示意: ┌───┐ │夹爪│ ← 关节4:开合(SG90) └─┬─┘ │ ┌──┴──┐ │ 关节3│ ← 肘关节(MG996R) └──┬──┘ │小臂 ┌──┴──┐ │ 关节2│ ← 肩关节(MG996R) └──┬──┘ │大臂 ┌──┴──┐ │ 关节1│ ← 基座旋转(MG996R) └──┬──┘ │ ═══╧═══ 底座 工作空间:基座旋转±180°,半径约200mm

3D打印件清单

💡 STL文件获取

推荐开源项目"Arduino Robot Arm"(Thingiverse/Printables搜索),或自行用Fusion 360/SolidWorks设计。本知识库后续会提供配套图纸。

电路连接

电路接线图: ┌─────────────────────────────────────────────┐ │ PCA9685 │ │ VCC ──────→ Arduino 5V │ │ GND ──────→ Arduino GND │ │ SDA ──────→ Arduino A4 │ │ SCL ──────→ Arduino A5 │ │ │ │ PWM0 ─────→ 舵机1信号(基座) │ │ PWM1 ─────→ 舵机2信号(肩关节) │ │ PWM2 ─────→ 舵机3信号(肘关节) │ │ PWM3 ─────→ 舵机4信号(夹爪) │ │ │ │ V+ ──────→ 外部5V电源(红线) │ │ GND ──────→ 外部电源地(黑线) │ └─────────────────────────────────────────────┘ ⚠️ 注意:舵机电源必须外接,不能用Arduino供电!

Arduino代码

// 桌面机械臂控制程序 - Arduino
// 硬件:Arduino Uno + PCA9685 + 4个舵机

#include <Wire.h>
#include <Adafruit_PWMServoDriver.h>

Adafruit_PWMServoDriver pwm = Adafruit_PWMServoDriver();

// 舵机参数(根据实际舵机调整)
#define SERVOMIN  150   // 0°脉宽
#define SERVOMAX  600   // 180°脉宽

// 舵机通道
#define BASE_SERVO     0  // 基座
#define SHOULDER_SERVO 1  // 肩关节
#define ELBOW_SERVO    2  // 肘关节
#define GRIPPER_SERVO  3  // 夹爪

// 当前角度
float angles[4] = {90, 90, 90, 90};

void setup() {
    Serial.begin(115200);
    pwm.begin();
    pwm.setPWMFreq(50);  // 50Hz
    
    // 初始化到中位
    setAllServos(90, 90, 90, 90);
    Serial.println("Robot Arm Ready!");
    Serial.println("Commands: B(angle) S(angle) E(angle) G(angle)");
}

void loop() {
    // 串口命令解析
    if (Serial.available() > 0) {
        char cmd = Serial.read();
        int angle = Serial.parseInt();
        
        switch (cmd) {
            case 'B':  // Base
            case 'b':
                angles[0] = constrain(angle, 0, 180);
                setServo(BASE_SERVO, angles[0]);
                break;
            case 'S':  // Shoulder
            case 's':
                angles[1] = constrain(angle, 0, 180);
                setServo(SHOULDER_SERVO, angles[1]);
                break;
            case 'E':  // Elbow
            case 'e':
                angles[2] = constrain(angle, 0, 180);
                setServo(ELBOW_SERVO, angles[2]);
                break;
            case 'G':  // Gripper
            case 'g':
                angles[3] = constrain(angle, 0, 180);
                setServo(GRIPPER_SERVO, angles[3]);
                break;
            case 'H':  // Home position
            case 'h':
                setAllServos(90, 90, 90, 90);
                break;
        }
        
        Serial.print("Angles: B=");
        Serial.print(angles[0]);
        Serial.print(" S=");
        Serial.print(angles[1]);
        Serial.print(" E=");
        Serial.print(angles[2]);
        Serial.print(" G=");
        Serial.println(angles[3]);
    }
}

void setServo(uint8_t channel, float angle) {
    uint16_t pulse = map(angle, 0, 180, SERVOMIN, SERVOMAX);
    pwm.setPWM(channel, 0, pulse);
}

void setAllServos(float b, float s, float e, float g) {
    setServo(BASE_SERVO, b);
    setServo(SHOULDER_SERVO, s);
    setServo(ELBOW_SERVO, e);
    setServo(GRIPPER_SERVO, g);
    angles[0] = b; angles[1] = s; angles[2] = e; angles[3] = g;
}

串口控制说明

通过串口发送命令控制机械臂:

命令功能示例
B(角度)设置基座角度B90 → 基座转90°
S(角度)设置肩关节角度S45 → 肩关节45°
E(角度)设置肘关节角度E120 → 肘关节120°
G(角度)设置夹爪开合G30 → 夹爪收紧
H回中位H → 所有关节90°

逆运动学实现

如果要根据目标坐标(x, y)自动计算关节角度,可以使用逆运动学:

// 简化逆运动学(2DOF平面臂)
// 输入:目标位置(x, y)
// 输出:肩关节角度θ1,肘关节角度θ2

void inverseKinematics(float x, float y, float* theta1, float* theta2) {
    float L1 = 100.0;  // 大臂长度(mm)
    float L2 = 100.0;  // 小臂长度(mm)
    
    // 计算距离
    float dist = sqrt(x*x + y*y);
    
    // 限制工作空间
    if (dist > L1 + L2) {
        dist = L1 + L2 - 1;  // 防止超出范围
    }
    
    // 肘关节角度(余弦定理)
    float cos_theta2 = (x*x + y*y - L1*L1 - L2*L2) / (2 * L1 * L2);
    cos_theta2 = constrain(cos_theta2, -1, 1);
    *theta2 = acos(cos_theta2);
    
    // 肩关节角度
    float k1 = L1 + L2 * cos(*theta2);
    float k2 = L2 * sin(*theta2);
    *theta1 = atan2(y, x) - atan2(k2, k1);
    
    // 转换为度
    *theta1 = degrees(*theta1);
    *theta2 = degrees(*theta2);
    
    // 调整到舵机角度范围(0-180)
    *theta1 = 90 + *theta1;
    *theta2 = 180 - *theta2;
}

调试与常见问题

问题原因解决
舵机抖动供电不足使用独立5V/5A电源
机械臂下垂舵机扭矩不够换更大扭矩舵机(如DS3218)
逆运动学计算错误目标点超出工作空间检查dist是否在L1+L2范围内
串口无响应波特率不匹配确认Arduino和串口工具波特率一致

扩展方向

项目二:双足步行机器人 🦿

Level 2-3 · 进阶级

8自由度小型双足机器人

一个能真正"走路"的小型双足机器人。每条腿4个自由度(髋3+膝1),可以实现前进、后退、转向等基本步态。学习步态规划、平衡控制、IMU姿态检测。

项目特点

BOM清单

类别名称规格数量参考价备注
舵机DS321820kg·cm 数字8个50×8=400元关节驱动
舵机支架铝合金U型8套40元连接舵机
控制Arduino MegaATmega25601块50元主控(多PWM)
MPU60506轴IMU1个8元姿态检测
HC-05蓝牙串口透传1个10元手机控制
电源锂电3S11.1V/1500mAh1块40元动力电源
降压DC-DC12V→6V/5A1块8元舵机供电
结构3D打印件PLA/PETG约400g~60元腿部+躯干
其他螺丝/螺母/轴承若干20元紧固件
总计~640元不含3D打印机

自由度分配

双足机器人自由度分配: ┌─────┐ │躯干 │ │IMU │ ← MPU6050安装位置 └──┬──┘ │ ┌──────┴──────┐ │ │ ┌──┴──┐ ┌──┴──┐ │左髋 │ │右髋 │ │Yaw │ │Yaw │ ← 关节1:侧摆(外展/内收) │Rol │ │Rol │ ← 关节2:外旋/内旋 │Pit │ │Pit │ ← 关节3:前屈/后伸 └──┬──┘ └──┬──┘ │大腿 │大腿 ┌──┴──┐ ┌──┴──┐ │左膝 │ │右膝 │ ← 关节4:膝关节 └──┬──┘ └──┬──┘ │小腿 │小腿 ┌──┴──┐ ┌──┴──┐ │左脚 │ │右脚 │ └─────┘ └─────┘ 单腿:4 DOF 双腿:8 DOF

步态规划核心代码

// 简化双足步态生成
// 生成单步周期的关节角度

const float T = 1.0;  // 步态周期(秒)

// 步态参数
float step_length = 40.0;   // 步长(mm)
float step_height = 20.0;   // 抬脚高度(mm)
float hip_swing = 15.0;     // 髋部摆动角度(度)

void generateGait(float t, float joints[8]) {
    float phase = fmod(t, T) / T;  // 0~1
    
    // 左腿相位
    float left_phase = phase;
    // 右腿相位(相差半个周期)
    float right_phase = fmod(phase + 0.5, 1.0);
    
    // === 左腿 ===
    if (left_phase < 0.5) {
        // 摆动相:抬腿前进
        float swing = sin(left_phase * 2 * PI);
        joints[0] = hip_swing * swing;           // 髋Yaw(侧摆)
        joints[2] = step_length * swing * 0.5;   // 髋Pitch(前后)
        joints[3] = -step_height * sin(left_phase * 4 * PI) * 0.5; // 膝
    } else {
        // 支撑相
        joints[0] = -hip_swing * 0.3;
        joints[2] = 0;
        joints[3] = 0;
    }
    
    // === 右腿 ===(相位相反)
    if (right_phase < 0.5) {
        float swing = sin(right_phase * 2 * PI);
        joints[4] = hip_swing * swing;
        joints[6] = step_length * swing * 0.5;
        joints[7] = -step_height * sin(right_phase * 4 * PI) * 0.5;
    } else {
        joints[4] = -hip_swing * 0.3;
        joints[6] = 0;
        joints[7] = 0;
    }
}

IMU平衡控制

// 简化平衡控制(基于IMU倾斜角)
// 当机器人前倾时,髋部后仰补偿

#include <Wire.h>
#include <MPU6050.h>

MPU6050 mpu;

float Kp_balance = 2.0;  // 平衡PID参数

void balanceControl(float* joints) {
    int16_t ax, ay, az, gx, gy, gz;
    mpu.getMotion6(&ax, &ay, &az, &gx, &gy, &gz);
    
    // 计算俯仰角(简化)
    float pitch = atan2(ay, az) * 180 / PI;
    
    // 补偿控制
    float compensation = Kp_balance * pitch;
    
    // 两个髋关节同时补偿
    joints[2] += compensation;   // 左髋Pitch
    joints[6] += compensation;   // 右髋Pitch
}

⚠️ 调试提示

双足机器人调试难度较高,建议:

  • 先固定在一个高度,调试单腿摆动
  • 使用"吊绳"支撑机器人重心,防止摔倒
  • 从慢速步态开始,逐步加速
  • IMU安装位置很重要,尽量靠近重心

扩展方向

项目三:小型人形机器人 🤖

Level 3-4 · 专业级

17自由度小型人形机器人

综合性最强、技术含量最高的项目。包含双腿、双臂、头部,可实现行走、挥手、舞蹈等复杂动作。需要系统集成、ROS通信、视觉处理等高级技能。

项目特点

BOM清单(精简版)

类别名称数量参考价备注
关节舵机总线舵机(如STS3215)17个150×17=2550元高性能、可串联
主控树莓派4B或Jetson Nano1块400~800元高层控制
底层控制STM32F407或专用舵机控制板1块50~150元实时控制
传感器IMU(ICM42688)、摄像头1套150元姿态+视觉
电源锂电3S 2200mAh + BMS1套80元动力电源
结构件3D打印或铝合金加工1套200~500元机械结构
总计~3500元起配置可调整

💡 成本优化建议

  • 使用普通PWM舵机替代总线舵机:成本降至~1500元,但性能降低
  • 使用ESP32替代树莓派+STM32:成本再降,但算力受限
  • 关注小米CyberGear等国产高性能电机方案:性价比高

自由度分配

人形机器人自由度分配(17 DOF): ┌───┐ │头 │ ← 2 DOF(左右/上下) └─┬─┘ │ ┌──────┴──────┐ ┌┴┐ ┌┴┐ │左│ │右│ │臂│ │臂│ ← 各3 DOF(肩3) │ │ │ │ └┬┘ └┬┘ │ │ └──────┬──────┘ │ ┌──┴──┐ │躯干 │ └──┬──┘ │ ┌──────┴──────┐ ┌┴┐ ┌┴┐ │左│ │右│ │腿│ │腿│ ← 各6 DOF(髋3+膝1+踝2) │ │ │ │ └─┘ └─┘ 头部:2 DOF 手臂:6 DOF(3×2) 腿部:12 DOF(6×2) 腰部:可选,增加1-3 DOF ────────────── 总计:20 DOF(基础版17 DOF)

分层控制架构

三层控制架构: ┌─────────────────────────────────────────┐ │ 应用层(树莓派/Jetson) │ │ - 任务规划:导航、抓取、语音交互 │ │ - 视觉处理:目标识别、SLAM │ │ - 语音:唤醒词、TTS、语音识别 │ │ 运行频率:10~50Hz │ │ 通信:UART/CAN │ └──────────────┬──────────────────────────┘ │ ┌──────────────▼──────────────────────────┐ │ 运动层(STM32/ESP32) │ │ - 步态生成:轨迹规划、逆运动学 │ │ - 平衡控制:IMU反馈、ZMP补偿 │ │ - 关节控制:位置/速度/力矩 │ │ 运行频率:200~1000Hz │ │ 通信:PWM/RS485/CAN │ └──────────────┬──────────────────────────┘ │ ┌──────────────▼──────────────────────────┐ │ 驱动层(舵机/电机) │ │ - 电流控制、编码器读取 │ │ - 过流保护、温度监控 │ │ 运行频率:10kHz(FOC) │ └─────────────────────────────────────────┘

ROS集成示例

# ROS 2 节点示例:发布关节命令

import rclpy
from rclpy.node import Node
from sensor_msgs.msg import JointState
from std_msgs.msg import String

class HumanoidController(Node):
    def __init__(self):
        super().__init__('humanoid_controller')
        
        # 订阅关节命令
        self.joint_sub = self.create_subscription(
            JointState,
            '/joint_command',
            self.joint_callback,
            10)
        
        # 发布到底层控制器(通过串口)
        self.serial_pub = self.create_publisher(String, '/serial_out', 10)
        
        self.get_logger().info('Humanoid Controller Ready')
    
    def joint_callback(self, msg):
        # 将ROS JointState消息转换为串口命令
        cmd = "JOINTS:"
        for i, name in enumerate(msg.name):
            angle = msg.position[i]
            cmd += f"{name}:{angle:.1f},"
        
        # 发布到串口节点
        out_msg = String()
        out_msg.data = cmd.rstrip(',')
        self.serial_pub.publish(out_msg)
        self.get_logger().debug(f'Sent: {out_msg.data}')

def main(args=None):
    rclpy.init(args=args)
    node = HumanoidController()
    rclpy.spin(node)
    node.destroy_node()
    rclpy.shutdown()

if __name__ == '__main__':
    main()

核心功能模块

模块功能技术要点
行走前进、后退、转向步态规划、IMU平衡
手势挥手、握手、拿物品逆运动学、轨迹规划
视觉人脸识别、跟随OpenCV、深度相机
语音唤醒、对话、TTS离线语音识别、在线API
遥控手柄、手机、网页WebSocket、HTTP服务

开发路线图

  1. 第1阶段:完成机械组装,测试所有关节运动
  2. 第2阶段:实现静态站立、简单步态
  3. 第3阶段:加入IMU平衡控制
  4. 第4阶段:开发上位机控制界面
  5. 第5阶段:集成视觉、语音功能
  6. 第6阶段:ROS集成、导航功能

📚 推荐学习资源

  • ROS官方教程:docs.ros.org
  • 开源人形机器人项目:Poppy、InMoov、PI4
  • 学术论文:IEEE ICRA、IROS会议
  • 视频教程:YouTube"Humanoid Robot"系列

本章小结

🎯 下一步

选择一个适合自己水平的项目,开始动手!记住:

  • 不要追求完美:先让它动起来,再优化
  • 记录过程:拍照、录视频、写笔记
  • 分享成果:开源精神,让更多人受益

"纸上得来终觉浅,绝知此事要躬行。"
—— 陆游