STM32驱动SG90舵机做个小车转向或机械臂?先搞懂PWM占空比和角度映射关系
STM32驱动SG90舵机:从PWM原理到机械臂控制的实战解析
第一次接触舵机时,我被它精准的角度控制能力震撼到了——这个小巧的装置竟然能像人类关节一样精确转动。在智能小车和机械臂项目中,SG90舵机因其性价比高、控制简单而成为入门首选。但要让这个"电子关节"真正活起来,关键在于理解PWM信号与角度之间的微妙关系。
1. SG90舵机控制的核心原理
1.1 舵机工作机制揭秘
SG90舵机内部包含三个关键部件:直流电机、减速齿轮组和位置反馈电位器。当PWM信号输入时,控制电路会比较信号脉宽与电位器反馈的当前位置,驱动电机转动直到两者匹配。这种闭环控制机制使得舵机能够精确保持设定的角度。
典型参数规格:
- 工作电压:4.8V-6V
- 工作电流:100-250mA(堵转时可达700mA)
- 扭矩:1.2-1.8kg·cm(6V时)
- 响应速度:0.1-0.2秒/60度
1.2 PWM信号与角度的数学关系
SG90舵机的角度控制遵循严格的时序规范:
| 脉冲宽度(ms) | 对应角度 | 占空比(20ms周期) |
|---|---|---|
| 0.5 | 0° | 2.5% |
| 1.0 | 45° | 5.0% |
| 1.5 | 90° | 7.5% |
| 2.0 | 135° | 10.0% |
| 2.5 | 180° | 12.5% |
这个线性关系可以用公式表示为:
角度 = (脉宽 - 0.5) × 180 / 22. STM32定时器配置实战
2.1 定时器参数计算
以STM32F103C8T6为例,假设系统时钟为72MHz,要实现20ms周期(50Hz)的PWM信号:
预分频器(PSC)设置:降低定时器时钟频率
// 预分频值 = 72MHz / (目标频率 × ARR) - 1 // 先设为72-1,得到1MHz计数器时钟 htim4.Init.Prescaler = 71;自动重装载值(ARR)设置:
// 周期 = (ARR + 1) / (定时器时钟频率) // 20ms = (ARR + 1) / 1MHz ⇒ ARR = 19999 htim4.Init.Period = 19999;捕获比较寄存器(CCR)计算:
// 脉宽 = (CCR + 1) / (定时器时钟频率) // 0.5ms = (CCR + 1) / 1MHz ⇒ CCR = 499
2.2 CubeMX图形化配置步骤
- 在Pinout视图选择TIM4_CH3(PB8引脚)
- 定时器配置:
- Clock Source: Internal Clock
- Prescaler: 71
- Counter Mode: Up
- Period: 19999
- Pulse: 默认值0
- PWM生成配置:
- Mode: PWM mode 1
- CH Polarity: High
// 生成的初始化代码示例 TIM_HandleTypeDef htim4; TIM_MasterConfigTypeDef sMasterConfig = {0}; TIM_OC_InitTypeDef sConfigOC = {0}; htim4.Instance = TIM4; htim4.Init.Prescaler = 71; htim4.Init.CounterMode = TIM_COUNTERMODE_UP; htim4.Init.Period = 19999; htim4.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1; // ... 其他初始化代码3. 角度控制函数封装
3.1 基础控制实现
void SG90_SetAngle(TIM_HandleTypeDef *htim, uint32_t Channel, float angle) { // 角度限幅 angle = angle > 180 ? 180 : (angle < 0 ? 0 : angle); // 计算对应CCR值 uint32_t ccr = 500 + (angle * 2000 / 180); __HAL_TIM_SET_COMPARE(htim, Channel, ccr); }3.2 多舵机协同控制
当需要控制多个舵机时,可以采用分时复用策略:
- 为每个舵机分配不同的定时器通道
- 使用同一个定时器但不同CCR值
- 通过软件延时确保信号稳定
// 控制两个舵机同步运动 void DualSG90_SyncMove(TIM_HandleTypeDef *htim, float angle1, float angle2) { SG90_SetAngle(htim, TIM_CHANNEL_1, angle1); SG90_SetAngle(htim, TIM_CHANNEL_2, angle2); HAL_Delay(20); // 等待至少一个PWM周期 }4. 高级应用与性能优化
4.1 机械臂关节控制方案
构建三自由度机械臂的关节控制:
| 关节 | 运动范围 | 定时器配置 |
|---|---|---|
| 底座 | 0-180° | TIM2_CH1 |
| 肩部 | 30-150° | TIM2_CH2 |
| 肘部 | 45-135° | TIM3_CH1 |
运动平滑技巧:
void SmoothMove(TIM_HandleTypeDef *htim, uint32_t Channel, float start, float end, uint16_t steps) { float delta = (end - start) / steps; for(int i=0; i<steps; i++){ SG90_SetAngle(htim, Channel, start + delta*i); HAL_Delay(10); } }4.2 性能优化要点
降低抖动:
- 电源端并联1000μF电容
- 信号线使用短导线并远离干扰源
- 添加软件消抖延迟
提高响应速度:
// 尝试使用10ms周期(100Hz) htim4.Init.Prescaler = 71; htim4.Init.Period = 999; // 10ms周期负载匹配:
- 超过舵机额定扭矩时添加减速机构
- 使用外部电源避免MCU电源过载
5. 常见问题排查指南
5.1 现象:舵机无反应
排查步骤:
- 检查接线:红色-5V,棕色-GND,黄色-信号
- 测量电源电压是否≥4.8V
- 用示波器验证PWM信号输出
- 确认定时器已启动:
HAL_TIM_PWM_Start(&htim4, TIM_CHANNEL_3);
5.2 现象:角度不准确
校准方法:
- 使用已知角度验证(如90°)
- 调整CCR偏移量:
// 在原有公式基础上添加校准偏移 uint32_t ccr = 500 + (angle * 2000 / 180) + offset; - 检查机械结构是否过紧
在最近的一个机械臂项目中,我发现SG90在连续工作30分钟后会出现约2-3度的漂移。通过添加温度补偿算法和定期归零校准,最终将误差控制在±0.5度以内。
