文章目录
- 1 舵机简介
- 2 注意事项
- 3 编写驱动程序
- 3.1 使用STM32作为控制器
- 3.1.1 计算高电平对应程序中的取值范围
- 3.1.2 编写控制程序
1 舵机简介
舵机使用PWM控制,周期为20ms,通过改变高电平占空比来驱动,高电平通常为1~2ms( 或 0.5 ~2.5ms)
2 注意事项
- 给舵机供电时,注意电流要足够,像使用电脑USB供电有可能带不动舵机
- 程序中高电平取值范围可以缩小一点,如最大值是200,最小值是40,程序中可以定义
#define DUTY_CYCLE_MIN 38 ;#define DUTY_CYCLE_MAX 198
,这样操作,舵机转到最大最小限位处,就不会响了。
3 编写驱动程序
3.1 使用STM32作为控制器
STM32单片机产生PWM,参考 《STM32CubeMX之定时器TIM,PWM》
3.1.1 计算高电平对应程序中的取值范围
舵机控制周期是20ms,高电平范围为 0.5~2.5ms
低位占空比:0.5 / 20 = 0.025;
高位占空比:2.5 / 20 = 0.125;
快速计算prescaler值,舵机周期是20ms固定值,即50Hz,Counter Period = 200,MCU时钟为72MHz
所以 72000000/50/200 = 7200
-
定时器初始化参数Counter Period = 200;
在程序中
低位占空比取值:200x0.025 = 5
高位占空比取值:200x0.125 = 25 -
定时器初始化参数Counter Period = 400;
在程序中
低位占空比取值:400x0.025 = 10
高位占空比取值:400x0.125 = 50 -
……
按照规律可以细分更多
3.1.2 编写控制程序
-
该程序逻辑实现,两个按键分别控制舵机顺时针和逆时针旋转,每按一下舵机旋转一个刻度(该刻度的精细可由定时器初始化参数Counter Period改变)
// 舵机的高电平范围为0.5ms ~ 2.5ms #define DUTY_CYCLE_MIN 5 // 注意该值范围跟定时器初始化参数Counter Period 有关系 #define DUTY_CYCLE_MAX 25 static uint8_t key1_flag = FALSE; static uint8_t key2_flag = FALSE; static uint8_t duty_cycle = DUTY_CYCLE_MAX; void servo_dispose(void) { if(0 == key1_get_status()) // 获取按键值 { HAL_Delay(10); if(0 == key1_get_status()) { if(key1_flag == FALSE) { key1_flag = TRUE; if((++duty_cycle) > DUTY_CYCLE_MAX) { duty_cycle = DUTY_CYCLE_MAX; } __HAL_TIM_SetCompare(&htim3,TIM_CHANNEL_1,duty_cycle); } } } else { key1_flag = FALSE; } if(0 == key2_get_status()) { HAL_Delay(10); if(0 == key2_get_status()) { if(key2_flag == FALSE) { key2_flag = TRUE; if((--duty_cycle) < DUTY_CYCLE_MIN) { duty_cycle = DUTY_CYCLE_MIN; } __HAL_TIM_SetCompare(&htim3,TIM_CHANNEL_1,duty_cycle); } } } else { key2_flag = FALSE; } }
int main(void) { …… HAL_TIM_PWM_Start(&htim3,TIM_CHANNEL_1); // 开启PWM __HAL_TIM_SetCompare(&htim3,TIM_CHANNEL_1,25); // 定义舵机有效的高电平占空比,这里配置最大值 while (1) { servo_dispose(); } }
-
该程序逻辑实现,两个按键分别控制舵机顺时针和逆时针旋转,按住按键舵机持续转动直到停止
// 舵机的高电平范围为0.5ms ~ 2.5ms // 1. 定时器初始化参数Counter Period 为200时,对应高电平取值范围如下 // #define DUTY_CYCLE_MIN 10 // #define DUTY_CYCLE_MAX 50 // 2. 定时器初始化参数Counter Period 为1600时,对应高电平取值范围如下 #define DUTY_CYCLE_MIN 38 // 最小值为40 ,可以稍微取值小一点,这样舵机到达最小限位处不会响 #define DUTY_CYCLE_MAX 198 // 最大值为200 ,可以稍微取值小一点,这样舵机到达最大限位处不会响 static uint8_t duty_cycle = DUTY_CYCLE_MAX; void servo_dispose(void) { if(0 == key1_get_status()) { HAL_Delay(10); if(0 == key1_get_status()) { // HAL_Delay(10); // 控制速度,速度太慢会出现一顿一顿的 if((++duty_cycle) > DUTY_CYCLE_MAX) { duty_cycle = DUTY_CYCLE_MAX; } __HAL_TIM_SetCompare(&htim3,TIM_CHANNEL_1,duty_cycle); } } if(0 == key2_get_status()) { HAL_Delay(10); if(0 == key2_get_status()) { // HAL_Delay(30); // 控制速度,速度太慢会出现一顿一顿的 if((--duty_cycle) < DUTY_CYCLE_MIN) { duty_cycle = DUTY_CYCLE_MIN; } __HAL_TIM_SetCompare(&htim3,TIM_CHANNEL_1,duty_cycle); } } }