1. 项目概述:从零搭建你的第一台四足机器人

还记得小时候看《变形金刚》时幻想过拥有自己的机器狗吗?现在用STM32就能实现这个梦想!我花了整整两周时间,从零开始搭建了这个四足机器人项目,实测下来效果非常稳定,行走姿态也很流畅。

这个项目特别适合嵌入式初学者和机器人爱好者。你不需要深厚的数学基础,我会用最直白的方式讲解步态算法;也不需要昂贵的硬件,整套成本控制在150元以内。核心控制器采用STM32F103C8T6(就是大家熟悉的蓝色pill板),通过JDY-31蓝牙模块实现手机遥控,PCA9685驱动12个SG90舵机完成各种动作。

我最开始做这个项目时踩过不少坑:舵机抖动、蓝牙断连、步态不协调等问题都遇到过。通过这篇文章,我会把调试经验和解决方案都分享出来,让你少走弯路。整个项目从硬件组装到代码编写,再到最后的调试优化,我都会手把手带你完成。

2. 硬件选型与电路设计

2.1 核心控制器:STM32F103C8T6

为什么选择这款芯片?首先它性价比极高,市场价只要10元左右;其次性能足够强大,72MHz的主频能轻松处理四足机器人的运动控制算法;最重要的是生态完善,网上资料丰富,遇到问题容易找到解决方案。

我在实际使用中发现,需要特别注意电源稳定性。当所有舵机同时运动时,电流可能瞬间达到2A以上,如果电源管理没做好,会导致单片机重启。我的解决方案是给数字部分和舵机电源分别供电,中间用磁珠隔离,实测下来再没出现过复位问题。

2.2 舵机驱动方案:PCA9685

直接用一个代码示例说明如何初始化PCA9685:

// PCA9685初始化函数
void PCA9685_Init(void) {
    // 重置芯片
    I2C_WriteByte(PCA9685_ADDRESS, MODE1, 0x00);
    
    // 设置PWM频率为50Hz(适用于舵机控制)
    uint8_t prescale = (uint8_t)(25000000 / (4096 * 50) - 1);
    I2C_WriteByte(PCA9685_ADDRESS, MODE1, 0x10);    // 进入睡眠模式
    I2C_WriteByte(PCA9685_ADDRESS, PRESCALE, prescale);
    I2C_WriteByte(PCA9685_ADDRESS, MODE1, 0x00);
    
    HAL_Delay(5);
    I2C_WriteByte(PCA9685_ADDRESS, MODE1, 0xA1);    // 自动递增使能
}

这个芯片最大的优势是节省IO口——只需要2个IIC引脚就能控制16路舵机!而且内置12位精度PWM发生器,比STM32软件模拟的PWM稳定得多。我在调试时发现,如果IIC通信不稳定,会导致舵机出现异常抖动。后来在IIC线上加了上拉电阻(4.7K到10K),问题就解决了。

2.3 蓝牙通信模块:JDY-31

JDY-31是我用过最省心的蓝牙模块之一,价格只要8块钱,却支持主从一体和透传功能。通过AT指令可以修改设备名称、波特率等参数,非常灵活。

这里分享一个配置JDY-31的实用技巧:

// 蓝牙模块初始化
void Bluetooth_Init(void) {
    // 设置模块名称
    HAL_UART_Transmit(&huart1, "AT+NAMEQuadRobot\r\n", 17, 100);
    HAL_Delay(100);
    
    // 设置波特率为115200
    HAL_UART_Transmit(&huart1, "AT+BAUD115200\r\n", 15, 100);
    HAL_Delay(100);
    
    // 查询模块状态
    HAL_UART_Transmit(&huart1, "AT+VER\r\n", 8, 100);
}

实测通信距离在无障碍环境下能达到20米,完全满足室内控制需求。需要注意的是,蓝牙模块最好远离电机和舵机,否则会产生干扰。我最初把模块放在舵机旁边,经常出现控制失灵,后来用锡纸做屏蔽才解决。

2.4 动力系统:SG90舵机

SG90虽然扭矩不大(1.8kg/cm),但胜在便宜轻便。每个机器腿需要3个舵机,四足共12个。购买时一定要注意买180度版本,而不是360度连续旋转版本——我就买错过一次,导致机器人完全无法正常站立。

