从零构建智能 Arduino 四足机器人:完整指南
元件清单
| Arduino Mega 2560 | ×1 | 15 路 PWM,驱动 12 舵机 + 3 路 RGB LED |
| SG90 9g 微型舵机 | ×12 | 每条腿 3 自由度 |
| HC-SR04 超声波测距模块 | ×1 | 避障/跟随功能 |
| 5mm 红/绿/蓝 LED | 各×4 | 组成 4 个 RGB 状态灯 |
| 排针 40P | ×2 | 舵机与传感器接口 |
| 定制 PCB(可选) | ×1 | 替代飞线,提升可靠性 |
| 硬纸板/亚克力板 | 若干 | 机身与腿部结构件 |
所需工具
- 电烙铁、热熔胶枪、螺丝刀、卡尺
核心原理:重心控制与步态规划
重心(CG)维持
四足行走的关键是始终让重心投影落在支撑三角形内部。静止时四腿呈 45° 对称,重心居中;抬起一条腿时,其余三腿需调整角度形成稳定三角形,确保重心在内部。

步态序列(波浪步态)
- 初始:C、D 腿外伸;A、B 腿内收
- B 腿抬起向前伸展
- 四腿同步后移,机身前进
- D 腿抬起向前迈步,形成镜像初始态
- A 腿抬起向前伸展
- 四腿同步后移
- C 腿收回,回到初始态

机械结构制作
- 下载
LEGS.pdf与BODY.pdf,按图激光切割或手工裁剪硬纸板/亚克力 - 组装 4 条腿,每腿 3 个舵机(髋横向、髋纵向、膝)
- 组装机身框架,预留 Mega、电池、超声波模块安装位


电路连接
Mega 2560 拥有 15 个 PWM 引脚:D2-D13, D44-D46。分配方案:
- 12 路舵机:任选 12 个 PWM 引脚(代码中定义
servo_pin[4][3]) - RGB LED:D44(蓝)、D45(绿)、D46(红) — PWM 控制颜色
- HC-SR04:Trig/Echo 任意两个数字口

舵机初始化与标定
上传初始化程序,将所有舵机设为 90° 中位,按图安装舵机摇臂,确保机械零位对齐:
#include <Servo.h>
Servo servo[4][3];
const int servo_pin[4][3] = {{10,11,2},{3,4,5},{6,7,8},{9,12,13}};
void setup() {
for(int i=0;i<4;i++) for(int j=0;j<3;j++) { servo[i][j].attach(servo_pin[i][j]); delay(20); }
}
void loop() {
for(int i=0;i<4;i++) for(int j=0;j<3;j++) { servo[i][j].write(90); delay(20); }
}

