写在前面:在嵌入式的项目中,舵机是一个十分常见的元器件模块,其主要的功能是实现机械转动,实质上舵机是一个伺服的驱动器,适用于那些需要角度不断变化并可以保持的控制系统。例如在机器人的电控制器系统中,飞行器设计,遥控机器人等。舵机的使用需要PWM信号,所以在学习STM32控制舵机之前,必须对于STM32的定时器输出PWM波形十分熟悉。
stm32基本定时器输出PWM波形实验:CSDN
目录
一、SG90舵机介绍
1.1舵机的基本参数
1.2舵机工作原理
二、硬件设计
2.1定时器设计
2.2 定时器参数设计
2.3硬件连接
三、软件设计
3.1 pwm.c
3.2 main.c
3.3 实验现象
一、SG90舵机介绍
1.1舵机的基本参数
本次我们使用的是SG90舵机,其电气特性为:
工作电压:4.8-6V;
操作角度:0-180度;
线序定义:VCC(红色)、GND(棕色)、SIG(橙色);分别为:电源线、接地线、数据(信号)线;
实物图:
该舵机的使用较为简单,通电后直接由单片机驱动,通过控制单片机输出一个占空比不同的PWM波形来控制舵机转动的角度
1.2舵机工作原理
舵机的工作方式是由PWM波形控制的,在这里简单说明一下PWM波形中的主要参数:PWM波形的周期,也就是一个PWM波形的时间长短;PWM波形的占空比,即高电平占整个周期的比率;通过控制占空比来控制舵机转动的角度。
一般情况下,舵机的控制需要一个20ms左右的时基脉冲,该脉冲的高电平部分一般为0.5ms-2.5ms范围控制转动的角度。如下图所示:
20240316_210243
高电平时间 | 转动角度 |
0.5ms | 0度 |
1.0ms | 45度 |
1.5ms | 90度 |
2.0ms | 135度 |
2.5ms | 180度 |
在调节的过程中,我遇到了一些困惑,在此与大家共享,希望能帮到大家:
1、高电平时间为小于0.5ms,舵机是个什么状态?
在通电后,PWM波形中高电平时间小于0.5ms,舵机不转,或通电一瞬间有少许转动属于正常情况。
2、在通电后,一直输出一种占空比的PWM波形,舵机会持续转动吗?
不会,一种PWM对应一个角度,在通电后,舵机会迅速转动到对应的角度,此后,PWM的电平不变,舵机会一直停留到对应的角度。
3、舵机转动后,还会回到初始状态吗?
不会,一旦舵机转动到对应的角度,不会再回到0°,除非有对应的pwm波形。例如:如果要让舵机在0-90度之间来回转动,就需要在两种PWM波形之间来回变化。
4、当给转动90度指令,再迅速转动45度的指令,舵机会怎样?
舵机转到需要一定的时间,而且转动到角度越大,所需要的时间越长,如果还没转到90度,就给了45度的指令,舵机可能直接转回到45度,所以转动角度指令给后,会有一定的延时,保证舵机能转到对应的角度。
二、硬件设计
2.1定时器设计
本次使用的开发板是STM32F103精英版,该开发板中定时器共有8个,其中定时器TIM6、7为基本定时器,TIM2-5为通用定时器,TIM1、8为高级定时器。那我们就利用通用定时器来输出PWM波形。其中对于通用定时器输出PWM的详细说明,大家可以看我之前对定时器的相关博客已经讲解的十分详细了。
本次采用的定时器为通用定时器3,其输出通道为定时器3的通道1,通过查阅开发书册CH1通道的输出IO口为PA6,所以可以使用,不需要复用与重映射。
2.2 定时器参数设计
首先我们需要控制PWM波形的周期为20ms的时基脉冲,我们之前讲过PWM的周期由预分频系数psc以及自动重装载值arr共同决定。
T=(psc+1)(arr+1)/72MHz
psc:预分频系数;arr:自动重装载值;T:周期(单位s)
故:取psc=200-1;arr=7200-1;
此时计算得到的PWM的周期为20ms;
旋转的角度由脉冲的高电平部分控制,0.5ms-2.5ms范围控制转动的角度。计数器计一个数的时间为72MHz/7200=0.1ms.则0.5ms比较捕获器CCR的值为5,1ms比较捕获器CCR的值为10,1.5ms比较捕获器CCR的值为15,2ms比较捕获器CCR的值为20,2.5ms比较捕获器CCR的值为25.分别对应的角度为0,45,90,135,180。
2.3硬件连接
三、软件设计
链接:https://pan.baidu.com/s/1XRcyXjD2FSD1ZA_odJbkuA
提取码:1022
3.1 pwm.c
#include "./BSP/PWM/pwm.h"
/**
* @brief 定时器TIM3的初始化函数
* @param arr:自动重装载值;psc:预分频系数;
* @retval 无
*/
TIM_HandleTypeDef btim_pwm_handle; /* 定时器句柄 */
void btim_pwm_init(uint16_t arr,uint16_t psc)
{
btim_pwm_handle.Instance=TIM3;/* 定时器基地址 */
btim_pwm_handle.Init.Period=arr; /* 设置预自动重装载值 */
btim_pwm_handle.Init.Prescaler=psc; /* 设置预分频系数 */
btim_pwm_handle.Init.CounterMode=TIM_COUNTERMODE_UP; /* 设置计数模式向上计数 */
HAL_TIM_PWM_Init(&btim_pwm_handle);
TIM_OC_InitTypeDef timx_oc_pwm_struct;
timx_oc_pwm_struct.OCMode=TIM_OCMODE_PWM1; /* 设置比较输出模式PWM1 */
timx_oc_pwm_struct.Pulse=0;/* 设置捕获/比较寄存器的值,后面还会根据角度重新设置*/
timx_oc_pwm_struct.OCPolarity=TIM_OCPOLARITY_LOW;/* 输出比较极性为低 */
HAL_TIM_PWM_ConfigChannel(&btim_pwm_handle,&timx_oc_pwm_struct,TIM_CHANNEL_1);/* 定时器的 PWM 通道设置初始化函数 */
HAL_TIM_PWM_Start(&btim_pwm_handle, TIM_CHANNEL_1);/* 定时器的 PWM 输出启动函数,参数1为句柄,参数2为通道数 */
}
/**
* @brief定时器底层驱动,时钟使能,引脚配置此函数会被 HAL_TIM_PWM_Init()调用
* @param htim:定时器句柄
* @retval无
*/
void HAL_TIM_PWM_MspInit(TIM_HandleTypeDef *htim)
{
if(htim->Instance==TIM3)/* 判断是否为定时器3 */
{
__HAL_RCC_TIM3_CLK_ENABLE();/* 使能定时器时钟 */
__HAL_RCC_GPIOA_CLK_ENABLE();/* 使能输出io时钟 */
GPIO_InitTypeDef gpio_init_struct;
gpio_init_struct.Mode= GPIO_MODE_AF_PP;
gpio_init_struct.Pin=GPIO_PIN_6;
gpio_init_struct.Speed=GPIO_SPEED_FREQ_HIGH;
HAL_GPIO_Init(GPIOA, &gpio_init_struct);
}
}
3.2 main.c
#include "./SYSTEM/sys/sys.h"
#include "./SYSTEM/usart/usart.h"
#include "./SYSTEM/delay/delay.h"
#include "./BSP/LED/led.h"
#include "./BSP/PWM/pwm.h"
/************************************************************************************/
/*以下函数为0-180度舵机角度控制测试函数
* PWM 信号与0-180舵机的关系:
* 0.5ms ---------------- 0度
* 1ms ---------------- 45度
* 1.5ms ---------------- 90度
* 2ms ---------------- 135度
* 2.5ms ---------------- 180度
* 舵机频率与占空比的计算:
* 设舵机的频率为50HZ,则PWM周期为20ms,0度对应的占空比为2.5%,即0.05ms的高电平输出。
*/
int main(void)
{
HAL_Init(); /* 初始化HAL库 */
sys_stm32_clock_init(RCC_PLL_MUL9); /* 设置时钟, 72Mhz */
delay_init(72); /* 延时初始化 */
led_init(); /* LED初始化 */
btim_pwm_init(200-1,7200-1);
while(1)
{
__HAL_TIM_SET_COMPARE(&btim_pwm_handle,TIM_CHANNEL_1,5); /* 0°*/
delay_ms(1000);/* 延时一定时间,保证能够转动到一定的角度 */
__HAL_TIM_SET_COMPARE(&btim_pwm_handle,TIM_CHANNEL_1,25); /*180°*/
delay_ms(1000);
__HAL_TIM_SET_COMPARE(&btim_pwm_handle,TIM_CHANNEL_1,15); /* 90°*/
delay_ms(1000); /* 最后就会停到90°位置 */
}
}
3.3 实验现象
舵机实验
不能转动常见问题:
1、确保舵机是否正常,连线是否正常,对应的IO口是否合适;
2、确保PWM波形是否按照要求;
3、代码书写问题,IO口,定时器,以及延迟是否到位!!!
总结:本节我们利用STM32输出不同占空比的PWM波形,成功实现了SG90舵机的转动。讲述了转动的原理,连接线以及分享了HAL库的源码,大家学习后一定要自身实践实践。
创作不易,还请大家多多点赞支持!!!