☰
蜘蛛机器人STM32F103控制程序:18路舵机三角步态稳定实现
2026/10/21 12:24:27 网站建设 项目流程

简介:这份蜘蛛机器人STM32F103控制程序源码面向嵌入式开发初学者与机器人控制爱好者,基于ARM Cortex-M3内核的经典STM32F103芯片,演示如何用单片机驱动多足蜘蛛形态机器人,帮助读者理解从硬件接口到运动控制的完整实现链路。资源包共188个文件,约1.6MB,以c源码与h头文件为核心,配合o目标文件、d依赖文件、crf交叉引用记录及uv2、axf等Keil工程产物,另含sct分散加载、map映射与lst列表文件,便于还原编译与调试过程。源码覆盖GPIO电机驱动、ADC传感器采集、定时器PWM输出、PID与步进电机控制算法,并涉及FreeRTOS任务调度、蓝牙或Wi-Fi通信协议栈、传感器融合避障及电池电源管理等知识点,可作为多足机器人控制框架的学习范本。目前已有1384人学习下载,适合对照工程结构梳理外设初始化、中断处理与任务划分思路,快速搭建自己的蜘蛛机器人控制程序。

1. 蜘蛛机器人STM32F103控制程序:从舵机抖动到步态稳定的完整实现

很多人第一次拿到蜘蛛机器人STM32F103控制程序源码时,第一反应是“这不就是个多舵机驱动吗”,结果烧进去一看,机器人要么趴着不动,要么六条腿各走各的,像喝醉了一样。这个项目解决的就是这类问题:它是一套运行在STM32F103上的六足机器人控制程序,核心任务是把18路PWM舵机协调成稳定的三角步态,让机器人能前进、后退、转向,甚至做一些简单的姿态调整。适合谁?适合已经玩过STM32最小系统、想从点灯和串口进阶到多轴运动控制的开发者,也适合做毕设或课程设计、需要一套能跑起来的完整控制框架的人。源码里包含了舵机驱动、步态调度、串口指令解析这几个关键模块,不是那种只给几个头文件的空壳工程。

2. 硬件架构与工程目录:18路舵机怎么接到STM32F103上

2.1 硬件连接方案与定时器分配

蜘蛛机器人一般用18个舵机,每条腿3个关节:髋、膝、踝。STM32F103的定时器资源有限,不可能一个定时器管一个舵机,常见做法是用TIM1、TIM2、TIM3、TIM4四个定时器,每个定时器出4路PWM,加起来16路,再补两路用TIM5或者软件PWM。这个项目里用的是TIM1到TIM4的16路加TIM5的两路,总共18路,刚好覆盖。

舵机的信号线接在定时器的CH1到CH4上,电源线单独走5V或6V的稳压模块,地线共地。这里有个血泪经验:千万不要用STM32板子上的3.3V给舵机供电,舵机启动瞬间的电流能把MCU拉复位。我一般会用一个独立的5V/10A开关电源给舵机,STM32只用USB供电,两边共地就行。

// servo.h 定时器通道映射 #define SERVO_TIM1_CH1 TIM1, 1 #define SERVO_TIM1_CH2 TIM1, 2 // ... 省略中间通道 #define SERVO_TIM5_CH2 TIM5, 2 // 舵机编号到定时器通道的映射表 const ServoMap servo_map[18] = { {TIM1, 1}, {TIM1, 2}, {TIM1, 3}, // 右前腿 髋膝踝 {TIM1, 4}, {TIM2, 1}, {TIM2, 2}, // 右中腿 // ... 其余腿 };

这段映射表的作用是把“第几条腿的第几个关节”翻译成“哪个定时器的哪个通道”。参数说明:ServoMap结构体里存的是定时器外设指针和通道号,初始化的时候遍历这个表,逐个配置PWM。改机器人腿的顺序时,只需要改这个表,不用动底层驱动。

2.2 工程目录结构与模块划分

源码的目录结构大致是这样的:

SpiderRobot_STM32F103/ ├── Core/ │ ├── Inc/ │ │ ├── servo.h // 舵机驱动接口 │ │ ├── gait.h // 步态生成 │ │ ├── ik.h // 逆运动学解算 │ │ └── cmd_parser.h // 串口指令解析 │ └── Src/ │ ├── main.c // 主循环与初始化 │ ├── servo.c // PWM输出与角度映射 │ ├── gait.c // 三角步态调度 │ ├── ik.c // 足端坐标到关节角度 │ └── cmd_parser.c // 指令解析 ├── Drivers/ │ └── STM32F1xx_HAL_Driver/ └── MDK-ARM/ └── SpiderRobot.uvprojx // Keil工程文件

