MG90S 舵机180°角度驱动

MG90S简介

  1. 舵机
    是一种角度伺服电机,一般是由齿轮组、电位器、舵机控制电路、直流电机构成。由发送控制信号来控制输出轴的位置。
  2. 数字舵机与模拟舵机的区别:
    MG90S是一款常用的数字舵机,还有一款常用的模拟电机是MG90。
    ①数字舵机只需发送1次PWM信号就能转动到某个角度。
    模拟舵机是需要多次发送PWM信号才能够保持在规定的位置上。
    ②模拟舵机存在“无反应区”,对于细微的动作,反应非常迟钝,或者没有动作。
    数字舵机的“无反应区”更小,反应速度更快,加速和减速时也更快、更柔和。
    (原因是数字舵机的控制电路比模拟舵机的多了微处理器和晶振)
  3. 使用参数:
    舵机控制一般需要20ms左右的时基脉冲,高电平部分一般为0.5ms-2.5ms范围内的角度控制脉冲部分。总间隔为2ms。(此数据是0-180°的舵机)
0.5ms
1ms45°
1.5ms90°
2ms135 °
2.5ms180°

需求分析

  1. 需求:
    舵机通过PWM波型来控制,我们想要的是给舵机一个角度,让它自己转换成占空比。
  2. 实现:
    如下图所示:脉冲周期是20ms,高电平部分是2.5ms,表示180°。
    上文已提到(0°到180°)对应着(0.5ms-2.5ms)。
    假设角度为A,则A角度所占时间的比例为:(A/180)×(2.5-0.5),再加上0°初始时间,A角度所占的时间为0.5+(A/180) ×(2.5-0.5)时间基数是20ms,那么占空比为[0.5+(A/180) ×(2.5-0.5)]/20。
    上面计算的占空比,乘以20ms内总的定时器的计数次数,得到捕获比较寄存器(TIM_Pulse)的脉冲值,也就是A角度所占的定时器计数次数:[0.5+(A/180) ×(2.5-0.5)]/20×10000。10000是本设计设定的计数器的计数次数(详情见下文)。
  3. 分频系数和计数器设置:
    此设计使用的是72M的单片机,分频系数设为(144-1),72000000Hz/144=500000Hz,频率为500K,周期为1/500000=2us。计数次数为(10000-1),也就是10000次,2us×10000=20ms。也就是定时器的周期是20ms。
  4. 误差计算:
    当然定时器周期20ms,还有很多种设法。设计时,计数周期应该尽可能的大,这样计错一次数对舵机角度的影响越小(注意计数周期最大存在上限)。
    0-180°是0.5-2.5ms,量程是2ms,1度约为11.11us。计数器计数一次是2us, 2/11.11约为0.18度。也就是说计数器计数一次,约为0.18°。如果计数器计错一次,误差0.18°。所以本设计的误差0.18°,这对于一般的设计来说完全足够。
    在这里插入图片描述

代码实现

#include "SG90.h"

/*定时器1初始化*/
void TIM1_PWM_Init(u16 arr,u16 psc)
{  
	GPIO_InitTypeDef GPIO_InitStructure;
	TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;						//TimeBase初始化结构体
	TIM_OCInitTypeDef  TIM_OCInitStructure;									//Time输出比较初始化结构体
	
	//使能TIM1时钟
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE);			//使能Time1时钟
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA , ENABLE);  		//使能GPIO外设时钟
	
	//设置引脚为复用输出功能,输出TIM1 CH1的PWM脉冲波形
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; 								
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;  					//复用推挽输出
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOA, &GPIO_InitStructure); 
	TIM_DeInit(TIM1);	
	
	//设置TIM1的ARR和PSC
	TIM_TimeBaseStructure.TIM_Period = arr; 								//自动重装载寄存器周期的值
	TIM_TimeBaseStructure.TIM_Prescaler =psc; 								//预分频值
	TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; 		//设置时钟分割:TDTS = Tck_tim
	TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;		//向上计数模式
	TIM_TimeBaseInit(TIM1, &TIM_TimeBaseStructure); 					//初始化TIMx的时间基数单位
	
	TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM2; 				//选择定时器比较输出模式:TIM脉冲宽度调制模式2
	TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low; 	//输出极性:TIM输出比较极性高
	TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;	//比较输出使能
	TIM_OCInitStructure.TIM_Pulse = 750;										//初始计数值设为750,以防1度以内抖动

	TIM_OC2Init(TIM1, &TIM_OCInitStructure);  						//根据TIM_OCInitStruct中指定的参数初始化外设TIMx
	
	TIM_Cmd(TIM1, ENABLE);  										//使能TIM1
	TIM_CtrlPWMOutputs(TIM1,ENABLE);								//TIM外设的主输出开关 参数2:TIM外设主输出的新状态
	TIM_OC2PreloadConfig(TIM1,ENABLE);  							//在CCR1上启用或禁用TIMx外设预加载寄存器	 
	TIM_ARRPreloadConfig(TIM1, ENABLE); 							//在ARR上启用或禁用TIMx外设预加载寄存器
}

/*
	舵机角度控制
	传入参数:角度
*/
void SERVO_Angle_Control(uint8_t Angle)
{
	uint16_t temp=0;
	
	temp = Angle*50/9 + 250;		//(0.5+(A/180)*(2.5-0.5))/20*10000
	TIM_SetCompare2(TIM1, temp);	//TIM1的通道2,Compare2给了捕获/比较寄存器一个捕获值
}

#include "stm32f10x.h"   	// Device header
#include "SG90.h"
#include "Delay.h"

uint8_t Anglecount=0;		//定义角度初始值

int main(void)
{
	TIM1_PWM_Init(10000-1,144-1);	
	SERVO_Angle_Control(0);			//校正舵机

	while(1)
	{
		int i=0;
		SERVO_Angle_Control(0);
		delay_ms(1000);
		for(i=0;i<90;i++)
		{
			SERVO_Angle_Control(i);
		}
		SERVO_Angle_Control(90);
		delay_ms(1000);
	}
}

  • 1
    点赞
  • 29
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值