第9章 舵机控制

news/2024/12/20 13:48:03/

 

有一种电机可以在程序的控制下,在一定范围内连续改变输出轴角度并且可以保持住。这种电机最早被用在航模和船模等遥控模型中,控制各种舵面的转动,这就是舵机。现在舵机除了运用在
遥控模型中,也大量的运用在各种机器人、机械臂的关节以及智能小车的转向机构中。下图就是一种标准舵机的外形。

9.1 舵机分类

1. 按照舵机的控制电路可以分为:模拟舵机和数字舵机。模拟舵机和数字舵机的机械结构可以说是完全相同的,模拟舵机的控制电路为纯模拟电路,需要一直发送目标信号,才能转到指定的位置,响应速度较慢,无反应区较大;数字舵机内部控制电路则加上了微控制器,只需要发送一次目标信号,即可到达指定位置,速度比模拟舵机更快,无反应区也更小。

2. 按照使用对象的不同,可以分为:航模舵机、车模舵机、船模舵机和机器人舵机。航模舵机一般要求速度快、精度高,而车模和船模用的舵机一般要求具有大扭矩和防水性好。

3. 按照内部机械材质,又可分成:塑料齿舵机和金属齿舵机。塑料齿舵机内部的传动齿轮是塑料的,重量轻价格便宜,扭矩一般较小无法做大;金属齿舵机的扭矩大,舵机更结实耐用,但是相比塑料齿更重也更贵。
4. 按照外部接口和舵机的控制方式,又可分为:PWM 舵机和串行总线舵机

9.2 舵机结构
舵机主要由以下几个部分组成:舵盘、外壳、直流电机、减速齿轮组、角度传感器、控制驱动电路和接口线缆等。常见的舵机内部结构如下图所示。

其中角度传感器负责舵机的位置反馈,直接装在舵机的主输出轴上,将轴旋转后产生的角度变化变成电压信号发回控制电路;

控制驱动电路:接收外部接口传来的信号和角度传感器反馈的电压值,以及驱动直流电机旋转;

减速齿轮组则是降低直流电机的转速并且放大扭矩;

市面上常见的廉价舵机通常采用小型的直流有刷电机和塑料材质减速齿轮组,传感器一般使用电位器返回模拟电压;而一些稍贵的则会使用金属齿轮组,一些高端的舵机内部甚至会采用无刷电机和磁电编码器。

9.3 舵机工作原理
模拟舵机和数字舵机内部电路不同,所以原理上稍有差别,这里以模拟舵机进行讲解。模拟舵机内部的控制驱动电路板从外界接收控制信号,经过处理后变为一个直流偏置电压,在控制板内部有一个基准电压,这个基准电压由电位器产生,将外部获得的直流偏置电压与电位器的电压进行比较获得电压差,并输出到电机驱动芯片驱动电机,电压差的正负决定电机的正反转,大小决定旋转的角度,电压差为0 时,电机停止转动。大致原理框图如下图所示。


从图中可以看到,舵机内部是闭环控制的,所以这一类电机实际上是一种位置(角度)伺服的简化版伺服电机,将工业伺服电机的三闭环控制简化成了只有一个位置闭环。舵机这个名字是国内
起的一种俗称,本质上属于伺服电机,它的英文就直接叫Servo,或者RC Servo。

9.4 舵机控制原理
舵机的输入有三根线,一般的中间的红色线为电源正极,咖啡色线的为电源负极,黄色色线为控制线号线。如下图所示。

舵机的控制通常采用PWM 信号,例如需要一个周期为20ms 的脉冲宽度调制(PWM),脉冲宽度部分一般为0.5ms-2.5ms 范围内的角度控制脉冲部分,总间隔为2ms。当脉冲宽度为1.5ms
时,舵机旋转至中间角度,大于1.5ms 时舵机旋转角度增大,小于1.5ms 时舵机旋转角度减小。舵机分90°、180°、270° 和360° 舵机,以180° 的舵机为例来看看脉冲宽度与角度的关系,见下
图所示。

