MG90S 舵机180°角度驱动

文章详细介绍了MG90S这款数字舵机的工作原理,对比了它与模拟舵机的区别,强调了数字舵机在精度和响应速度上的优势。并提供了通过PWM波形控制舵机角度的方法,包括角度与占空比的转换公式,以及代码实现示例,展示了如何使用STM32单片机进行舵机控制。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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);
	}
}

### STM32 控制 MG996R 360度舵机实现精确角度控制 对于MG996R这类支持360度旋转的舵机而言,实际上并不像传统意义上的舵机那样能够被设定到某个具体的角度位置。相反,这种类型的舵机会响应PWM信号来改变其转速和转向[^2]。 然而,在某些应用场景下,如果希望模拟出近似于角度控制的效果,则可以通过调整PWM占空比的方式间接影响电机的速度以及方向,进而达到一定的定位效果。需要注意的是,这种方式并不能真正意义上做到精准的角度控制,而是通过时间累积的方式来接近目标位置。 为了使STM32成功驱动并调节MG996R的工作状态,需要配置定时器生成合适的PWM波形。通常情况下,设置频率为50Hz(即周期为20ms),并通过修改比较寄存器中的值来更改脉宽宽度从而改变输出电压比例[^3]。 下面是一个简单的C语言程序片段用于初始化TIM2作为PWM输出端口,并提供了一个函数`set_servo_angle()`用来发送不同占空比给定至指定通道: ```c #include "stm32f1xx_hal.h" #define SERVO_MIN_PULSEWIDTH (uint16_t)(0.5 * 84) /* Min Pulse width value */ #define SERVO_MAX_PULSEWIDTH (uint16_t)(2.5 * 84) /* Max pulse width value */ void MX_TIM2_Init(void); void set_servo_angle(float angle); int main(void){ HAL_Init(); SystemClock_Config(); MX_GPIO_Init(); MX_TIM2_Init(); while(1){ // Example usage of setting servo to different angles over time. for(int i=0;i<=180;i+=10){ set_servo_angle(i); HAL_Delay(500); // Wait half a second between each step change } for(int i=180;i>=0;i-=10){ set_servo_angle(i); HAL_Delay(500); } } } // Initialize TIM2 as PWM output on channel 1, with frequency at 50 Hz and period equals 20 ms. void MX_TIM2_Init(void){ __HAL_RCC_TIM2_CLK_ENABLE(); TIM_HandleTypeDef htim2; htim2.Instance = TIM2; htim2.Init.Prescaler = 72-1; // Set prescaler so that timer clock is 1MHz htim2.Init.CounterMode = TIM_COUNTERMODE_UP; htim2.Init.Period = 20000-1; // Period corresponds to 20ms @ 1MHz htim2.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1; if(HAL_TIM_PWM_Init(&htim2)!= HAL_OK){Error_Handler();} TIM_OC_InitTypeDef sConfigOC; sConfigOC.OCMode = TIM_OCMODE_PWM1; sConfigOC.Pulse = SERVO_MIN_PULSEWIDTH; // Initial duty cycle corresponding to minimum position sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH; sConfigOC.OCFastMode = TIM_OCFAST_DISABLE; if(HAL_TIM_PWM_ConfigChannel(&htim2,&sConfigOC,TIM_CHANNEL_1)!= HAL_OK){Error_Handler();} HAL_TIM_PWM_Start(&htim2,TIM_CHANNEL_1); } /* Function sets the desired 'angle' by adjusting the PWM signal sent out via Channel 1*/ void set_servo_angle(float angle){ uint16_t pulse_width; float slope=(SERVO_MAX_PULSEWIDTH-SERVO_MIN_PULSEWIDTH)/180.0; pulse_width=SERO_MIN_PULSEWIDTH+(slope*angle); __HAL_TIM_SET_COMPARE(htim2,TIM_CHANNEL_1,pulse_width); } ``` 上述代码实现了基本的功能框架,实际应用时可能还需要考虑更多细节因素如硬件连接方式、电源管理等。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值