资讯动态

STM32F103八足蜘蛛机器人:16路舵机PWM与三角步态控制

发布时间:2026/10/26 10:53:07 来源:尧图企业网站定制
简介一份面向嵌入式初学者与机器人控制爱好者的STM32F103实战项目源码围绕蜘蛛形机器人演示芯片外设、驱动与运动控制的完整实现可用于课程设计、毕业项目参考或嵌入式技能进阶。压缩包共188个文件约1.6MB以h头文件、c源文件、o目标文件及crf浏览信息文件为主并含少量工程配置、映射与烧录相关文件便于在Keil等环境中查看工程结构和编译关系。现有1386人学习说明其作为入门到中级案例具有一定参考价值。读者可从中梳理GPIO、ADC、SPI、I2C、UART等接口在电机与传感器连接中的用法理解电机驱动、中断处理、FreeRTOS任务调度、PID与步进电机控制、通信协议栈、传感器融合、电源管理及故障诊断等关键环节并借助调试工程文件还原蜘蛛机器人控制程序的整体框架与排错思路。1. 一块 F103 撑起八条腿这套蜘蛛机器人控制程序到底能干什么桌上摊着八条铝合金腿、十六颗舵机、一块 STM32F103 最小系统板线一接上电十六条腿同时抽一下——这是很多人第一次做多足机器人时的真实画面。这份蜘蛛机器人 STM32F103 控制程序源码解决的就是从“一堆舵机”到“能按步态走起来”这一段它把 50Hz 的舵机 PWM 驱动、单腿二自由度逆运动学、八足交替的三角步态调度、串口指令解析这几块拼成一个完整工程烧进去就能让机器人在原地站立、前进、转向。它更适合已经摸过 STM32、想让运动学公式落到实物上的开发者也适合拿它当多舵机联动模板改机械臂、四足、六足都行。十六路 PWM 全靠片内定时器硬扛没上外挂驱动芯片这一点对想搞懂底层时序的人特别友好。2. 硬件与工程骨架八轴舵机的引脚分配与启动链路拿到这类源码第一步不是打开 main.c而是先搞清楚“板子怎么接、电源从哪来、定时器够不够用”。这三件事没理顺后面写多少代码都是白搭。多足机器人翻车的地方八成不在算法而在供电和资源分配。2.1 机体结构与供电拓扑这份工程按八条腿、每条腿两个关节髋关节 膝关节组织合计 16 颗舵机。选二自由度而不是三自由度是因为 STM32F103 的定时器通道刚好卡在这个数上TIM1、TIM2、TIM3、TIM4 各 4 个通道合计 16 路每路都能独立输出 50Hz PWM不用分时复用也不用软件模拟。如果再给每条腿加一个踝关节24 路就超出片内资源了常见做法是外挂一颗 PCA9685 用 I2C 扩 16 路那时序精度反而比软件模拟稳。舵机型号上髋关节承重大一般用 MG996R 这类金属齿的膝关节负载轻MG90S 就够。这里有个必须算的账MG996R 空载电流约 100mA堵转能到 1.2A 以上16 颗舵机同时动作瞬时电流轻松突破 5A。所以供电千万不能从最小系统板的 5V 引脚取。我一般的接法是 2S 锂电7.4V分两路一路经 UBEC 降压到 5V/5A 单独喂舵机排针另一路经另一颗 UBEC 或板载 LDO 给 MCU。两路电源的 GND 必须拧在一起这是硬要求不共地的话 PWM 信号没有参考电平舵机会出现玄学抖动。舵机排针旁边并一颗 1000μF 电解电容加若干 0.1μF 瓷片电容作用是吸收舵机换向时的电流尖峰。这个细节看着土但它决定的是一上电就复位还是一上电就站稳。2.2 工程目录与启动链路工程目录不需要多花哨但分层要清楚不然改步态的时候会翻到驱动文件里去。SpiderBot_F103/ ├── CMSIS/ # 内核与外设寄存器定义 ├── Startup/ │ └── startup_stm32f10x_md.s ├── Hardware/ │ ├── servo.c / servo.h # 16 路 PWM 输出与角度映射 │ ├── uart.c / uart.h # 串口/蓝牙指令收发 │ └── timer.c / timer.h # 20ms 调度节拍 ├── Algorithm/ │ ├── ik.c / ik.h # 单腿逆运动学 │ ├── gait.c / gait.h # 三角步态相位调度 │ └── leg.c / leg.h # 腿对象IK 结果 - 舵机通道 ├── App/ │ ├── main.c │ └── config.h # 腿长、中位、限幅、步态参数 └── Project/ └── SpiderBot.uvprojx # Keil MDK 工程分层的核心思路是Hardware 层只认“通道号 微秒值”完全不知道腿和关节的概念Algorithm 层只认“毫米和角度”不知道 CCR 寄存器在哪App 层做参数配置和状态机调度。这样换舵机型号只改 servo.c 里的限幅表换机体尺寸只改 config.h 里的腿长两层互不干扰。config.h 单独拎出来是有意的——调参的时候只动一个文件比在十几个 .c 里翻宏定义舒服太多。启动链路是标准的 F103 流程上电复位 → startup 文件里的 Reset_Handler → SystemInit 把时钟拉到 72MHz →__main初始化.data/.bss 段 → main()。需要注意的是Keil 工程里一定要确认启动文件选的是 md中容量版本F103C8T6 是 64KB Flash、20KB RAM选成 hd 版本链接会报一堆错。2.3 时钟、定时器与 PWM 资源分配舵机的控制协议很简单每 20ms 给一个高电平脉冲脉宽 0.5ms 对应 -90°1.5ms 对应 0°2.5ms 对应 90°。所以定时器要配成 50Hz计数分辨率最好能到 1μs这样脉宽调节才够细。/* TIM3 四通道输出 50Hz PWM驱动第 0~3 号舵机 */ void ServoPwm_Init(void) { GPIO_InitTypeDef gpio; TIM_TimeBaseInitTypeDef tb; TIM_OCInitTypeDef oc; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB | RCC_APB2Periph_AFIO, ENABLE); RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); /* PB0/PB1 复用推挽TIM3_CH3 / TIM3_CH4 */ gpio.GPIO_Pin GPIO_Pin_0 | GPIO_Pin_1; gpio.GPIO_Mode GPIO_Mode_AF_PP; gpio.GPIO_Speed GPIO_Speed_50MHz; GPIO_Init(GPIOB, gpio); /* 72MHz / 72 1MHz 计数ARR 20000 - 20ms 周期正好 50Hz */ tb.TIM_Prescaler 72 - 1; tb.TIM_Period 20000 - 1; tb.TIM_CounterMode TIM_CounterMode_Up; tb.TIM_ClockDivision TIM_CKD_DIV1; TIM_TimeBaseInit(TIM3, tb); oc.TIM_OCMode TIM_OCMode_PWM1; oc.TIM_OutputState TIM_OutputState_Enable; oc.TIM_Pulse 1500; /* 上电默认 1.5ms 中位 */ oc.TIM_OCPolarity TIM_OCPolarity_High; TIM_OC3Init(TIM3, oc); TIM_OC4Init(TIM3, oc); TIM_OC3PreloadConfig(TIM3, TIM_OCPreload_Enable); TIM_OC4PreloadConfig(TIM3, TIM_OCPreload_Enable); TIM_Cmd(TIM3, ENABLE); }这段的关键在两个数字Prescaler 71把 72MHz 分频到 1MHz也就是每个计数代表 1μsPeriod 19999让计数器数到 20000 溢出周期正好 20ms。两者一除就是 50Hz脉宽直接等于 CCR 值写 1500 就是 1.5ms中间不需要任何换算调试的时候看 CCR 就知道脉宽省心。TIM_OCPreload_Enable建议打开。它让 CCR 的修改在下一个周期生效避免在计数中途改值导致出现半个畸变脉冲——舵机对畸形脉冲很敏感轻则抖一下重则内部电路误判。四个定时器的分配我一般这么排定时器通道驱动对象备注TIM1CH1~CH4右前腿、右中腿4 颗高级定时器需TIM_CtrlPWMOutputs使能TIM2CH1~CH4右后腿、左前腿4 颗通用定时器TIM3CH3~CH4左中腿2 颗部分通道被占用时只取能用的TIM4CH1~CH4左后腿4 颗通用定时器TIM1 是高级定时器除了常规的TIM_Cmd之外还要调一次TIM_CtrlPWMOutputs(TIM1, ENABLE)才有输出这个坑后面还会提。另外 PB3/PB4 默认被 JTAG 占用如果舵机通道分到这两个脚必须先关掉 JTAG 或者重映射否则怎么写都没波形。3. 核心模块拆解步态解算、舵机驱动与逆运动学的代码落地骨架搭好之后真正决定机器人走得像不像样的是三个模块把角度翻译成脉宽的舵机层、把足端坐标翻译成关节角的逆运动学、把时间切成一拍一拍的步态调度。这三层是串联的任何一层出错表现都是“腿抽风”但原因完全不同所以代码上要分清楚。3.1 舵机驱动角度到脉宽的映射与限幅最朴素的做法是CCR 500 angle * 11.1能跑但装到机器上就会出问题每颗舵机的中位都有偏差机械装配也有公差同样的角度指令这条腿偏 3°、那条腿偏 5°机器人站都站不直。所以舵机层必须带一个可标定的补偿量。#define SERVO_MIN_US 500 #define SERVO_MAX_US 2500 #define SERVO_MIN_DEG (-90.0f) #define SERVO_MAX_DEG ( 90.0f) typedef struct { uint8_t ch; /* 逻辑通道 0~15 */ int16_t trim; /* 装配误差补偿单位 us标定时填 */ int16_t min_us; /* 机械限位下限防止撞结构 */ int16_t max_us; /* 机械限位上限 */ } Servo_t; static Servo_t g_servo[16] { { 0, 0, 600, 2400 }, /* 0 右前髋 */ { 1, 0, 600, 2400 }, /* 1 右前膝 */ /* ... 其余 14 路初值一致标定时逐条改 trim */ }; void Servo_SetAngle(uint8_t id, float deg) { Servo_t *s g_servo[id]; int32_t us; if (deg SERVO_MIN_DEG) deg SERVO_MIN_DEG; if (deg SERVO_MAX_DEG) deg SERVO_MAX_DEG; /* -90~90 线性映射到 500~2500us */ us (int32_t)(SERVO_MIN_US (deg - SERVO_MIN_DEG) * 1000.0f / 180.0f); us s-trim; /* 叠加标定补偿 */ if (us s-min_us) us s-min_us; /* 机械限位优先 */ if (us s-max_us) us s-max_us; Servo_WriteCCR(s-ch, (uint16_t)us); }trim是这套代码里最有价值的一个字段。标定的时候把机器人架起来让所有舵机输出 0°看哪条腿没摆正量出偏差角度换算成微秒填进去一次标完写进结构体初值以后每次上电都是正的。两个限幅要分清SERVO_MIN_DEG/MAX_DEG是软件角度范围保证映射公式不越界min_us/max_us是机械限位是舵机装上结构之后实际能转到的范围通常比 ±90° 窄。第二层限幅必须放在trim之后否则补偿量会把脉宽推出机械行程舵机顶住结构堵转几分钟就能闻到味道。Servo_WriteCCR内部就是一张switch(ch)查表按通道号找到对应的 TIMx 和 CCRy 写进去。这张表是 16 个 case写起来枯燥但没别的办法因为 F103 的定时器通道和 GPIO 是绑死的没法运行时动态绑定。3.2 单腿逆运动学两条边解一个膝关节足端坐标是毫米舵机要的是角度中间这层换算就是逆运动学。二自由度腿是个平面两连杆问题已知大腿长 L1、小腿长 L2、足端相对髋关节的坐标 (x, y)求髋角和膝角余弦定理直接解。typedef struct { float hip_deg; float knee_deg; bool ok; } Joint_t; /* x 向前为正y 向上为正单位 mm原点在髋关节转轴 */ Joint_t Leg_SolveIK(float x, float y, float L1, float L2) { Joint_t out { 0.0f, 0.0f, false }; float d sqrtf(x * x y * y); float c1, c2, alpha, beta; const float R2D 57.29578f; /* 够不到时贴着极限走不要让 acos 参数越界 */ if (d (L1 L2) * 0.995f) d (L1 L2) * 0.995f; if (d fabsf(L1 - L2) 1.0f) d fabsf(L1 - L2) 1.0f; c1 (L1 * L1 d * d - L2 * L2) / (2.0f * L1 * d); c1 c1 1.0f ? 1.0f : c1; c1 c1 -1.0f ? -1.0f : c1; c2 (L1 * L1 L2 * L2 - d * d) / (2.0f * L1 * L2); c2 c2 1.0f ? 1.0f : c2; c2 c2 -1.0f ? -1.0f : c2; alpha atan2f(y, x); /* 足端方向角 */ beta acosf(c1); /* 大腿与足端连线的夹角 */ out.hip_deg (alpha beta) * R2D; out.knee_deg 180.0f - acosf(c2) * R2D; /* 膝内角转舵机角 */ out.ok true; return out; }d是髋关节到足端的直线距离。两个 clamp 是这段代码的保命符d超过 L1L2 说明目标点够不到直接算acos会得到 NaNNaN 传进舵机层再转成整数结果是一个随机的大数舵机瞬间打死d小于 |L1-L2| 同理。乘 0.995 是留一点余量让腿在极限位置保持微弯完全伸直的时候膝关节受力最差也最容易抖。knee_deg那行的180° - 内角是因为舵机的 0° 通常对应腿伸直状态而余弦定理算出来的是膝关节的内夹角两者差一个补角。这个换算方向和舵机的装配朝向强相关装反了就是膝盖往反方向弯——调试时先单腿验证别整机一起上。atan2f而不是atan是因为 x 可能为负腿往后摆atan只能返回 ±90°会让后摆的腿算到反方向去。3.3 三角步态相位表驱动的八足节拍八条腿不可能同时抬那样机器人就飞出去了。稳定的走法是分组交替一半腿支撑、一半腿抬起前摆半个周期后交换。八足常用的是两组交替学名叫交替三角步态落地时始终有四条腿在地上重心不会跑出支撑多边形。typedef struct { float stride_x; /* 单周期前后摆幅mm */ float lift_h; /* 抬腿高度mm */ float body_h; /* 机身离地高度mm */ uint16_t period_ms; /* 一个完整步态周期 */ } GaitParam_t; static const GaitParam_t g_gait { 30.0f, 18.0f, 90.0f, 600 }; /* 建议 20ms 调用一次与 PWM 周期同节拍 */ void Gait_Task(void) { static float t 0.0f; float step 20.0f / (float)g_gait.period_ms; t step; if (t 1.0f) t - 1.0f; for (uint8_t i 0; i 8; i) { /* 奇偶腿错开半周期0/2/4/6 与 1/3/5/7 分两组 */ float phase t ((i 1) ? 0.5f : 0.0f); float px, py; if (phase 1.0f) phase - 1.0f; if (phase 0.5f) { /* 支撑相贴地后移 */ float k phase * 2.0f; px g_gait.stride_x * (0.5f - k); py -g_gait.body_h; } else { /* 摆动相抬起前移 */ float k (phase - 0.5f) * 2.0f; px -g_gait.stride_x * (0.5f - k); py -g_gait.body_h g_gait.lift_h * sinf(k * 3.14159f); } Leg_SetFootTarget(i, px, py); /* 内部调 IK Servo_SetAngle */ } }t是归一化时间0~1 循环代表一个完整步态周期。支撑相占 0~0.5摆动相占 0.5~1.0各占一半这是交替步态能稳定的前提。如果支撑相少于一半会出现所有腿都在空中的瞬间机器人直接趴下。摆动相的py用了一个正弦项作用是让抬腿和落腿有加减速不是生硬地直线抬起。没有这一项的话足端在离地和触地瞬间速度突变整个机身会跟着顿一下走起来一颠一颠的。正弦是最省算力的平滑方案F103 没有 FPU能少一次浮点运算就少一次。stride_x和period_ms是一对步幅除以周期就是理论速度600ms 周期配 30mm 步幅大概是 50mm/s。想走快就缩短周期但周期太短舵机跟不上会出现指令发下去了、腿还在路上表现是越走越偏。Leg_SetFootTarget是腿对象层的入口负责把足端坐标转成髋膝角度再叠加各腿的安装方向最后调Servo_SetAngle。八条腿的安装朝向各不相同前后左右对称这个方向变换在腿对象初始化时用一张表配好步态层不用管。3.4 指令解析一行串口文本控制整机调试阶段用串口或者蓝牙发单字符指令最方便比接遥控器省事。/* 指令格式F80\n 前进速度 0~100S\n 停止 */ void Cmd_Parse(const char *line) { char dir line[0]; int spd (line[1] ! \0) ? atoi(line[1]) : 60; if (spd 0) spd 0; if (spd 100) spd 100; switch (dir) { case F: g_cmd.vx (int16_t)spd; break; case B: g_cmd.vx -(int16_t)spd; break; case L: g_cmd.wz (int16_t)spd; break; case R: g_cmd.wz -(int16_t)spd; break; case S: g_cmd.vx 0; g_cmd.wz 0; break; default: return; /* 非法指令直接丢弃 */ } g_cmd.updated true; }解析放在主循环里做中断只负责收字节、遇到\n置标志位不要在中断里直接调atoi和舵机输出浮点运算和长耗时操作会把 20ms 节拍拖乱。g_cmd是全局的指令缓存步态任务每个周期读一次。updated标志用于让步态层知道有速度变化可以做个简单的加减速斜坡不然速度从 0 直接跳到 100机器人会猛冲一下。4. 跑起来从 Keil 工程编译到第一次上电校准代码看懂了下一步是让它动。多足机器人有个特点代码没错装起来照样不走。因为机械装配、中位偏差、供电压降这些物理因素都不会在编译期报错。所以上电顺序必须讲究一上来就整机跑出问题根本分不清是硬件还是软件。4.1 编译下载与第一个心跳打开Project/SpiderBot.uvprojx先确认三件事再点编译检查项正确值出错后果DeviceSTM32F103C8选错无法下载启动文件startup_stm32f10x_md.shd 版本链接报错C/C 宏定义USE_STDPERIPH_DRIVER, STM32F10X_MD外设库编译不过下载器ST-Link / DAP-LinkSWD 模式连不上目标编译通过后先别急着接舵机只接 MCU 和下载器烧一个最小程序验证心跳。用调试器看SystemCoreClock是不是 72000000串口能不能收到上电打印。这一步过了说明时钟和串口没问题再往下走。# 命令行编译可选Keil 装了 UV4 就能用 UV4 -b Project/SpiderBot.uvprojx -j0 -o build_log.txt # 看返回码0 表示成功1 表示有警告2 以上是错误命令行编译主要图省事改完代码一键编译不用每次点开 IDE。-j0是隐藏 GUI-o把日志写到文件CI 里也能用。返回码 1 是警告常见的是未使用变量不影响功能但最好清掉。4.2 舵机中位标定先让八条腿站直标定这一步千万别省。16 颗舵机每颗中位偏差 ±5°装到腿上放大到足端就是 ±10mm 的误差八条腿各偏各的机器人站上去就是歪的之后所有步态参数都白调。标定流程我一般这么走把机器人架在支架上八条腿悬空接上舵机电源但不上整机电源。烧一个专用标定程序所有通道输出 1500μs0°死循环不跑步态。逐条腿观察哪条腿没摆到设计位置量出偏差角度按1° ≈ 5.56μs换算成微秒。把值填进g_servo[]的trim字段重新烧录再看一遍。重复 2~4直到八条腿目测对齐。有条件的用角度尺比目测准。偏差换算成微秒这一步不要凭感觉1000μs / 180° 5.56μs/°偏 3° 就填 17μs 左右写完再验证。填反了方向会更大别问我是怎么知道的。标定期间务必让腿悬空。带着负载调中位舵机会因为重力矩产生位置误差标出来的值是错的装回去又不准。4.3 首走测试与调参顺序标定完整机放地上按这个顺序调先测单腿。写个测试函数让指定的一条腿在 0° 和 30° 之间来回摆观察运动方向对不对、有没有撞结构、有没有异响。八条腿挨个过一遍这一步花十分钟能省掉后面两小时的排查。再测四腿。让对角的两组腿同时动看整机能不能保持平衡。此时不走路只做原地抬腿。如果某一组抬起来时机身明显下沉说明重心偏了需要调整body_h或者配重。然后测步态。把stride_x设成 10mm、period_ms设成 1000ms慢速走。慢速能看清每条腿的落地顺序速度一快就全靠猜了。确认落地顺序是交替的再逐步加步幅、减周期。最后调速度。速度上限不是拍脑袋定的取决于舵机响应和电源余量。加到某个值开始出现丢步或者复位就是上限往回收 20% 当工作点。整个过程中电源电压最好挂个电压表盯着。走起来电压从 5.0V 掉到 4.3V说明电源余量不够再怎么调代码也没用。5. 避坑与排查八条腿同时抽风时的 5 个血泪现场多足机器人的故障表现高度雷同抖、不走、走偏、复位。但原因可能分布在大相径庭的层面。下面这五条是我在实际调试里踩得最深的每条都按现象、原因、解决三步记下来。5.1 一上电全部舵机抖动MCU 反复复位现象电源一接通16 颗舵机同时“滋滋”响板载 LED 闪烁串口每隔一两秒打印一次启动信息。原因舵机和 MCU 共用一路 5V。舵机上电瞬间的浪涌电流把 5V 拉到 3V 以下MCU 触发欠压复位 BOR复位后重新初始化舵机又上电形成循环。这个现象特别像“程序跑飞”很容易误判成代码问题实际上示波器一夹电源就真相大白。解决舵机和 MCU 分路供电各用一颗 UBECGND 单点共接。舵机排针并 1000μF 电解电容。如果空间紧张只能用一路至少把 MCU 的供电线上串一个肖特基二极管加 100μF 电容做隔离让 MCU 侧的电压跌落慢一点。5.2 舵机全部往一个方向打死怎么调角度都没用现象所有舵机同时转到极限位置顶住发出持续的堵转声Servo_SetAngle传任何值都一样。原因PWM 频率配错了。常见的是TIM_Prescaler和TIM_Period只改了一个或者定时器时钟源不是 72MHz比如误用了 APB1 的分频后时钟。频率如果变成 1kHz舵机内部电路会把每个脉冲都当成一个新指令行为完全乱掉。另一个可能是 TIM1 忘了调TIM_CtrlPWMOutputs(TIM1, ENABLE)主输出没开通道上根本没有波形舵机收到的是持续低电平也会往一边靠。解决先用示波器或者逻辑分析仪量一路 PWM确认周期是 20ms、高电平在 0.5~2.5ms 之间。没有仪器就用调试器读 CCR 寄存器看值对不对再读 TIMx-PSC 和 ARR 确认分频。TIM1 的高级定时器使能那句单独检查一遍。5.3 走起来原地打滑越走越偏现象步态跑起来了腿也在动但机器人几乎不前进或者在原地慢慢转圈。原因三个可能。一是支撑相和摆动相的占空比不是 50/50支撑时间短于摆动时间腿还没蹬实地就抬起来了。二是八条腿的相位分配不对称比如奇偶分组写成了i % 3导致支撑多边形不完整。三是trim没标定各腿实际落地位置不一致等效于每条腿的步幅都不一样合力方向就偏了。解决先把period_ms拉到 1500ms肉眼看落地顺序确认是严格的交替。再把stride_x设成 5mm 慢走看足端是不是真的在地面上划过后移。如果打滑严重检查足端材料光滑地面的摩擦系数不够贴一层硅胶垫比调代码管用。5.4 串口发指令没反应或者只收到第一个字符现象串口助手发F80机器人不动发单字符F偶尔能动一下。原因中断接收里把字节存进缓冲区但没补\0atoi读到的是越界内存。或者主循环解析的速度跟不上接收速度缓冲区被覆盖。还有一种情况是 3.3V 的 MCU 直连 5V 电平的蓝牙模块TX 方向电平不匹配收到的字节是乱的。解决接收中断里维护一个索引收到\n时补\0并置标志主循环处理完清空索引。缓冲区长度给到 32 字节以上别卡着 8 字节用。电平不匹配的加一个电平转换或者选 3.3V 供电的模块。5.5 加了踝关节之后某几路舵机完全不动现象扩到三自由度之后24 路里有 8 路没有任何输出换通道、换舵机都没用。原因F103 的定时器通道数和 GPIO 复用是绑死的扩到 24 路必须外挂 PCA9685 或者用软件模拟。如果是外挂方案多半是 I2C 地址冲突或者初始化顺序不对如果是 GPIO 模拟常见的是某个脚被 JTAG 占用PB3/PB4/PA13/PA14/PA15或者被别的外设重映射抢走了。解决先确认引脚有没有被占用查GPIO_PinRemapConfig的调用必要时GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable, ENABLE)关掉 JTAG 保留 SWD。外挂方案先扫 I2C 总线确认能读到器件地址再往下查。6. 二次开发加闭环、换步态、扩腿数的改造路径这套代码的可扩展性主要来自分层步态层只输出足端坐标逆运动学只输出关节角舵机层只输出脉宽。想加东西找准层插进去就行不用动其他部分。最常见的改造是加 IMU 做姿态闭环。MPU6050 走 I2C 读加速度和角速度算出俯仰和横滚反馈到步态层调整body_h机身往前倾就把前腿抬高一点、后腿压低一点。改动集中在Gait_Task里给py加一个和姿态角相关的偏置项不用碰 IK 和舵机层。验证方法是把机器人架起来手动倾斜看腿会不会跟着补偿补偿方向反了就把符号取反。改造方向涉及文件主要风险IMU 姿态闭环gait.c、新增 imu.cI2C 阻塞拖慢 20ms 节拍建议 DMA 或分频读取换步态波纹/波浪gait.c 的相位表支撑腿数量变化重心可能出支撑多边形腿数扩到 12/24config.h、servo.c定时器通道不够需外挂驱动加遥控uart.c、新增 rc.c中断优先级和 PWM 冲突换步态是另一条常见路线。现在的实现是两组交替改成波浪步态只需要把相位偏移从 0.5 改成按腿序号递增的 1/8但支撑腿数量会从 4 条变成 7 条重心容差更小stride_x得跟着降下来。这类改动建议先在纸上画相位图确认每个时刻有多少条腿着地再动代码。扩腿数要谨慎。片内 16 路已经用满往上加必须外挂那就不是改几行代码的事了涉及 I2C 时序、刷新率、地址分配一整套。PCA9685 的刷新率是 50~1000Hz 可配但 I2C 写 16 个通道的耗时在 100kHz 总线下大概 2ms塞进 20ms 节拍里还行塞进 5ms 节拍就够呛。还有个实用技巧把config.h里的腿长、中位、步态参数全部改成可以从串口在线修改的变量调试的时候不用反复烧录。加一个P开头的参数设置指令比如P045.5改大腿长改完立刻生效。这个改动很小但能把调参效率提上去一大截。调试多足机器人我最深的一条教训是任何改动都先单腿验证再整机上电。有次偷懒直接改了 IK 的符号烧进去上电瞬间八条腿同时往内折两颗舵机的齿轮当场扫了换舵机花的时间比验证多十倍。从那以后我每次改运动学参数都强制走一遍“单腿悬空 → 四腿悬空 → 整机慢速”的流程一步都不跳。希望帮到你。本文还有配套的精品资源点击获取

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