上图中脉冲宽度与舵机旋转角度为线性关系,其他舵机控制脉冲也类似,0.5ms 对应0 度,2.5ms对应最大旋转角度,脉冲宽度与旋转角度也是线性关系。

9.5 舵机几个参数介绍
舵机速度的单位是sec/60°,就是舵机转过60° 需要的时间,如果控制脉冲变化宽度大,变化速度快,舵机就有可能在一次脉冲的变化过程中还没有转到目标角度时,而脉冲就再次发生了变化,舵机的转动速度一般有0.16sec/60°、0.12sec/60° 等,0.16sec/60° 就是舵机转动60° 需要0.16 秒的时间。旋转停留时间大于240ms/90度

舵机的速度还有工作电压有关,在允许的电压范围内,电压越大速度越快,反之亦然。

舵机扭矩的单位是KG*CM,这是一个扭矩的单位,可以理解为在舵盘上距离舵机轴中心水平距离1CM 处,舵机能够带动的物体重量,如下图所示。


通常说的55g 舵机、9g 舵机等,这里的55g 和9g 指的是舵机本身的重量。

SG9g舵机参数

9.6 舵机基本控制实验

程序在其它程序的基础上修改,注释没有改,但功能能实现:

 

 

/*主程序main  */
// TIM—通用定时器-4路PWM输出应用
#include "stm32f10x.h"
//#include "bsp_led.h"
#include "bsp_GeneralTim.h"  
#include "bsp_rccclkconfig.h"
#include "bsp_systick.h"
/*** @brief  主函数* @param  无  * @retval 无*/
int main(void)
{/* led 端口配置 */ 
//	LED_GPIO_Config();HSE_SetSysClk( RCC_PLLMul_6 );/* 定时器初始化 */GENERAL_TIM_Init();while(1){ TIM_SetCompare4(TIM3,15);	SysTick_Delay_ms(3000);TIM_SetCompare4(TIM3,10);SysTick_Delay_ms(3000);	TIM_SetCompare4(TIM3,5);SysTick_Delay_ms(3000);	TIM_SetCompare4(TIM3,15);	SysTick_Delay_ms(3000);	TIM_SetCompare4(TIM3,20);SysTick_Delay_ms(3000);	TIM_SetCompare4(TIM3,25);SysTick_Delay_ms(3000);	}
}
/*********************************************END OF FILE**********************/
/*通用定时器TIM3  .C程序  */
#include "bsp_GeneralTim.h" static void GENERAL_TIM_GPIO_Config(void) 
{GPIO_InitTypeDef GPIO_InitStructure;//  // 输出比较通道1 GPIO 初始化
//	RCC_APB2PeriphClockCmd(GENERAL_TIM_CH1_GPIO_CLK, ENABLE);
//  GPIO_InitStructure.GPIO_Pin =  GENERAL_TIM_CH1_PIN;
//  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
//  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
//  GPIO_Init(GENERAL_TIM_CH1_PORT, &GPIO_InitStructure);
//	
//	// 输出比较通道2 GPIO 初始化
//	RCC_APB2PeriphClockCmd(GENERAL_TIM_CH2_GPIO_CLK, ENABLE);
//  GPIO_InitStructure.GPIO_Pin =  GENERAL_TIM_CH2_PIN;
//  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
//  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
//  GPIO_Init(GENERAL_TIM_CH2_PORT, &GPIO_InitStructure);
//	
//	// 输出比较通道3 GPIO 初始化
//	RCC_APB2PeriphClockCmd(GENERAL_TIM_CH3_GPIO_CLK, ENABLE);
//  GPIO_InitStructure.GPIO_Pin =  GENERAL_TIM_CH3_PIN;
//  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
//  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
//  GPIO_Init(GENERAL_TIM_CH3_PORT, &GPIO_InitStructure);// 输出比较通道4 GPIO 初始化RCC_APB2PeriphClockCmd(GENERAL_TIM_CH4_GPIO_CLK, ENABLE);GPIO_InitStructure.GPIO_Pin =  GENERAL_TIM_CH4_PIN;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GENERAL_TIM_CH4_PORT, &GPIO_InitStructure);
}///*
// * 注意:TIM_TimeBaseInitTypeDef结构体里面有5个成员,TIM6和TIM7的寄存器里面只有
// * TIM_Prescaler和TIM_Period,所以使用TIM6和TIM7的时候只需初始化这两个成员即可,
// * 另外三个成员是通用定时器和高级定时器才有.
// *-----------------------------------------------------------------------------
// *typedef struct
// *{ TIM_Prescaler            都有
// *	TIM_CounterMode			     TIMx,x[6,7]没有,其他都有
// *  TIM_Period               都有
// *  TIM_ClockDivision        TIMx,x[6,7]没有,其他都有
// *  TIM_RepetitionCounter    TIMx,x[1,8,15,16,17]才有
// *}TIM_TimeBaseInitTypeDef; 
// *-----------------------------------------------------------------------------
// *//* ----------------   PWM信号 周期和占空比的计算--------------- */
// ARR :自动重装载寄存器的值
// CLK_cnt:计数器的时钟,等于 Fck_int / (psc+1) = 72M/(psc+1)
// PWM 信号的周期 T = ARR * (1/CLK_cnt) = ARR*(PSC+1) / 72M
// 占空比P=CCR/(ARR+1)static void GENERAL_TIM_Mode_Config(void)
{// 开启定时器时钟,即内部时钟CK_INT=72MGENERAL_TIM_APBxClock_FUN(GENERAL_TIM_CLK,ENABLE);/*--------------------时基结构体初始化-------------------------*/// 配置周期,这里配置为100KTIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;// 自动重装载寄存器的值,累计TIM_Period+1个频率后产生一个更新或者中断TIM_TimeBaseStructure.TIM_Period=GENERAL_TIM_Period;	// 驱动CNT计数器的时钟 = Fck_int/(psc+1)TIM_TimeBaseStructure.TIM_Prescaler= GENERAL_TIM_Prescaler;	// 时钟分频因子 ,配置死区时间时需要用到TIM_TimeBaseStructure.TIM_ClockDivision=TIM_CKD_DIV1;		// 计数器计数模式,设置为向上计数TIM_TimeBaseStructure.TIM_CounterMode=TIM_CounterMode_Up;		// 重复计数器的值,没用到不用管TIM_TimeBaseStructure.TIM_RepetitionCounter=0;	// 初始化定时器TIM_TimeBaseInit(GENERAL_TIM, &TIM_TimeBaseStructure);/*--------------------输出比较结构体初始化-------------------*/	// 占空比配置
//	uint16_t CCR1_Val = 5;
//	uint16_t CCR2_Val = 4;
//	uint16_t CCR3_Val = 3;
//200个脉冲式20ms,1.5ms是15个脉冲0度;
//1ms=10脉冲=-45度;0.5ms=5脉冲=-90度;20脉冲=45度;25脉冲=90度uint16_t CCR4_Val = 10;TIM_OCInitTypeDef  TIM_OCInitStructure;// 配置为PWM模式1TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;// 输出使能TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;// 输出通道电平极性配置	TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;// 输出比较通道 1
//	TIM_OCInitStructure.TIM_Pulse = CCR1_Val;
//	TIM_OC1Init(GENERAL_TIM, &TIM_OCInitStructure);
//	TIM_OC1PreloadConfig(GENERAL_TIM, TIM_OCPreload_Enable);// 输出比较通道 2
//	TIM_OCInitStructure.TIM_Pulse = CCR2_Val;
//	TIM_OC2Init(GENERAL_TIM, &TIM_OCInitStructure);
//	TIM_OC2PreloadConfig(GENERAL_TIM, TIM_OCPreload_Enable);// 输出比较通道 3
//	TIM_OCInitStructure.TIM_Pulse = CCR3_Val;
//	TIM_OC3Init(GENERAL_TIM, &TIM_OCInitStructure);
//	TIM_OC3PreloadConfig(GENERAL_TIM, TIM_OCPreload_Enable);// 输出比较通道 4TIM_OCInitStructure.TIM_Pulse = CCR4_Val;TIM_OC4Init(GENERAL_TIM, &TIM_OCInitStructure);TIM_OC4PreloadConfig(GENERAL_TIM, TIM_OCPreload_Enable);// 使能计数器TIM_Cmd(GENERAL_TIM, ENABLE);
}void GENERAL_TIM_Init(void)
{GENERAL_TIM_GPIO_Config();GENERAL_TIM_Mode_Config();		
}/*********************************************END OF FILE**********************/
/*通用定时器TIM3  .h程序  */
#ifndef __BSP_GENERALTIME_H
#define __BSP_GENERALTIME_H#include "stm32f10x.h"/************通用定时器TIM参数定义,只限TIM2、3、4、5************/
// 当使用不同的定时器的时候,对应的GPIO是不一样的,这点要注意
// 我们这里默认使用TIM3#define            GENERAL_TIM                   TIM3
#define            GENERAL_TIM_APBxClock_FUN     RCC_APB1PeriphClockCmd
#define            GENERAL_TIM_CLK               RCC_APB1Periph_TIM3
#define            GENERAL_TIM_Period            200-1
#define            GENERAL_TIM_Prescaler         7200TIM3 输出比较通道1
//#define            GENERAL_TIM_CH1_GPIO_CLK      RCC_APB2Periph_GPIOA
//#define            GENERAL_TIM_CH1_PORT          GPIOA
//#define            GENERAL_TIM_CH1_PIN           GPIO_Pin_6TIM3 输出比较通道2
//#define            GENERAL_TIM_CH2_GPIO_CLK      RCC_APB2Periph_GPIOA
//#define            GENERAL_TIM_CH2_PORT          GPIOA
//#define            GENERAL_TIM_CH2_PIN           GPIO_Pin_7TIM3 输出比较通道3
//#define            GENERAL_TIM_CH3_GPIO_CLK      RCC_APB2Periph_GPIOB
//#define            GENERAL_TIM_CH3_PORT          GPIOB
//#define            GENERAL_TIM_CH3_PIN           GPIO_Pin_0// TIM3 输出比较通道4
#define            GENERAL_TIM_CH4_GPIO_CLK      RCC_APB2Periph_GPIOB
#define            GENERAL_TIM_CH4_PORT          GPIOB
#define            GENERAL_TIM_CH4_PIN           GPIO_Pin_1/**************************函数声明********************************/void GENERAL_TIM_Init(void);#endif	/* __BSP_GENERALTIME_H */
/*RCC晶振8M改为12MHz  .C程序  */
#include "bsp_rccclkconfig.h"void HSE_SetSysClk( uint32_t RCC_PLLMul_x )
{ErrorStatus HSEStatus;// 把RCC 寄存器复位成复位值RCC_DeInit();	// 使能 HSE RCC_HSEConfig(RCC_HSE_ON);HSEStatus = RCC_WaitForHSEStartUp();if( HSEStatus == SUCCESS ){// 使能预取指FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable);FLASH_SetLatency(FLASH_Latency_2);RCC_HCLKConfig(RCC_SYSCLK_Div1);RCC_PCLK1Config(RCC_HCLK_Div2);RCC_PCLK2Config(RCC_HCLK_Div1);// 配置 PLLCLK = HSE * RCC_PLLMul_xRCC_PLLConfig(RCC_PLLSource_HSE_Div1, RCC_PLLMul_x);// 使能PLLRCC_PLLCmd(ENABLE);// 等待PLL稳定while( RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET );// 选择系统时钟RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);while( RCC_GetSYSCLKSource() != 0x08 );}else{/* 如果HSE 启动失败,用户可以在这里添加处理错误的代码 */}
}void HSI_SetSysClk( uint32_t RCC_PLLMul_x )
{__IO uint32_t HSIStatus = 0;// 把RCC 寄存器复位成复位值RCC_DeInit();	// 使能 HSI RCC_HSICmd(ENABLE);HSIStatus = RCC->CR & RCC_CR_HSIRDY;if( HSIStatus == RCC_CR_HSIRDY ){// 使能预取指FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable);FLASH_SetLatency(FLASH_Latency_2);RCC_HCLKConfig(RCC_SYSCLK_Div1);RCC_PCLK1Config(RCC_HCLK_Div2);RCC_PCLK2Config(RCC_HCLK_Div1);// 配置 PLLCLK = HSE * RCC_PLLMul_xRCC_PLLConfig(RCC_PLLSource_HSI_Div2, RCC_PLLMul_x);// 使能PLLRCC_PLLCmd(ENABLE);// 等待PLL稳定while( RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET );// 选择系统时钟RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);while( RCC_GetSYSCLKSource() != 0x08 );}else{/* 如果HSI 启动失败,用户可以在这里添加处理错误的代码 */}
}void MCO_GPIO_Config(void)
{GPIO_InitTypeDef  GPIO_InitStruct;RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);GPIO_InitStruct.GPIO_Pin = GPIO_Pin_8;GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_PP;GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOA, &GPIO_InitStruct);	
}
/*RCC晶振8M改为12MHz  .h程序  */
#ifndef __BSP_RCCCLKCONFIG_H
#define __BSP_RCCCLKCONFIG_H#include "stm32f10x.h"void HSE_SetSysClk( uint32_t RCC_PLLMul_x );
void MCO_GPIO_Config(void);
void HSI_SetSysClk( uint32_t RCC_PLLMul_x );
#endif /*__BSP_RCCCLKCONFIG_H */
/*systick延时  .C程序  */
#include "bsp_systick.h"#if 0
static __INLINE uint32_t SysTick_Config(uint32_t ticks)
{ //  判断 tick 的值是否大于 2^24,如果大于,则不符合规则if (ticks > SysTick_LOAD_RELOAD_Msk)  return (1);// 初始化reload寄存器的值	SysTick->LOAD  = (ticks & SysTick_LOAD_RELOAD_Msk) - 1;// 配置中断优先级,配置为15,默认为最低的优先级NVIC_SetPriority (SysTick_IRQn, (1<<__NVIC_PRIO_BITS) - 1); // 初始化counter的值为0	SysTick->VAL   = 0; // 配置 systick 的时钟为 72M// 使能中断// 使能systickSysTick->CTRL  = SysTick_CTRL_CLKSOURCE_Msk | SysTick_CTRL_TICKINT_Msk   | SysTick_CTRL_ENABLE_Msk;                    return (0);                                                 
}
#endifvoid SysTick_Delay_us(uint32_t us)
{uint32_t i;SysTick_Config(72);for(i=0; i<us; i++){while( !((SysTick->CTRL) & (1<<16)) );}SysTick->CTRL &= ~ SysTick_CTRL_ENABLE_Msk;
}void SysTick_Delay_ms(uint32_t ms)
{uint32_t i;SysTick_Config(72000);for(i=0; i<ms; i++){while( !((SysTick->CTRL) & (1<<16)) );}SysTick->CTRL &= ~ SysTick_CTRL_ENABLE_Msk;
}
/*systick延时  .h程序  */
#ifndef __BSP_SYSTICK_H
#define __BSP_SYSTICK_H#include "stm32f10x.h"
#include "core_cm3.h"void SysTick_Delay_us(uint32_t us);
void SysTick_Delay_ms(uint32_t ms);#endif /* __BSP_SYSTICK_H */

 


