在 STM32 智能垃圾桶项目中,我们需要控制垃圾桶盖的自动开合,而舵机(SG90)是一个常用的选择。本文将深入探讨如何使用 STM32 的 PWM 功能来精确控制 SG90 舵机,并分享一些实战经验。
问题场景:垃圾桶盖的精确控制
我们需要实现:
- 当检测到垃圾桶前方有人靠近时,垃圾桶盖自动打开。
- 在一定时间后,垃圾桶盖自动关闭。
- 能够通过程序精确控制垃圾桶盖的开合角度。
这需要我们精确控制舵机的转动角度,而 PWM 正是实现这一目标的关键。
PWM 原理回顾
PWM(Pulse Width Modulation,脉冲宽度调制)是一种通过改变脉冲的占空比来调节信号有效值的技术。在 STM32 中,我们可以通过配置定时器(Timer)来生成 PWM 信号。PWM 的几个关键参数包括:
- 频率(Frequency):PWM 信号的周期,决定了舵机控制的刷新率。一般来说,舵机的工作频率在 50Hz 左右。
- 占空比(Duty Cycle):高电平时间在一个周期中所占的比例,决定了舵机的转动角度。对于 SG90 舵机,通常使用 0.5ms-2.5ms 的高电平脉宽来控制 0-180 度的转动。
- 分辨率(Resolution):占空比变化的最小单位,分辨率越高,舵机控制精度越高。
STM32 的定时器资源非常丰富,例如 TIM1、TIM2 等,我们可以选择合适的定时器来生成 PWM 信号。在使用定时器时,我们需要配置以下参数:
- 时钟源(Clock Source):选择定时器的时钟源,通常选择内部时钟。
- 预分频器(Prescaler):对时钟进行分频,降低定时器的计数频率。
- 自动重载值(Auto-Reload Value,ARR):定时器计数到 ARR 值时,会重新开始计数。
- 比较值(Compare Value,CCR):当定时器的计数值与 CCR 值相等时,输出 PWM 信号发生翻转。
SG90 舵机控制原理
SG90 舵机的工作原理是:通过控制输入 PWM 信号的高电平脉宽来控制舵机的转动角度。一般来说,SG90 的控制信号周期为 20ms(50Hz),高电平脉宽与转动角度的关系如下:
- 0.5ms:0 度
- 1.5ms:90 度
- 2.5ms:180 度
因此,我们需要根据所需的转动角度,计算出对应的 PWM 占空比,然后配置 STM32 的定时器,生成相应的 PWM 信号。
代码实现:STM32 控制 SG90
以下是一个使用 STM32CubeIDE 生成的工程控制 SG90 舵机的示例代码:
// 初始化 TIM1 的 PWM 输出
void PWM_Init(void) {
TIM_HandleTypeDef htim1;
TIM_MasterConfigTypeDef sMasterConfig = {0};
TIM_OC_InitTypeDef sConfigOC = {0};
htim1.Instance = TIM1;
htim1.Init.Prescaler = 71; // 72MHz / 72 = 1MHz
htim1.Init.CounterMode = TIM_COUNTERMODE_UP;
htim1.Init.Period = 19999; // 1MHz / 20000 = 50Hz (20ms)
htim1.Init.ClockDivision = 0;
htim1.Init.RepetitionCounter = 0;
htim1.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
if (HAL_TIM_PWM_Init(&htim1) != HAL_OK) {
Error_Handler();
}
sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
if (HAL_TIMEx_MasterConfigSynchronization(&htim1, &sMasterConfig) != HAL_OK) {
Error_Handler();
}
sConfigOC.OCMode = TIM_OCMODE_PWM1;
sConfigOC.Pulse = 1500; // 初始角度,对应 1.5ms
sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;
sConfigOC.OCNPolarity = TIM_OCNPOLARITY_HIGH;
sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;
sConfigOC.OCIdleState = TIM_OCIDLESTATE_RESET;
sConfigOC.OCNIdleState = TIM_OCNIDLESTATE_RESET;
if (HAL_TIM_PWM_ConfigChannel(&htim1, &sConfigOC, TIM_CHANNEL_1) != HAL_OK) {
Error_Handler();
}
HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_1); // 启动 PWM
}
// 设置舵机角度
void SetServoAngle(float angle) {
// 计算对应的 PWM 脉宽
float pulse_width = 0.5 + (angle / 180.0) * 2.0; // 0.5ms - 2.5ms
uint32_t pulse = (uint32_t)(pulse_width * 1000); // us
// 设置 CCR 值
TIM1->CCR1 = pulse; // 假设使用 TIM1_CH1
}
代码解释:
PWM_Init()函数用于初始化 TIM1,配置 PWM 频率为 50Hz,并设置初始角度对应的脉宽(1.5ms)。SetServoAngle()函数用于设置舵机的转动角度,根据给定的角度计算出对应的 PWM 脉宽,然后设置 TIM1 的 CCR1 寄存器,改变 PWM 的占空比。
实战避坑经验总结
- 电源问题:SG90 舵机需要独立的 5V 电源供电,不能直接从 STM32 的 3.3V 引脚取电,否则可能导致舵机工作不稳定甚至无法工作。
- GND 共地:务必将 STM32 和舵机的 GND 引脚连接在一起,否则可能导致信号传输异常。
- 抖动问题:如果舵机出现抖动,可以尝试调整 PWM 频率和分辨率,或者增加滤波电路。
- 角度校准:由于 SG90 舵机的实际角度与 PWM 脉宽之间可能存在偏差,需要进行角度校准,以确保舵机能够精确转动到目标角度。
- 注意舵机寿命:频繁地快速转动舵机可能会缩短其寿命,尽量避免不必要的转动。
- CubeMX 配置要点:在使用 STM32CubeMX 配置时钟树时,需要确保 TIMx 的时钟频率是正确的,这直接影响 PWM 的频率和精度。可以使用调试器查看时钟频率,或者使用 HAL 库提供的时钟查询函数。
扩展:配合红外传感器实现智能控制
可以将代码与红外传感器或其他传感器结合,实现更智能的垃圾桶控制。例如,使用红外传感器检测到有人靠近时,自动调用 SetServoAngle() 函数打开垃圾桶盖,并在一段时间后自动关闭。
通过本文,我们详细了解了如何使用 STM32 的 PWM 功能来控制 SG90 舵机,并分享了一些实战经验。希望这些内容能够帮助你更好地完成你的 STM32 智能垃圾桶项目。
冠军资讯
键盘上的咸鱼