这个划分的好处是:舵机驱动只管发PWM,步态模块只管决定“什么时候抬哪条腿”,逆运动学只管算角度。三者通过一个结构体传递数据,耦合度低。常见做法是定义一个RobotState结构体,里面存当前足端坐标、关节角度、步态相位,各个模块读写这个结构体的不同字段。

注意:如果你用的是标准库而不是HAL库,servo.c里的PWM配置要换成TIM_OCInitTypeDef那套,但接口函数名可以保持不变,这样上层步态代码不用改。

3. 核心模块拆解:从PWM到三角步态的完整链路

3.1 舵机驱动:角度到脉宽的线性映射

舵机控制本质就是输出一个周期20ms、高电平0.5ms到2.5ms的PWM。0.5ms对应0度,2.5ms对应180度,中间线性插值。STM32F103的TIM时钟一般是72MHz,预分频72-1得到1MHz计数频率,也就是1个计数等于1微秒。自动重装载值设成20000-1,就是20ms周期。比较值设成500到2500,就是0.5ms到2.5ms。

// servo.c 设置某个舵机的角度 void Servo_SetAngle(uint8_t servo_id, float angle) { // 限制角度范围,防止舵机堵转 if (angle < 0) angle = 0; if (angle > 180) angle = 180; // 线性映射:0度->500us, 180度->2500us uint16_t pulse = 500 + (uint16_t)(angle * (2000.0f / 180.0f)); // 根据映射表找到定时器和通道,设置比较值 TIM_TypeDef *tim = servo_map[servo_id].tim; uint8_t ch = servo_map[servo_id].ch; switch (ch) { case 1: tim->CCR1 = pulse; break; case 2: tim->CCR2 = pulse; break; // ... 其余通道 } }

逻辑说明:先做角度限幅,避免用户传入超范围值导致舵机打到机械限位。然后做线性映射,2000.0f/180.0f是每度对应的微秒数。最后直接写CCR寄存器,不用HAL库的延时函数,因为步态调度里会频繁调用这个函数,用寄存器操作能省不少时间。参数说明:servo_id是0到17,对应18个舵机;angle是浮点数,方便逆运动学算出来的小数角度直接传进来。

3.2 逆运动学:足端坐标怎么变成三个关节角度

蜘蛛机器人每条腿可以简化为一个三自由度的连杆机构。给定足端相对于髋关节的坐标(x, y, z),需要算出髋、膝、踝三个舵机的角度。这里用的是几何法,不是DH参数法,因为几何法在二维平面内更直观。

// ik.c 单腿逆运动学解算 void IK_Solve(float x, float y, float z, float *hip, float *knee, float *ankle) { // 髋关节角度:足端在水平面的投影角度 *hip = atan2f(y, x) * 180.0f / M_PI; // 腿在垂直平面的投影长度 float L = sqrtf(x*x + y*y) - coxa; // coxa是髋关节到腿根的水平距离 float D = sqrtf(L*L + z*z); // 腿根到足端的直线距离 // 余弦定理求膝关节角度 float cos_knee = (femur*femur + tibia*tibia - D*D) / (2*femur*tibia); *knee = acosf(cos_knee) * 180.0f / M_PI; // 踝关节角度由几何关系推导 *ankle = 180.0f - *knee - atan2f(z, L) * 180.0f / M_PI; }

逻辑说明:hip角度是足端在水平面内相对于x轴的角度,直接atan2算出来。然后算腿根到足端的直线距离D,用余弦定理求膝关节的夹角。踝关节角度由三角形内角和推导。参数说明:coxa、femur、tibia是三条腿段的长度,单位毫米,需要根据实际机械结构测量后填入。x、y、z是足端坐标,一般以髋关节为原点,x向前,y向左,z向上。

提示:如果机器人实际运动方向和预期相反,先检查hip角度的正方向定义,很多翻车都是因为坐标系定义和机械安装对不上。

3.3 三角步态调度:六条腿怎么分组才不摔

三角步态的核心思想是把六条腿分成两组,每组三条腿构成一个三角形支撑面。一组抬起向前摆的时候,另一组支撑身体向后蹬。这样任意时刻至少有三条腿着地,机器人不会摔。

