STM32实战:SG90舵机PWM精准控制与多通道应用
1. SG90舵机与STM32的完美组合第一次接触SG90舵机是在做一个机械臂项目的时候当时就被这个小东西的精准控制能力惊艳到了。SG90作为最常见的微型舵机之一价格亲民但性能不俗特别适合搭配STM32做各种有趣的项目。你可能在航模、机器人或者智能家居设备里都见过它的身影。说到控制原理其实特别像我们平时用的开关。想象一下你每天开灯关灯的动作只不过SG90需要的是一个特别精确的开关节奏。它需要每20毫秒接收一次信号这个信号的高电平持续时间决定了舵机转动的角度。比如1.5毫秒的高电平对应中间位置2.5毫秒就是转到最右边。为什么选择STM32来控制呢我实测过好几款单片机发现STM32的定时器特别适合生成这种精确的PWM信号。它的定时器资源丰富像TIM3、TIM4这些通用定时器用起来特别顺手而且精度完全能满足SG90的需求。记得我第一次用Arduino控制SG90时偶尔会出现抖动的情况换成STM32后就稳如老狗了。2. PWM信号生成的底层原理要理解SG90的控制得先搞明白PWM是怎么回事。PWM全称是脉冲宽度调制说白了就是通过调节高电平的持续时间来控制设备。对于SG90来说这个周期固定是20ms也就是50Hz但高电平的持续时间可以在0.5ms到2.5ms之间变化。这里有个特别容易踩坑的地方很多人以为占空比越大舵机转得越厉害其实不是这样的。SG90只关心高电平的绝对持续时间而不是占空比的比例。比如同样是50%占空比10ms周期的5ms高电平和20ms周期的10ms高电平对SG90来说完全是两码事。STM32的定时器配置其实就是在设置这两个关键参数ARR自动重装载值决定PWM的周期PSC预分频器用来调整定时器的计数频率举个例子如果系统时钟是72MHz我们设置PSC71ARR1999那么实际的PWM频率就是72MHz/(72×2000)50Hz正好符合SG20的要求。这个计算过程刚开始可能会有点晕多试几次就明白了。3. 单通道舵机控制实战现在我们来点实际的看看怎么用STM32的TIM3控制一个SG90。首先得初始化GPIO这里要注意必须把引脚设置为复用推挽输出模式。我刚开始学的时候经常忘记这一步结果死活出不了PWM信号。配置定时器的步骤其实很有规律开启定时器和GPIO时钟设置GPIO为复用功能配置定时器基本参数ARR、PSC等配置PWM模式开启定时器这里有个小技巧STM32CubeMX可以自动生成这些初始化代码但我建议初学者还是手动写一遍这样才能真正理解每个参数的作用。我遇到过有人用CubeMX生成代码后舵机就是不动最后发现是没开启定时器使能。控制角度的时候要用到TIM_SetComparex()函数来改变占空比。比如想让舵机转到90度位置就需要设置比较寄存器的值为150假设ARR是199。这个150是怎么来的呢因为90度对应1.5ms高电平1.5ms/20ms×2000150。这个换算关系一定要记牢。4. 多通道控制与机械臂应用单个舵机玩熟了就该挑战多通道控制了。STM32的一个定时器可以同时输出4路PWM这意味着用TIM3和TIM4就能控制8个SG90足够做个简单的机械臂了。在多通道控制时有几点特别需要注意所有通道必须使用相同的ARR值保证周期一致每个通道有独立的CCRx寄存器控制占空比注意引脚的重映射功能避免冲突我在做六自由度机械臂时就遇到过引脚冲突的问题。当时TIM3_CH1和USART1的TX脚复用了导致要么舵机动不了要么串口发不出数据。后来查阅数据手册才发现这个问题改用TIM4的通道就解决了。多通道控制还有个常见问题是电源供应。SG90在转动瞬间电流可能达到500mA以上如果多个舵机同时动作普通的5V/1A电源根本扛不住。我的经验是至少准备5V/3A的电源并且每个舵机的电源线上都要加个100μF的电容滤波。5. 高级技巧与性能优化玩转基础功能后可以尝试一些进阶技巧。比如用中断来精确控制多个舵机的运动时序或者加入PID算法让运动更加平滑。一个很实用的技巧是使用DMA来更新CCR值。这样CPU就不用频繁干预PWM输出了特别适合需要同时控制多个舵机做复杂运动的场景。我在做一个云台项目时就用到了这个技术效果非常不错。还有一点很重要SG90的机械结构是有物理限位的虽然控制信号可以让它转到180度之外但强行超过限位会损坏齿轮。我的建议是在软件里做限幅处理比如void SetServoAngle(TIM_TypeDef* TIMx, uint32_t Channel, float angle) { angle angle 180 ? 180 : (angle 0 ? 0 : angle); uint32_t pulse (uint32_t)(50 angle * 100 / 180); switch(Channel) { case TIM_CHANNEL_1: TIMx-CCR1 pulse; break; case TIM_CHANNEL_2: TIMx-CCR2 pulse; break; // 其他通道... } }6. 常见问题排查指南调试舵机时难免会遇到各种问题我总结了几种常见情况舵机完全没反应检查电源是否接好确认信号线连接正确测量PWM信号是否正常输出舵机抖动或不稳定检查电源是否足够尝试在电源端加滤波电容确认PWM周期是否为准确的20ms舵机只能转到特定角度检查CCR值设置是否正确确认ARR值没有设置过小测试舵机机械结构是否卡住记得有一次我调试时舵机老是吱吱叫但不转动折腾了半天才发现是电源线接触不良。后来养成了习惯遇到问题先用万用表量电压往往能快速定位问题。7. 项目实战云台控制系统最后分享一个实际项目经验用STM32F103控制两个SG90搭建的简易云台。这个项目用到了TIM3的通道1和通道2分别控制水平和垂直方向的转动。关键点在于如何协调两个舵机的运动。我的做法是创建一个任务队列把转动指令按顺序执行。比如先水平转动45度再垂直转动30度每个动作完成后通过延时确保舵机到位。为了提升用户体验我还加入了按键控制和串口指令两种模式。按键用于手动调整角度串口则可以接收预设的坐标指令。代码结构大致如下typedef struct { uint8_t cmd; float h_angle; float v_angle; uint16_t duration; } ServoCommand; void ExecuteCommand(ServoCommand cmd) { // 平滑移动到指定角度 // 这里可以加入运动曲线算法 SetServoAngle(TIM3, TIM_CHANNEL_1, cmd.h_angle); SetServoAngle(TIM3, TIM_CHANNEL_2, cmd.v_angle); HAL_Delay(cmd.duration); }这个项目虽然简单但涵盖了STM32控制SG90的大部分关键技术点。通过它我深刻理解了定时器配置、多通道控制、外设协同工作等概念。