STM32驱动SG90舵机做个小车转向或机械臂?先搞懂PWM占空比和角度映射关系

📅 2026/7/8 23:25:51 👁️ 阅读次数 📝 编程学习
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.52.5%
1.045°5.0%
1.590°7.5%
2.0135°10.0%
2.5180°12.5%

这个线性关系可以用公式表示为:

角度 = (脉宽 - 0.5) × 180 / 2

2. STM32定时器配置实战

2.1 定时器参数计算

以STM32F103C8T6为例,假设系统时钟为72MHz,要实现20ms周期(50Hz)的PWM信号:

  1. 预分频器(PSC)设置:降低定时器时钟频率

    // 预分频值 = 72MHz / (目标频率 × ARR) - 1 // 先设为72-1,得到1MHz计数器时钟 htim4.Init.Prescaler = 71;
  2. 自动重装载值(ARR)设置

    // 周期 = (ARR + 1) / (定时器时钟频率) // 20ms = (ARR + 1) / 1MHz ⇒ ARR = 19999 htim4.Init.Period = 19999;
  3. 捕获比较寄存器(CCR)计算

    // 脉宽 = (CCR + 1) / (定时器时钟频率) // 0.5ms = (CCR + 1) / 1MHz ⇒ CCR = 499

2.2 CubeMX图形化配置步骤

  1. 在Pinout视图选择TIM4_CH3(PB8引脚)
  2. 定时器配置:
    • Clock Source: Internal Clock
    • Prescaler: 71
    • Counter Mode: Up
    • Period: 19999
    • Pulse: 默认值0
  3. 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 多舵机协同控制

当需要控制多个舵机时,可以采用分时复用策略:

  1. 为每个舵机分配不同的定时器通道
  2. 使用同一个定时器但不同CCR值
  3. 通过软件延时确保信号稳定
// 控制两个舵机同步运动 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 性能优化要点

  1. 降低抖动

    • 电源端并联1000μF电容
    • 信号线使用短导线并远离干扰源
    • 添加软件消抖延迟
  2. 提高响应速度

    // 尝试使用10ms周期(100Hz) htim4.Init.Prescaler = 71; htim4.Init.Period = 999; // 10ms周期
  3. 负载匹配

    • 超过舵机额定扭矩时添加减速机构
    • 使用外部电源避免MCU电源过载

5. 常见问题排查指南

5.1 现象:舵机无反应

排查步骤

  1. 检查接线:红色-5V,棕色-GND,黄色-信号
  2. 测量电源电压是否≥4.8V
  3. 用示波器验证PWM信号输出
  4. 确认定时器已启动:
    HAL_TIM_PWM_Start(&htim4, TIM_CHANNEL_3);

5.2 现象:角度不准确

校准方法

  1. 使用已知角度验证(如90°)
  2. 调整CCR偏移量:
    // 在原有公式基础上添加校准偏移 uint32_t ccr = 500 + (angle * 2000 / 180) + offset;
  3. 检查机械结构是否过紧

在最近的一个机械臂项目中,我发现SG90在连续工作30分钟后会出现约2-3度的漂移。通过添加温度补偿算法和定期归零校准,最终将误差控制在±0.5度以内。