// gait.c 三角步态更新 void Gait_Update(RobotState *state) { // 步态相位:0到1循环 state->phase += state->speed; if (state->phase >= 1.0f) state->phase -= 1.0f; // 分组A:右前、左中、右后 // 分组B:左前、右中、左后 for (int i = 0; i < 6; i++) { float leg_phase = state->phase; if (i % 2 == 1) { // 分组B相位偏移0.5 leg_phase += 0.5f; if (leg_phase >= 1.0f) leg_phase -= 1.0f; } // 抬腿阶段:0到0.5,腿抬起并前摆 // 支撑阶段:0.5到1,腿着地并后蹬 if (leg_phase < 0.5f) { state->foot[i].z = lift_height * sinf(leg_phase * 2 * M_PI); state->foot[i].x = stride * (leg_phase * 2 - 0.5f); } else { state->foot[i].z = 0; state->foot[i].x = stride * (1.5f - leg_phase * 2); } } }

逻辑说明:phase是全局步态相位,speed控制步频。分组B的相位偏移0.5,这样两组腿交替抬起。抬腿阶段用正弦函数让足端平滑抬起和落下,避免突然离地导致机身晃动。支撑阶段足端x坐标线性后移,推动身体前进。参数说明:lift_height是抬腿高度,一般20到30毫米;stride是步幅,根据腿长决定,太大容易扯到关节。

3.4 串口指令解析:怎么用上位机控制机器人

项目里用串口接收上位机指令,格式是简单的ASCII字符串,比如“F”前进、“B”后退、“L”左转、“R”右转、“S”停止。解析函数放在主循环里轮询,不用中断,因为指令频率不高。

// cmd_parser.c 指令解析 void CMD_Parse(RobotState *state, uint8_t *buf, uint16_t len) { for (uint16_t i = 0; i < len; i++) { switch (buf[i]) { case 'F': state->speed = 0.02f; state->direction = 0; break; case 'B': state->speed = -0.02f; state->direction = 0; break; case 'L': state->direction = -0.5f; break; case 'R': state->direction = 0.5f; break; case 'S': state->speed = 0; state->direction = 0; break; default: break; } } }

逻辑说明:遍历接收缓冲区,遇到对应字符就修改RobotState里的速度和方向。speed是步态相位的增量,正数前进,负数后退。direction是转向分量,会叠加到足端y坐标上,实现差速转向。参数说明:buf是串口接收缓冲区,len是本次接收到的字节数。常见做法是在主循环里用HAL_UART_Receive轮询接收,超时设10ms,不阻塞步态更新。

4. 编译、烧录与调试:让机器人第一次站起来

4.1 Keil工程配置与编译选项

源码包里的MDK-ARM目录下有现成的uvprojx工程文件,用Keil MDK打开就能编译。但有几个地方需要检查:一是器件型号要选STM32F103C8T6或者你实际用的型号,二是C/C++选项卡里的预定义宏要有USE_HAL_DRIVER和STM32F103xB,三是下载器选ST-Link还是J-Link要和实际硬件一致。

# 如果用命令行编译,可以用arm-none-eabi-gcc arm-none-eabi-gcc -mcpu=cortex-m3 -mthumb \ -DUSE_HAL_DRIVER -DSTM32F103xB \ -ICore/Inc -IDrivers/STM32F1xx_HAL_Driver/Inc \ -c Core/Src/main.c -o build/main.o

这段命令的含义:指定Cortex-M3内核和Thumb指令集,定义两个宏让HAL库知道用哪个芯片,包含头文件路径,编译main.c。参数说明:-mcpu和-mthumb是必须的,否则链接会报错;-D开头的宏定义要和Keil里保持一致,不然HAL库会走错分支。

4.2 舵机中位校准与机械安装

烧录之前,先把所有舵机转到中位,再安装腿。中位就是Servo_SetAngle(id, 90)的位置。如果先装腿再上电,舵机可能会因为初始角度不对把腿拧断。我一般会写一个校准模式,上电后所有舵机慢慢转到90度,等5秒再进入正常步态。

// main.c 校准模式 void Calibration_Mode(void) { for (int i = 0; i < 18; i++) { Servo_SetAngle(i, 90); // 全部转到中位 } HAL_Delay(5000); // 等5秒,让机械安装到位 }

逻辑说明:这个函数在main初始化之后、进入主循环之前调用。5秒的延时是给安装留时间,实际调试时可以改成串口触发。参数说明:90是中位角度,如果你的舵机中位不是90,改成实际值。