完整运动控制代码(含逆运动学)
核心采用 FlexiTimer2 定时器中断(50Hz)驱动舵机平滑插值,配合逆运动学将笛卡尔坐标转舵机角度。主要参数:
- 连杆长度:
length_a=55,length_b=77.5,length_c=27.5,length_side=71 - 默认足端坐标:
x_default=62,y_step=40,z_default=-50 - 运动速度常量:原地转向 4、腿部移动 8、机身移动 3、站立/趴下 1
代码实现了以下动作原语(阻塞式):
stand() / sit():站立/趴下step_forward(n) / step_back(n):前进/后退 n 步turn_left(n) / turn_right(n):原地左/右转 n 步hand_wave(n) / hand_shake(n):挥手/握手 n 次body_dance(n):机身扭动舞蹈
/* 完整代码较长,仅列出关键函数签名与核心算法 */
#include <Servo.h> #include <FlexiTimer2.h>
#define ledred 46 #define ledblue 44 #define ledgreen 45
Servo servo[4][3];
const int servo_pin[4][3] = {{2,3,4},{20,6,7},{8,9,17},{16,12,13}};
// ... 几何常量定义 ...
volatile float site_now[4][3], site_expect[4][3];
float temp_speed[4][3], move_speed, speed_multiple = 1;
const float KEEP = 255, pi = 3.1415926;
void setup() {
pinMode(ledred,OUTPUT); pinMode(ledblue,OUTPUT); pinMode(ledgreen,OUTPUT);
Serial.begin(115200);
// 初始化足端期望坐标
set_site(0, x_default, y_start+y_step, z_boot);
set_site(1, x_default, y_start+y_step, z_boot);
set_site(2, x_default, y_start, z_boot);
set_site(3, x_default, y_start, z_boot);
for(int i=0;i<4;i++) for(int j=0;j<3;j++) site_now[i][j]=site_expect[i][j];
FlexiTimer2::set(20, servo_service); FlexiTimer2::start();
servo_attach();
}
void loop() {
// 演示序列:站立→前进→后退→左转→右转→挥手→握手→RGB 呼吸灯
analogWrite(ledred,255); stand(); delay(2000);
analogWrite(ledblue,255); step_forward(5); delay(2000);
analogWrite(ledgreen,255); step_back(5); delay(2000);
analogWrite(ledred,255); analogWrite(ledblue,255); turn_left(5); delay(2000);
analogWrite(ledgreen,255); analogWrite(ledred,0); turn_right(5); delay(2000);
// ... 其余动作 ...
}
// 核心:50Hz 定时器中断,线性插值移动足端
void servo_service() {
sei(); static float alpha,beta,gamma;
for(int i=0;i<4;i++) for(int j=0;j<3;j++) {
if(abs(site_now[i][j]-site_expect[i][j]) >= abs(temp_speed[i][j]))
site_now[i][j] += temp_speed[i][j];
else site_now[i][j] = site_expect[i][j];
cartesian_to_polar(alpha,beta,gamma, site_now[i][0],site_now[i][1],site_now[i][2]);
polar_to_servo(i,alpha,beta,gamma);
}
}
// 逆运动学:笛卡尔坐标 → 极坐标 → 舵机角度
void cartesian_to_polar(float &alpha,float &beta,float &gamma,float x,float y,float z) {
float w = (x>=0?1:-1)*sqrt(x*x+y*y);
float v = w - length_c;
alpha = atan2(z,v) + acos((length_a*length_a - length_b*length_b + v*v + z*z)/(2*length_a*sqrt(v*v+z*z)));
beta = acos((length_a*length_a + length_b*length_b - v*v - z*z)/(2*length_a*length_b));
gamma = (w>=0)? atan2(y,x) : atan2(-y,-x);
alpha = alpha/pi*180; beta = beta/pi*180; gamma = gamma/pi*180;
}
void polar_to_servo(int leg,float alpha,float beta,float gamma) {
if(leg==0){ alpha=90-alpha; gamma+=90; }
else if(leg==1){ alpha+=90; beta=180-beta; gamma=90-gamma; }
else if(leg==2){ alpha+=90; beta=180-beta; gamma=90-gamma; }
else if(leg==3){ alpha=90-alpha; gamma+=90; }
servo[leg][0].write(alpha); servo[leg][1].write(beta); servo[leg][2].write(gamma);
}
// 设定足端目标坐标并计算速度向量
void set_site(int leg,float x,float y,float z) {
float lx=0,ly=0,lz=0;
if(x!=KEEP) lx=x-site_now[leg][0];
if(y!=KEEP) ly=y-site_now[leg][1];
if(z!=KEEP) lz=z-site_now[leg][2];
float len=sqrt(lx*lx+ly*ly+lz*lz);
temp_speed[leg][0]=lx/len*move_speed*speed_multiple;
temp_speed[leg][1]=ly/len*move_speed*speed_multiple;
temp_speed[leg][2]=lz/len*move_speed*speed_multiple;
if(x!=KEEP) site_expect[leg][0]=x;
if(y!=KEEP) site_expect[leg][1]=y;
if(z!=KEEP) site_expect[leg][2]=z;
}
进阶扩展建议
- 加装 IMU(MPU6050)实现姿态自稳
- 集成摄像头/树莓派实现视觉跟随
- 设计 3D 打印结构件替代纸板,提升刚性与美观
- 移植至 ESP32 实现 Wi-Fi/蓝牙远程控制
- 优化步态算法:添加小跑、奔跑等动态步态
资源文件
- 机械图纸:
LEGS.pdf,BODY.pdf - PCB 原理图:
schematic.png - 激光切割矢量图:
box.dxf
制造工艺
- 自制LUMAZOID:基于Arduino的音乐可视化灯光控制器
- Arduino Nano飞行模拟2020控制面板——LCD与CDI显示
- Arduino + HC-05 蓝牙控制 LED:MIT App Inventor 手机 App 开发全攻略
- Arduino 洗手计时器:抗击 COVID-19 的简易 DIY 工具
- Arduino RGB LED调色器:三电位器混色入门项目
- Arduino Uno驱动MAX7219级联8×8 LED矩阵:从入门到动画显示
- DIY Arduino 电子波疗设备 - 基于拉德尼克疗法的 EMR 治疗仪
- 户外DMX控制RGB投光灯:低成本高性能舞台灯光DIY方案
- DIY LED 轮盘赌游戏机 —— Arduino Nano 打造单人桌面街机
- Arduino 智能自动停车场系统:红外检测 + 舵机闸门 + LED 余位显示
- Arduino 超声波测距仪:HC-SR04 量程探测器
- MSGEQ7 音频可视化 RGB 灯带背光:电视/桌面氛围灯 DIY