目录
舵机
舵机简介
舵机(Servo,奴隶)实际上可以看做一个伺服电机,服从控制信号的要求而动作,可以很好的掌握电机角度。
特点:体积小、力矩大、结构简单、稳定性高。
应用:机器人关节、船舵、机械手等。
舵机按控制电路分类:数字舵机、模拟舵机。
数字舵机:数字电路(MCU和晶振)。只需要发送一次PWM信号就能保持在规定的某个位置。
模拟舵机:模拟电路。需要给它不断地发送PWM信号,才能让它保持在规定的某个位置或按照某个速度转动。
舵机按旋转角度分类:180°、360°。
180°:±90°,舵机常用。
360°:和直流电机差不多。
舵机结构
舵机主要由直流电机、减速齿轮组、角度传感器、控制电路构成。
角度传感器:用来实现位置反馈的,它会将其旋转后产生的电阻变化信号发送回控制电路,从而监控当前轴旋转的角度。
控制电路:用来驱动电机和接收PWM控制信号以及电位器反馈信号。
减速齿轮组:增大直流电机扭矩。
舵机工作流程图:
舵机的主要参数:
舵机型号:MG996R
工作电压:4.8V~6V
扭矩:11kg·cm(4.8V,相当于1cm的舵机能带动22斤的物体),13kg·cm(6V,相当于1cm的舵机能带动26斤的物体)
运行速度:0.12sec/60°(4.8V无负载),0.11sec/60°(6V无负载)
工作温度:-10℃~55℃
齿轮形式:金属齿轮
舵机工作原理
舵机一般需要周期为20ms的PWM信号来控制,该脉冲的高电平时间一般为0.5ms~2.5ms范围,相对应舵盘位置的0~180°。
舵机的输入线:VCC(一般4.8V~6V)、GND、信号线(输入PWM方波)。
ms和°对应关系(呈比例关系,0°~180°都可调节):
0.5ms -- 0°
1.0ms -- 45°
1.5ms -- 90°
2.0ms -- 135°
2.5ms -- 180°
正点原子的舵机接口电路分析
SERVO1信号线 PI5/TIM8_CH1/DCMI_VSYNC SERVO2信号线 PI6/TIM8_CH2/DCMI_D6 SERVO3信号线 PI7/TIM8_CH3/DCMI_D7 如:
PI6高电平时,此时三极管导通,SRV2的引脚3接到GND。
PI6低电平时,此时三极管截止,SRV2的引脚3接到SRV+。
正点原子舵机实验
功能描述:
KEY0控制三个舵机的某个舵机
KEY1增加舵机角度,最大180°
KEY2减小舵机角度,最小0°
硬件资源:
SERVO1信号线 PI5/TIM8_CH1/DCMI_VSYNC SERVO2信号线 PI6/TIM8_CH2/DCMI_D6 SERVO3信号线 PI7/TIM8_CH3/DCMI_D7
舵机控制代码编写步骤:
1、初始化LED,按键:初始化LED以及按键,用于指示和按键控制。
2、初始化定时器:初始化IO,设置ARR、PSC,计数方式以及脉冲输出模式(PWM模式2)等
3、修改比较值CCR1:通过函数__HAL_TIM_SetCompare修改CCRx的值。控制输出脉冲的占空比,进而控制舵机旋转角度。
PWM2模式:
在递增计数模式下,只要 TIMx_CNT<TIMx_CCR1,通道 1 便为无效状态,否则为有效状态。
在递减计数模式下,只要 TIMx_CNT>TIMx_CCR1,通道 1 便为有效状态,否则为无效状态。
即PWM2模式无论是递增计数还是递减计数,TIMx_CNT>TIMx_CCR1时通道为有效状态。
CH1N是CH1的反相,CH1N通道是会自动带着一个取反的。
/**
* @brief 高级定时器 TIMX PWM 初始化函数
* @note
* 高级定时器的时钟来自 APB2, 而 PCLK2 = 168Mhz, 我们设置 PPRE2 不分频, 因此
* 高级定时器时钟 = 168Mhz
* 定时器溢出时间计算方法: Tout = ((arr + 1) * (psc + 1)) / Ft us.
* Ft=定时器工作频率,单位:Mhz
*
* @param arr: 自动重装值
* @param psc: 时钟预分频数
* @retval 无
**/
void atim_timx_pwm_chy_init(uint16_t arr, uint16_t psc)
{
ATIM_TIMX_PWM_CHY_CLK_ENABLE(); /* TIMX 时钟使能 */
ATIM_TIMX_PWM_CH1_GPIO_CLK_ENABLE(); /* IO 时钟使能 */
ATIM_TIMX_PWM_CH2_GPIO_CLK_ENABLE(); /* IO 时钟使能 */
ATIM_TIMX_PWM_CH3_GPIO_CLK_ENABLE(); /* IO 时钟使能 */
g_atimx_pwm_chy_handle.Instance = ATIM_TIMX_PWM; /* 定时器 x */
g_atimx_pwm_chy_handle.Init.Prescaler = psc; /* 定时器分频 */
g_atimx_pwm_chy_handle.Init.CounterMode = TIM_COUNTERMODE_UP;
g_atimx_pwm_chy_handle.Init.Period = arr; /* 自动重装载值 */
g_atimx_pwm_chy_handle.Init.ClockDivision=TIM_CLOCKDIVISION_DIV1;
g_atimx_pwm_chy_handle.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE; /* 使能 TIMx_ARR 进行缓冲 */
g_atimx_pwm_chy_handle.Init.RepetitionCounter = 0;
HAL_TIM_PWM_Init(&g_atimx_pwm_chy_handle); /* 初始化 PWM */
g_atimx_oc_pwm_chy_handle.OCMode = TIM_OCMODE_PWM2;/* 模式选择 PWM2 */
g_atimx_oc_pwm_chy_handle.Pulse = 0.5/20*(arr+1);
g_atimx_oc_pwm_chy_handle.OCPolarity = TIM_OCPOLARITY_HIGH;
g_atimx_oc_pwm_chy_handle.OCNPolarity = TIM_OCNPOLARITY_HIGH;
g_atimx_oc_pwm_chy_handle.OCFastMode = TIM_OCFAST_DISABLE;
g_atimx_oc_pwm_chy_handle.OCIdleState = TIM_OCIDLESTATE_RESET;
g_atimx_oc_pwm_chy_handle.OCNIdleState = TIM_OCNIDLESTATE_RESET;
HAL_TIM_PWM_ConfigChannel(&g_atimx_pwm_chy_handle, &g_atimx_oc_pwm_chy_handle, ATIM_TIMX_PWM_CH1); /* 配置 TIMx 通道 y */
HAL_TIM_PWM_ConfigChannel(&g_atimx_pwm_chy_handle, &g_atimx_oc_pwm_chy_handle, ATIM_TIMX_PWM_CH2); /* 配置 TIMx 通道 y */
HAL_TIM_PWM_ConfigChannel(&g_atimx_pwm_chy_handle, &g_atimx_oc_pwm_chy_handle, ATIM_TIMX_PWM_CH3); /* 配置 TIMx 通道 y */
/* 开启对应 PWM 通道 */
HAL_TIM_PWM_Start(&g_atimx_pwm_chy_handle, ATIM_TIMX_PWM_CH1);
HAL_TIM_PWM_Start(&g_atimx_pwm_chy_handle, ATIM_TIMX_PWM_CH2);
HAL_TIM_PWM_Start(&g_atimx_pwm_chy_handle, ATIM_TIMX_PWM_CH3);
}
/* 168 000 000 / 168 = 1000 000 1Mhz 的计数频率, 1us 计数一次, 20K 次为 20ms */
atim_timx_pwm_chy_init(20000 - 1, 168 - 1);
20ms对应20000脉冲值。互补通道此处未使用。按照电路图,一周期0.5ms~2.5ms低电平对应舵机0°~180°,即脉冲500~2500。
/**
* @brief 舵机角度转定时器比较值
* @param angle:角度
* @retval 定时器装比较值
**/
uint16_t angle_to_tim_val(float angle)
{
uint16_t ret;
if((angle < 0)||(angle > 180))
{
ret = 0;
}
else
{
/* 0° -- 500, 45° -- 1000, 90° -- 1500, 135° -- 2000, 180° -- 2500 */
ret = 1500 + (int)((float)((angle - 90) * 100 / 9));
if((ret < 500)||(ret > 2500))
{
ret = 0;
}
}
return ret;
}
/**
* @brief 舵机角度设定
* @param id:舵机编号对应舵机的接口: 1~3; angle:角度
* @retval 0:成功
**/
uint8_t servo_angle_set(uint8_t id,float angle)
{
uint16_t val;
switch(id)
{
case 1:
val = angle_to_tim_val(angle); /* 得到角度转换的比较值 */
if(val != 0)
{
__HAL_TIM_SetCompare(&g_atimx_pwm_chy_handle, TIM_CHANNEL_1, val); /* 设置比较值 */
}
break;
case 2:
val = angle_to_tim_val(angle);
if(val != 0)
{
__HAL_TIM_SetCompare(&g_atimx_pwm_chy_handle,TIM_CHANNEL_2,val);
}
break;
case 3:
val = angle_to_tim_val(angle);
if(val != 0)
{
__HAL_TIM_SetCompare(&g_atimx_pwm_chy_handle,TIM_CHANNEL_3,val);
}
break;
default:
break;
}
return 0;
}