舵机安装有个小技巧:先不要上紧螺丝,把所有舵机调到90度中位点后再固定,这样能保证机器人的初始姿态水平。我第一个版本就是没注意这点,结果机器人站都站不稳。

3. 软件环境配置

3.1 CubeMX工程设置

用CubeMX配置项目能节省大量时间。关键配置如下:

  • 时钟源选择HSE(外部8MHz晶振)
  • 调试接口选择SWD(占用引脚少)
  • I2C1用于PCA9685,I2C2用于OLED
  • USART1用于蓝牙模块,开启中断接收
  • 系统时钟设置为72MHz

时钟树配置有个坑:如果PLL倍频设置不对,会导致I2C时序错误。我推荐直接使用CubeMX的自动配置功能,然后微调即可。

3.2 驱动程序编写

PCA9685的驱动程序需要实现PWM设置函数:

void SetServoAngle(uint8_t channel, float angle) {
    // 将角度转换为PWM脉宽
    // 0°对应0.5ms,180°对应2.5ms
    uint16_t pulse = (uint16_t)(angle * (2000.0 / 180.0) + 500);
    uint16_t counts = (uint16_t)(pulse * 4096 / 20000); // 20ms周期
    
    // 设置PWM占空比
    uint8_t buffer[4];
    buffer[0] = 0x06 + 4 * channel; // LED0_ON_L寄存器
    buffer[1] = 0x00;               // 上升沿时刻低字节
    buffer[2] = 0x00;               // 上升沿时刻高字节
    buffer[3] = counts & 0xFF;      // 下降沿时刻低字节
    buffer[4] = counts >> 8;        // 下降沿时刻高字节
    
    HAL_I2C_Master_Transmit(&hi2c1, PCA9685_ADDRESS, buffer, 5, 100);
}

这个函数实现了角度到PWM脉宽的精确转换。注意SG90舵机的控制脉冲周期是20ms,脉宽范围0.5ms到2.5ms对应0°到180°。

4. 四足机器人步态算法

4.1 基础步态原理

四足机器人的步态其实是在模仿动物的行走方式。最常见的是三角步态(Trot Gait)——始终保持三个脚着地形成一个支撑三角,另一个脚抬起迈步。这种步态稳定性最好,实现也相对简单。

我最初尝试直接写舵机角度,结果动作非常生硬。后来发现需要用三角函数来平滑过渡,下面是关键代码:

// 生成平滑的步态轨迹
void GaitGenerator(void) {
    static float phase = 0;
    phase += 0.1; // 控制步频
    
    for(int i=0; i<4; i++) {
        // 计算每条腿的相位偏移
        float leg_phase = phase + i * M_PI/2;
        
        // 用正弦函数生成平滑运动
        float lift_height = sin(leg_phase) > 0 ? sin(leg_phase) : 0;
        float step_progress = fmod(leg_phase, M_PI*2) / (M_PI*2);
        
        // 设置舵机角度
        SetLegPosition(i, step_progress, lift_height);
    }
}

4.2 逆运动学实现

逆运动学是机器人的核心算法,负责将脚底的目标位置转换为各个关节的角度。虽然听起来很高大上,但四足机器人的逆运动学其实很简单:

// 简化的逆运动学计算
void CalculateIK(float x, float y, float z, float* angles) {
    // 第一关节(髋部左右)角度
    angles[0] = atan2(y, x);
    
    // 计算平面距离
    float planar_dist = sqrt(x*x + y*y);
    
    // 第二关节(髋部前后)和第三关节(膝关节)角度
    // 使用余弦定理计算
    float L1 = 50; // 大腿长度
    float L2 = 50; // 小腿长度
    
    float D = sqrt(planar_dist*planar_dist + z*z);
    angles[2] = acos((L1*L1 + L2*L2 - D*D) / (2*L1*L2)) - M_PI;
    angles[1] = atan2(z, planar_dist) - atan2(L2*sin(angles[2]), L1 + L2*cos(angles[2]));
}

这个算法我调试了很久才稳定。最开始没考虑奇点位置,导致某些角度会突然翻转。后来加了角度限制和保护判断,现在运行非常稳定。

