Complete Projects — 从图纸到成品
💡 学习路径:不要一上来就做人形机器人。先从简单的机械臂开始,掌握基本原理,再逐步升级。每个项目都是前一个的进阶。
| 项目 | 难度 | 预算 | 时间 | 学到的核心技能 |
|---|---|---|---|---|
| 🦾 桌面机械臂 | Level 1-2 | ~300元 | 1-2周 | 舵机控制、逆运动学、串口通信 |
| 🦿 双足步行 | Level 2-3 | ~800元 | 2-4周 | 步态规划、平衡控制、IMU使用 |
| 🤖 小型人形 | Level 3-4 | ~3000元 | 1-3个月 | 系统集成、视觉、ROS、高级控制 |
一个经典的入门项目,使用4个舵机实现基座旋转、肩关节、肘关节、夹爪控制。通过串口或手机App控制,可完成抓取、搬运等任务。
| 类别 | 名称 | 规格 | 数量 | 参考价 | 备注 |
|---|---|---|---|---|---|
| 舵机 | MG996R | 20kg·cm扭矩 | 3个 | 15×3=45元 | 肩/肘关节 |
| SG90 | 1.8kg·cm | 1个 | 3元 | 夹爪 | |
| 舵机支架 | 铝合金U型 | 4套 | 20元 | 连接舵机 | |
| 舵机盘 | 十字/圆盘 | 4个 | 5元 | 随舵机附赠 | |
| 控制 | Arduino Uno | ATmega328P | 1块 | 25元 | 主控 |
| PCA9685 | 16路PWM扩展 | 1块 | 12元 | 舵机驱动 | |
| HC-05蓝牙 | 串口透传 | 1个 | 10元 | 手机控制(可选) | |
| 电源 | 5V开关电源 | 5V/5A | 1个 | 15元 | 舵机供电 |
| DC插座 | 5.5×2.1mm | 1个 | 1元 | 电源接口 | |
| 结构 | 3D打印件 | PLA/PETG | 约200g | ~30元 | 自行打印或淘宝代打 |
| 其他 | 螺丝螺母 | M2/M3/M4 | 若干 | 5元 | 紧固 |
| 总计 | ~170元 | 不含3D打印机 | |||
推荐开源项目"Arduino Robot Arm"(Thingiverse/Printables搜索),或自行用Fusion 360/SolidWorks设计。本知识库后续会提供配套图纸。
// 桌面机械臂控制程序 - 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和串口工具波特率一致 |
一个能真正"走路"的小型双足机器人。每条腿4个自由度(髋3+膝1),可以实现前进、后退、转向等基本步态。学习步态规划、平衡控制、IMU姿态检测。
| 类别 | 名称 | 规格 | 数量 | 参考价 | 备注 |
|---|---|---|---|---|---|
| 舵机 | DS3218 | 20kg·cm 数字 | 8个 | 50×8=400元 | 关节驱动 |
| 舵机支架 | 铝合金U型 | 8套 | 40元 | 连接舵机 | |
| 控制 | Arduino Mega | ATmega2560 | 1块 | 50元 | 主控(多PWM) |
| MPU6050 | 6轴IMU | 1个 | 8元 | 姿态检测 | |
| HC-05蓝牙 | 串口透传 | 1个 | 10元 | 手机控制 | |
| 电源 | 锂电3S | 11.1V/1500mAh | 1块 | 40元 | 动力电源 |
| 降压 | DC-DC | 12V→6V/5A | 1块 | 8元 | 舵机供电 |
| 结构 | 3D打印件 | PLA/PETG | 约400g | ~60元 | 腿部+躯干 |
| 其他 | 螺丝/螺母/轴承 | — | 若干 | 20元 | 紧固件 |
| 总计 | ~640元 | 不含3D打印机 | |||
// 简化双足步态生成
// 生成单步周期的关节角度
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倾斜角)
// 当机器人前倾时,髋部后仰补偿
#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
}
双足机器人调试难度较高,建议:
综合性最强、技术含量最高的项目。包含双腿、双臂、头部,可实现行走、挥手、舞蹈等复杂动作。需要系统集成、ROS通信、视觉处理等高级技能。
| 类别 | 名称 | 数量 | 参考价 | 备注 |
|---|---|---|---|---|
| 关节舵机 | 总线舵机(如STS3215) | 17个 | 150×17=2550元 | 高性能、可串联 |
| 主控 | 树莓派4B或Jetson Nano | 1块 | 400~800元 | 高层控制 |
| 底层控制 | STM32F407或专用舵机控制板 | 1块 | 50~150元 | 实时控制 |
| 传感器 | IMU(ICM42688)、摄像头 | 1套 | 150元 | 姿态+视觉 |
| 电源 | 锂电3S 2200mAh + BMS | 1套 | 80元 | 动力电源 |
| 结构件 | 3D打印或铝合金加工 | 1套 | 200~500元 | 机械结构 |
| 总计 | ~3500元起 | 配置可调整 | ||
# 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服务 |
选择一个适合自己水平的项目,开始动手!记住:
"纸上得来终觉浅,绝知此事要躬行。"
—— 陆游