http://www.ppmy.cn/news/175959.html

相关文章

手机连接ftp文件服务器,手机链接ftp服务器地址

手机链接ftp服务器地址 内容精选 换一换 通过公网连接云手机实例时,弹性公网IP绑定在服务器上,因此需要先建立SSH隧道,即ADB方式(公网)包括两个步骤:建立SSH隧道;通过ADB连接云手机。关于SSH隧道和ADB的介绍请参见“基本概念”。用于连接云手机的设备可以为本地设备,也可…

咖啡知识大全

咖啡知识大全 听说咖啡产代码?哈哈哈 也许吧! 每天除了工作,当然也要有自己的小喜好 喜欢清晨来一杯现磨咖啡,那香气足以叫醒我的身体,开始美好的一天! 工欲善其事必先利其器,那就先探索咖啡的起源和文化 咖啡的分类&#xff1a; 咖啡树大致可分为5种&#xff0c;其中…

Barsetto百胜图BAV01咖啡机——效率超神buff获取攻略

Barsetto百胜图BAV01咖啡机自投放上市以来&#xff0c;就备受国内消费者喜爱&#xff0c;成为精英人士竞相追捧的咖啡消费理想选择。越来越多的咖啡爱好者都开始热爱这种咖啡购买方式&#xff0c;很多没有体验过的咖啡专业人士&#xff0c;也开始注意到这款极具市场竞争力的最新…