4.3 串口调试与步态参数整定

机器人站起来之后,用串口助手发“F”看能不能走。如果走起来像抽搐,一般是步态参数不对。先调speed,从0.01开始慢慢加,找到不摔的最大值。再调lift_height,太低会拖地,太高会晃。最后调stride,太大腿会打架。

注意:调试的时候把机器人架空,让腿悬空,先看动作对不对,再放到地上。直接放地上调参数,摔几次舵机就扫齿了。

5. 避坑与常见问题:舵机抖动、步态错乱、串口没反应

5.1 舵机抖动或不动

现象:上电后舵机嗡嗡响但不转,或者偶尔抽一下。原因:PWM周期不对,或者比较值超出了500到2500的范围。解决:用示波器看PWM波形,确认周期是20ms,高电平在0.5到2.5ms之间。如果没有示波器,把Servo_SetAngle的输入固定成90,用万用表测信号线电压,应该是1.5V左右(平均值)。

5.2 步态错乱,腿的顺序不对

现象:机器人走起来像螃蟹,或者两条腿同时抬。原因:servo_map映射表和实际接线对不上,或者分组逻辑写反了。解决:先写一个测试函数,让18个舵机依次从0转到180再转回来,记录每个舵机对应的腿和关节。然后对照servo_map改映射表。分组逻辑检查i%2那行,如果分组反了,把0.5的偏移加到另一组。

5.3 串口发送指令没反应

现象:串口助手显示发送成功,但机器人不动。原因:串口接收中断没开,或者波特率不对。解决:检查main里的MX_USART1_UART_Init,波特率一般是115200。如果用的是轮询接收,确认HAL_UART_Receive的返回值是HAL_OK。常见做法是在接收回调里把数据存到环形缓冲区,主循环再从缓冲区取,避免阻塞。

5.4 机器人走几步就复位

现象:刚开始正常,走几秒后突然重启。原因:舵机电流太大,导致5V电源跌落,STM32的BOR复位。解决:给舵机电源并联一个大电容(1000uF以上),或者换更大电流的电源。STM32的供电和舵机供电分开走线,只在电源地处共地。

5.5 逆运动学算出来的角度是NaN

现象:串口打印关节角度,有时候是nan。原因:余弦定理里cos_knee超出了-1到1的范围,一般是D大于femur+tibia,腿够不着。解决:在IK_Solve里加限幅,把cos_knee限制在-1到1之间。同时检查输入的足端坐标是不是超出了腿的工作空间。

6. 二次开发:改步态、加传感器、换主控的实操思路

拿到这套源码之后,最常改的三个方向是:换步态、加传感器、换主控。换步态最简单,gait.c里的三角步态改成波形步态或者四足步态,只需要改Gait_Update里的相位分配逻辑。比如波形步态是每条腿依次抬,相位差1/6,改起来就是leg_phase = state->phase + i * (1.0f/6.0f)。加传感器的话,常见的是加MPU6050做姿态反馈,把俯仰角和横滚角读出来,叠加到足端z坐标上,实现坡道自适应。换主控比如换成STM32F4,主要改时钟配置和PWM频率,上层步态和逆运动学代码基本不用动。

// 加MPU6050姿态补偿的示例 void Gait_UpdateWithIMU(RobotState *state, float pitch, float roll) { // 原来的步态更新 Gait_Update(state); // 姿态补偿:根据俯仰角调整前后腿的高度 for (int i = 0; i < 6; i++) { float comp = pitch * state->foot[i].x * 0.01f; // 补偿系数 state->foot[i].z += comp; } }

逻辑说明:先跑原来的步态,得到基础足端坐标,然后根据俯仰角对z坐标做线性补偿。x越大的腿(前腿)补偿越多,x为负的后腿补偿相反。参数说明:pitch是俯仰角,单位度;0.01f是补偿系数,需要实际调试。这个改动不需要动ik.c和servo.c,只在步态层加一个函数。

验证方法:改完步态之后,先把机器人架空,用串口打印每条腿的足端坐标和关节角度,看波形是不是平滑。然后放到地上低速跑,用手机慢动作拍下来,逐帧看抬腿和落地的时序。我一般会保留一个“调试模式”,串口发“D”进入,机器人只做单腿动作,方便定位问题。

从那以后我每次改步态参数,都强制走一遍“架空看波形、低速看落地、高速看稳定性”这三步,不再直接上地跑。希望帮到你。

本文还有配套的精品资源,点击获取

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询