STM32控制舵机完全指南:从原理到实战(适合小白入门)_stm32 3.3v怎么驱动舵机
STM32控制舵机完全指南:从原理到实战
一、舵机基础原理
1.1 舵机是什么?
舵机(Servo Motor)是一种位置伺服驱动器,它可以根据控制信号精确地旋转到特定角度并保持在该位置。舵机内部包含直流电机、减速齿轮组、控制电路和电位器(用于检测当前角度)。
1.2 舵机如何工作?
舵机通过接收PWM(脉冲宽度调制)信号来控制角度。这个信号有三个关键特征:
- 频率固定:通常为50Hz(周期20ms)
- 脉宽可变:高电平持续时间在0.5ms-2.5ms之间变化
- 脉宽与角度对应:
- 0.5ms → 0度
- 1.5ms → 90度
- 2.5ms → 180度
二、硬件准备与连接
2.1 所需材料
- STM32开发板(如STM32F103C8T6)
- 舵机(常见SG90)
- 杜邦线若干
- 5V电源(注意:STM32的3.3V可能无法驱动舵机)
2.2 接线方式
重要提示:
- 当驱动多个舵机时,建议使用外部电源供电
- 确保共地(STM32与舵机电源地连接在一起)
三、STM32 PWM配置
3.1 PWM基础概念
PWM(脉冲宽度调制)是控制舵机的核心技术。STM32的定时器可以生成精确的PWM信号:
- ARR(自动重装载值):决定PWM周期
- CCR(捕获/比较值):决定脉冲宽度(占空比)
3.2 CubeMX配置步骤
- 打开STM32CubeMX,选择对应芯片
- 配置时钟树,确保定时器时钟正确(如72MHz)
- 选择定时器(如TIM3)和通道(如CH1)
- 设置模式为\"PWM Generation CH1\"
- 参数设置:
- Prescaler(分频系数):71
- Counter Period(ARR):1999
- Pulse(初始CCR):150(对应1.5ms)
3.3 关键代码解析
PWM初始化代码(以TIM3通道1为例):
// PWM初始化函数void PWM_Init(void) { TIM_TimeBaseInitTypeDef TIM_TimeBaseStruct; TIM_OCInitTypeDef TIM_OCInitStruct; // 1. 使能时钟 RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); // 2. GPIO配置 GPIO_InitStruct.GPIO_Pin = GPIO_Pin_6; GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOA, &GPIO_InitStruct); // 3. 定时器基础配置 TIM_TimeBaseStruct.TIM_Prescaler = 72 - 1; // 72MHz/72 = 1MHz TIM_TimeBaseStruct.TIM_Period = 20000 - 1; // 20ms周期 TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStruct); // 4. PWM通道配置 TIM_OCInitStruct.TIM_OCMode = TIM_OCMode_PWM1; TIM_OCInitStruct.TIM_OutputState = TIM_OutputState_Enable; TIM_OCInitStruct.TIM_OCPolarity = TIM_OCPolarity_High; TIM_OC1Init(TIM3, &TIM_OCInitStruct); // 5. 启动定时器 TIM_Cmd(TIM3, ENABLE);}
四、舵机控制实战
4.1 角度控制函数
将PWM脉宽转换为角度控制:
// 设置舵机角度(0-180度)void Servo_SetAngle(float angle) { // 角度转换为CCR值:500(0°) ~ 2500(180°) uint16_t pulse = (angle / 180) * 2000 + 500; TIM_SetCompare1(TIM3, pulse); // 更新CCR值}
4.2 主程序示例
#include \"stm32f10x.h\"#include \"pwm.h\"#include \"delay.h\"int main(void) { Delay_Init(); PWM_Init(); while(1) { // 0° → 90° → 180°循环 Servo_SetAngle(0); Delay_ms(1000); Servo_SetAngle(90); Delay_ms(1000); Servo_SetAngle(180); Delay_ms(1000); }}
4.3 按键控制进阶版
通过按键控制角度增减:
uint8_t key = KEY_GetNum();if(key == 1) { // KEY1按下 angle += 30; if(angle > 180) angle = 0; Servo_SetAngle(angle); OLED_ShowNum(1, 7, angle, 3); // 显示当前角度}
五、常见问题与调试技巧
5.1 舵机不转动
检查步骤:
- 确认电源电压≥4.8V
- 检查信号线连接是否正确
- 用示波器测量PWM波形
- 检查代码中定时器和GPIO配置
5.2 舵机抖动或不稳定
解决方案:
- 增加电源滤波电容(如100μF)
- 确保电源电流足够(单个舵机约需300mA)
- 检查PWM信号是否稳定
5.3 角度不准确
校准方法:
// 实际测试后调整公式void Servo_Calibrate(float angle) { // 自定义校准参数 uint16_t pulse = (angle / 180) * 1800 + 600; // 根据实测调整 TIM_SetCompare1(TIM3, pulse);}
六、项目扩展
6.1 多舵机控制
STM32的单个定时器可以同时控制4路舵机(通用定时器):
// 初始化TIM3的4个通道TIM_OC1Init(TIM3, &TIM_OCInitStruct); // CH1TIM_OC2Init(TIM3, &TIM_OCInitStruct); // CH2// ...其他通道类似
6.2 机械臂控制实例
6自由度机械臂控制:
void RoboticArm_Control(float angles[6]) { Servo_SetAngle(0, angles[0]); // 底座 Servo_SetAngle(1, angles[1]); // 肩部 Servo_SetAngle(2, angles[2]); // 肘部 // ...其他关节}
6.3 使用中断优化
通过定时器中断实现平滑运动:
void TIM3_IRQHandler(void) { if(TIM_GetITStatus(TIM3, TIM_IT_Update)) { static uint8_t step = 0; float target_angle = 90 + 30 * sin(step++ * 0.1); Servo_SetAngle(target_angle); TIM_ClearITPendingBit(TIM3, TIM_IT_Update); }}
七、学习资源推荐
-
官方文档:
- 《STM32参考手册》定时器章节
- STM32CubeMX用户手册
-
开发工具:
- 逻辑分析仪(观察PWM波形)
- STM32CubeMonitor(实时调试)
-
进阶项目:
- 双足机器人平衡控制
- 云台跟踪系统
- 自动窗帘控制器
完整工程下载:
STM32舵机控制示例代码
通过本指南,您已经掌握了从基础原理到实际应用的STM32舵机控制技术。建议按照以下步骤实践:
- 从单个舵机控制开始
- 尝试按键交互控制
- 实现多舵机协同
- 最后开发完整项目(如机械臂)
遇到问题时,记住检查电源、信号和代码配置这三个关键环节。祝您在嵌入式开发之路上越走越远!