PWM驱动舵机原理与实践:基于STM32的精准控制
脉冲宽度调制(Pulse Width Modulation, PWM)是一种通过调节脉冲信号的占空比来控制模拟电路的技术。在嵌入式系统中,PWM被广泛用于电机速度控制、LED亮度调节、舵机角度控制等场景。频率(Frequency):单位时间内完整脉冲周期的数量占空比(Duty Cycle):高电平时间占整个周期的百分比分辨率(Resolution):占空比可调节的最小步进值理解了PWM控制舵机的基
目录
- PWM与舵机基础原理
- 1.1 PWM技术简介
- 1.2 舵机工作原理
- 1.3 PWM控制舵机角度原理
- 硬件设计与连接
- 软件实现详解
- 系统调试与优化
- 完整代码解析
- 应用扩展
- 总结
1. PWM与舵机基础原理
1.1 PWM技术简介
脉冲宽度调制(Pulse Width Modulation, PWM)是一种通过调节脉冲信号的占空比来控制模拟电路的技术。在嵌入式系统中,PWM被广泛用于电机速度控制、LED亮度调节、舵机角度控制等场景。
PWM有三个关键参数:
- 频率(Frequency):单位时间内完整脉冲周期的数量
- 占空比(Duty Cycle):高电平时间占整个周期的百分比
- 分辨率(Resolution):占空比可调节的最小步进值
1.2 舵机工作原理
舵机是一种位置伺服驱动器,主要由直流电机、减速齿轮组、位置反馈电位器和控制电路组成。常见的小型舵机工作电压为4.8-6V,控制信号为50Hz(周期20ms)的PWM信号。
舵机角度与PWM信号的关系:
- 0.5ms脉宽 → 0度位置
- 1.5ms脉宽 → 90度中立位置
- 2.5ms脉宽 → 180度位置
1.3 PWM控制舵机角度原理
通过改变PWM信号的脉冲宽度,可以精确控制舵机的输出角度。在STM32中,我们通过定时器的PWM模式产生符合舵机要求的控制信号:
舵机角度 = (PWM脉宽 - 500) × 180 / 2000
其中:
- 500对应0度(0.5ms)
- 2500对应180度(2.5ms)
- 2000是差值范围(2500-500)
2. 硬件设计与连接
2.1 STM32硬件资源
本设计基于STM32F103系列微控制器,主要使用以下硬件资源:
- GPIOA Pin1:PWM输出引脚(TIM2_CH2)
- GPIOB Pin1/Pin11:按键输入引脚
- GPIOB Pin8/Pin9:OLED I2C接口
2.2 舵机接口电路
舵机连接非常简单,只需三根线:
- 红色线:接5V电源正极
- 棕色/黑色线:接电源地
- 橙色/黄色线:接STM32的PWM输出(PA1)
注意:当驱动多个舵机时,建议使用外部电源供电,避免STM32开发板电源过载。
3. 软件实现详解
3.1 PWM模块配置
PWM初始化代码位于PWM.c中,关键配置如下:
void PWM_Init(void)
{
// 1. 时钟使能
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
// 2. GPIO配置为复用推挽输出
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
// 3. 定时器基础配置
TIM_TimeBaseInitStructure.TIM_Period = 20000 - 1; // ARR: 20ms周期
TIM_TimeBaseInitStructure.TIM_Prescaler = 72 - 1; // PSC: 72分频(1MHz)
// 4. PWM输出通道配置
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
TIM_OC2Init(TIM2, &TIM_OCInitStructure);
}
参数计算:
- 系统时钟72MHz,预分频72 → 计数器时钟1MHz
- 周期20000对应20ms(50Hz)
- 比较值500-2500对应0.5ms-2.5ms脉宽
3.2 舵机驱动实现
舵机驱动层在Servo.c中实现角度控制:
void Servo_SetAngle(float Angle)
{
PWM_SetCompare2(Angle / 180 * 2000 + 500);
}
这个函数实现了角度到PWM脉宽的线性转换:
- 0度 → 500 (0.5ms)
- 90度 → 1500 (1.5ms)
- 180度 → 2500 (2.5ms)
3.3 按键控制逻辑
按键检测代码位于Key.c中,实现了防抖处理:
uint8_t Key_GetNum(void)
{
uint8_t KeyNum = 0;
if (GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_1) == 0) // KEY1按下
{
Delay_ms(20); // 消抖
while (GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_1) == 0); // 等待释放
Delay_ms(20);
KeyNum = 1;
}
// KEY2检测类似...
return KeyNum;
}
在主循环中,可以通过按键控制舵机角度:
KeyNum = Key_GetNum();
if (KeyNum == 1) // KEY1按下
{
Angle += 30; // 角度增加30度
if (Angle > 180) Angle = 0; // 超过180度归零
Servo_SetAngle(Angle); // 设置新角度
OLED_ShowNum(1, 7, Angle, 3); // 显示当前角度
}
4. 系统调试与优化
4.1 常见问题排查
-
舵机不响应
- 检查电源电压是否足够(建议5-6V)
- 确认PWM信号线连接正确
- 使用示波器测量PWM波形是否符合要求
-
舵机抖动
- 确保电源有足够电流供应
- 检查PWM信号是否稳定
- 尝试增加电源滤波电容
-
角度不准确
- 校准PWM参数(调整500和2500的基准值)
- 检查舵机机械结构是否受阻
4.2 性能优化建议
-
多舵机控制
- 使用定时器多个通道同时控制多个舵机
- 考虑使用舵机控制芯片如PCA9685
-
运动平滑处理
- 实现角度缓动算法,避免突变
void Servo_SmoothMove(float TargetAngle, uint16_t Duration) { float step = (TargetAngle - CurrentAngle) / (Duration / 10); for(int i=0; i<Duration/10; i++){ CurrentAngle += step; Servo_SetAngle(CurrentAngle); Delay_ms(10); } } -
低功耗优化
- 空闲时关闭PWM输出
- 使用定时器中断代替轮询
5. 完整代码解析
系统主循环实现了两种工作模式:
- 自动模式:舵机在5度和90度间周期性摆动
- 按键模式:通过按键控制角度(代码中被注释)
while (1)
{
// 自动模式
Servo_SetAngle(90);
Delay_ms(2000);
Servo_SetAngle(5);
Delay_ms(2000);
// 按键控制模式(需取消注释)
/*
KeyNum = Key_GetNum();
if (KeyNum == 1) {
Angle += 30;
if (Angle > 180) Angle = 0;
}
Servo_SetAngle(Angle);
OLED_ShowNum(1, 7, Angle, 3);
*/
}
6. 应用扩展
基于此项目可扩展多种应用:
- 机器人关节控制:多舵机协调实现复杂动作
- 摄像头云台:双舵机实现水平和垂直控制
- 智能家居:窗帘、门锁等设备的电动控制
- 航模控制:飞机舵面、油门控制
高级扩展方向:
- 加入PID算法实现更精准的位置控制
- 通过蓝牙/WiFi实现远程控制
- 结合传感器实现闭环反馈控制
7. 总结
本文详细介绍了基于STM32的PWM舵机控制系统设计与实现,关键点包括:
- 理解了PWM控制舵机的基本原理
- 掌握了STM32定时器PWM模式的配置方法
- 实现了精确的角度控制算法
- 开发了完整的硬件接口和软件驱动
通过本项目,我们不仅学习了一个具体的嵌入式应用,更重要的是掌握了"定时器→PWM→外设控制"这一嵌入式开发的典型模式。这种模式可以推广到电机控制、LED调光等多种应用场景。
实践建议:读者可以尝试修改PWM参数观察舵机反应,或者扩展多路舵机控制,这将大大加深对PWM技术的理解。
更多推荐



所有评论(0)