Barsetto百胜图美式便携咖啡机,总有这杯在身边

咖啡的需求无时不在、无处不在&#xff0c;当我们工作时&#xff0c;来杯咖啡可以提神醒脑&#xff1b;当我们在家无聊时&#xff0c;来杯咖啡可以细细品味思考人生&#xff1b;当我们外出旅行时&#xff0c;来杯咖啡可以缓解疲劳。 为求得一杯好咖啡&#xff0c;真的煞费苦心&…

Barsetto百胜图智能胶囊咖啡机测评香浓不必久候

作为咖啡控的我&#xff0c;经常去星巴克喝咖啡&#xff0c;不过忙的时候真没有时间去&#xff0c;有时候在想如果自己买个咖啡机在家煮&#xff0c;岂不是很有情调&#xff1f;虽然我爱喝咖啡&#xff0c;但是真的对煮咖啡不懂行&#xff0c;如何有比较智能的轻松可以操作的咖…

PID 控制的“开源咖啡机”

工程师 Gleb Polyakove 和 Igor Zamlinsky 的新项目借助于 KickStarter 平台&#xff0c;筹集了 30 多万的资金&#xff0c;远远超过他们预计的 16 倍。他们的产品为什么如此受欢迎&#xff1f; 一台 PID 控制的 Espresso 咖啡机。 在筹资页面上&#xff0c;Gleb 和 Igor 指出&…

痛点不去,自助咖啡机恐难成气候?

我国咖啡行业发展得有点晚&#xff0c;最近十几年来才开始进入快速发展的时期。据前瞻产业研究院数据显示&#xff0c;2004年中国咖啡行业产值才1.94亿元&#xff0c;而2015年产值已达到13.55亿元&#xff0c;其中在2011年时创下历史新高&#xff0c;达到17.68亿元&#xff0c;…

PrimaDonna智能咖啡机,咖啡也要私人定制

土豪&#xff0c;赐我一杯用PrimaDonna自制的咖啡可好&#xff1f; “咖啡”一词源于希腊语“Kaweh”&#xff0c;表示“力量与热情”。人们日常饮用的咖啡其实就是咖啡豆配合不同的烹煮器制作出来的。如今在世界各地&#xff0c;越来越多的人喜欢喝咖啡。所谓的“咖啡文化”也…