5. 蓝牙控制系统的实现

5.1 通信协议设计

蓝牙通信需要设计一个简单的协议来保证可靠性。我用的协议格式如下:

起始字节命令类型数据长度数据内容校验和
0xFF1字节1字节N字节1字节

实际代码实现:

// 蓝牙数据解析
void Bluetooth_Parse(uint8_t data) {
    static uint8_t buffer[20];
    static uint8_t state = 0;
    static uint8_t index = 0;
    static uint8_t length = 0;
    
    switch(state) {
        case 0: // 等待起始字节
            if(data == 0xFF) {
                state = 1;
                index = 0;
            }
            break;
            
        case 1: // 读取命令类型
            buffer[index++] = data;
            state = 2;
            break;
            
        case 2: // 读取数据长度
            length = data;
            buffer[index++] = data;
            state = length > 0 ? 3 : 4;
            break;
            
        case 3: // 读取数据内容
            buffer[index++] = data;
            if(index >= length + 3) {
                state = 4;
            }
            break;
            
        case 4: // 校验和验证
            if(VerifyChecksum(buffer, index, data)) {
                ExecuteCommand(buffer);
            }
            state = 0;
            break;
    }
}

5.2 手机APP控制

我写了一个简单的Android控制APP,界面包括方向摇杆和功能按钮。通过蓝牙发送控制指令,机器人就能实时响应。这里有个小技巧:在APP端添加指令队列和重发机制,能显著提高控制可靠性。

实测延迟在50ms左右,基本达到实时控制的要求。如果发现延迟太大,可以降低蓝牙波特率到9600,虽然传输速度变慢,但稳定性会提升。

6. 系统集成与调试

6.1 机械结构组装

组装顺序很重要:先装腿部和身体框架,再安装舵机,最后接线。我建议用尼龙架而不是3D打印件——3D打印的容易断裂,尼龙架韧性好很多。

接线时一定要做好标记,12个舵机的线缆很容易搞混。我吃过亏,接错线导致舵机烧毁一个。现在都是用不同颜色的热缩管来区分。

6.2 系统调试技巧

调试分三步走:首先单独测试每个舵机,确保都能正常转动;然后测试每条腿的三个舵机协调运动;最后才测试整体步态。

常见的调试问题及解决方案:

  • 舵机抖动:检查电源是否足够,I2C信号是否稳定
  • 步态不协调:调整步态算法中的相位参数
  • 蓝牙控制失灵:检查天线位置,远离电源线

我用OLED屏幕显示调试信息,实时显示舵机角度和电池电压,非常方便:

// OLED显示调试信息
void DisplayDebugInfo(void) {
    OLED_Clear();
    OLED_ShowString(0, 0, "Angle:");
    OLED_ShowNum(48, 0, current_angle, 3);
    OLED_ShowString(0, 2, "Battery:");
    OLED_ShowNum(64, 2, get_battery_voltage(), 2);
    OLED_ShowString(88, 2, "V");
    OLED_Refresh();
}

7. 优化与扩展功能

7.1 性能优化

经过实际测试,我发现几个优化点:首先是降低刷新频率,舵机不需要每毫秒都更新,50Hz足够了;其次是使用查表法代替实时计算,提前计算好步态数据存数组里。

电源管理也很重要:加上休眠功能,无操作时自动进入低功耗模式。我的实现是5分钟无操作就进入休眠,抖动一下身体就唤醒。

7.2 功能扩展

这个基础框架可以扩展很多功能:比如加装超声波避障、语音控制、甚至机器视觉。我最近在尝试加一个摄像头做图像识别,让机器人能跟踪特定颜色的物体。

另一个有趣的扩展是添加姿态传感器(MPU6050),实现自动平衡功能。当地面不平时,机器人能自动调整姿态保持稳定。

最后分享一个实用建议:做好代码版本管理!我因为没备份重写过一次程序,现在都用Git管理每个版本的代码。机器人开发是个迭代过程,经常需要调整参数和算法,有好用的工具能事半功倍。

Logo

北京人形旗下天工造物具身智能开源社区,聚焦具身天工与慧思开物两大平台

更多推荐