stm32如何控制舵机转动到指定角度?

推荐两个非常好的参考资料:
舵机工作原理
舵机控制
STM32如何配置PWM
关于舵机

STM32定时器定时计算公式
Tout = ((arr+1)*(psc+1))/Tclk ;
其中:
Tclk:定时器的输入时钟频率(单位MHZ) eg;stm32f103RCT6为72MHz
Tout:定时器溢出时间(单位为us)
.TIM_Period = arr; eg;4999
.TIM_Prescaler = psc; eg:7199

Tout = ((4999+1)×(7199+1))/72 = 500000us = 500ms 。
如何理解这个公式?
Tout = ((arr+1) * (psc+1))/Tclk ;
= (arr+1)* [(psc+1)/Tclk ]
PWM的周期=需要多少节拍数 *多久产生一个节拍
其中:
(arr+1)可以理解为需要多少节拍数
[(psc+1)/Tclk ]可以理解为多久产生一个节拍,这就要设置时钟了
分析:
采用的是stm32f103RCT6起产生节拍的频率为72MHz,也就是1/72000000 秒=1/72微妙 产生一次节拍,对应舵机来说,频率太快也就是周期太短,所有需要分频,也就是降低到适当的频率用来产生PWM信号控制舵机,
Tclk为72MHz
Tclk /(psc+1) 为分频后的频率
(psc+1)/Tclk分频后的周期,也就是这么久产生一个节拍
所以PWM的周期=需要多少节拍数 * 多久产生一个节拍
看资料可知,舵机的周期为20ms,高电平占比跨距2ms(0.5ms——2.5ms),在这个跨距对应舵机的180°
0.5ms----------- 0°
1.0ms----------- 45°
1.5ms----------- 90°
2.0ms-----------135°
2.5ms-----------180°
就变成了一个题目:
当 Tclk=72M时,怎么来选取合适的arr(要求小于65535),psc(要求小于65535),使得PWM的周期为20ms,高电平占比跨距2ms(0.5ms——2.5ms),而且要精细,也就是更多的节拍表示小量程,如果把20ms看作是大量程,跨距2ms是其中一段小量程,那么每个节拍就是精度了,求角度和节拍的对应关系?
解:
20ms={(arr+1) * [(psc+1)/72000000] }s= {(arr+1) *[(psc+1)/72000] }ms
也就是:
20={(arr+1) * [(psc+1)/72000] }
也就是:
(arr+1) * (psc+1)=1440000

1)选取pas+1=1440则arr+1=1000,也就是1000个节拍表示20ms,那50个节拍就是1ms,小量程是2ms,也就是100个节拍
2)选取pas+1=144则arr+1=10000,也就是10000个节拍表示20ms,那500个节拍就是1ms,小量程是2ms,也就是1000个节拍,比第一种取法更精细,所以我采用这种
也就是:pas=144-1;arr=10000-1;500个节拍1ms也就是1000us,对应就是1个节拍2us
当0.5ms时,也就是比较值为250的时候,舵机转动的角度为0°,时间每0.5ms=500us增加对应角度45°的增加,即1us=0.09°2us=0.18°=1个节拍

PWM的比较值(看作节拍)和角度的关系:
1个节拍=0.18°
角度为N时,对应的节拍是(N/0.18)

如下:
时间 ----------------------- 角度——— 节拍(Compare)
0.5ms(500us)----------- 0°————250
1.0ms(1000us)----------- 45°———250+45/0.18=250+250
1.5ms(1500us)----------- 90°———250+90/0.18=250+500
2.0ms(2000us)-----------135°———250+135/0.18=250+750
2.5ms(2500us)-----------180°———250+180/0.18=250+1000
总结:
每行递增500us,45°即250个节拍
Compare1=250+(N/0.18)

void SetAngle(int N)//0<=N<=180
{
TIM_SetCompare1(TIM3,250+(N/0.18));
}
配置代码如下:

void TIM3_PWM_Init(u16 arr,u16 psc)
{  
	GPIO_InitTypeDef GPIO_InitStructure;
	TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
	TIM_OCInitTypeDef  TIM_OCInitStructure;

	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);// 使能定时器3外设时钟使能
 	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC , ENABLE);  //使能GPIO外设时钟使能
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO , ENABLE); //使能复用时钟使能
	   
   GPIO_PinRemapConfig(GPIO_FullRemap_TIM3 , ENABLE);	//完全重映射

   //设置该引脚为复用输出功能,输出TIM3 CH1的PWM脉冲波形
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6; //TIM_CH1
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;  //复用推挽输出
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOC, &GPIO_InitStructure);
//配置定时器,确定周期,周期的节拍数,和产生节拍的频率
	TIM_TimeBaseStructure.TIM_Period = arr; //设置在下一个更新事件装入活动的自动重装载寄存器周期的值
	TIM_TimeBaseStructure.TIM_Prescaler =psc; //设置用来作为TIMx时钟频率除数的预分频值  
	TIM_TimeBaseStructure.TIM_ClockDivision = 0; //设置时钟分割:TDTS = Tck_tim
	TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;  //TIM向上计数模式
	TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure); //根据TIM_TimeBaseInitStruct中指定的参数初始化TIMx的时间基数单位

 //设置TIM3_CH1的PWM模式,使能TIM3的CH1输出,配置输出比较通道,PWM模式,有效电平等:
	TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; //选择定时器模式:TIM脉冲宽度调制模式1
	TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //比较输出使能
	TIM_OCInitStructure.TIM_Pulse = 0; //设置待装入捕获比较寄存器的脉冲值
	TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; //输出极性:TIM输出比较极性高
	TIM_OC1Init(TIM3, &TIM_OCInitStructure);  //根据TIM_OCInitStruct中指定的参数初始化外设TIMx

    TIM_CtrlPWMOutputs(TIM3,ENABLE);	//MOE 主输出使能	

	TIM_OC1PreloadConfig(TIM3, TIM_OCPreload_Enable);  //CH1预装载使能	 
	
	TIM_ARRPreloadConfig(TIM3, ENABLE); //使能TIMx在ARR上的预装载寄存器
	
	TIM_Cmd(TIM3, ENABLE);  //使能TIM3
  
}

输入角度,转化成PWM的比较值,控制高电平占空的占比,从而达到想要的角度

void  SetAngle(int N)//N<180 
{
	TIM_SetCompare1(TIM3,250+(N/0.18));	                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                
}

主函数初始化
采用第二种方式:选取pas=144-1;arr=10000-1;

TIM3_PWM_Init(10000-1,144-1);//计数1次代表2us代表0.18°

扩展一下……
参考:PPM信号介绍
1,PWM信号可以控制舵机和电机,但有区别
舵机的PWM是有周期要求,一般是20ms,而有效脉宽是2ms,这2us就是2000us,脉宽跨度不是从0us开始的,而是500us到2500us,对应角度 0°到180°
时间 ----------------------- 角度——— 节拍(Compare)
0.5ms(500us)----------- 0°————250
1.0ms(1000us)----------- 45°———250+45/0.18=250+250
1.5ms(1500us)----------- 90°———250+90/0.18=250+500
2.0ms(2000us)-----------135°———250+135/0.18=250+750
2.5ms(2500us)-----------180°———250+180/0.18=250+1000
假如是Xus

2,航模接收机输出的PWM,周期一般是20ms, 20ms就是50HZ,但有效脉宽是1ms,也就是1000us,脉宽跨度也不是从0us开始的,而是1000us到2000us,如果用这种PWM信号去驱动舵机,只能使舵机在 45°到135°范围活动,即转动90°,一般固定翼有90°的转动空间也够了。
1.0ms(1000us)----------- 45°———250+45/0.18=250+250
1.5ms(1500us)----------- 90°———250+90/0.18=250+500
2.0ms(2000us)-----------135°———250+135/0.18=250+750
在这里插入图片描述
可知1:控制电调的信号是脉宽,而不是频率,比如:频率高,意味着周期T短,占空比=脉宽/周期,同样1ms的脉宽,周期越短,占空比越大。
在这里插入图片描述

在这里插入图片描述

可知2:频率是有限的,即周期不能无限短,当占空比是百分之百时,脉宽信号=周期=2ms,即500hz,为了延续1ms-2ms的脉宽,所以只更改频率,频率设置为400hz,周期2.5ms,能容纳1ms-2ms的脉宽,留点余地,如果频率是800hz,对应的1.25ms,都容纳不了1ms-2ms的脉宽

可知3:输入给无刷电调的PWM频率不会影响电机的转速但会影响控制频率和精度,接收机或者飞控输出给电调的PWM基本只是起到一个信号传递的作用,传递的是脉宽这个信号,电调会根据这个脉宽与电调的内部算法还有驱动电路来驱动电机

3,当摇杆处于中位时,给出的是脉宽为1500us的信号, 比如油门打到底是1000us的信号,打到最上是2000us的信号,航模遥控器每个摇杆旁边都有个微调按键,如果调节了,那中间值就不是1500us,对应另外两个方向的极值也会随着变化。总之输出范围是围绕着中间值±500的范围。
4,接收机输出的PWM信号是不能直接控制电机的,虽然最终控制电机的信号也叫PWM,但两种信号是不同的了(参考航模无人机中PWM信号频率浅谈),接收机的PWM信号控制电调,电调转换成我们希望的电机驱动信号,并通过内部的电机驱动电路实现对电机的控制。再控制电机。
控制电机的PWM信号对周期没有严格要求,占空比变化范围0~100%;(猜想:对周期没要求,为兼容控制舵机的PWM信号,采用舵机的PWM周期,也可换其他周期,周期短,频率高,响应快)
而航模遥控器接收机输出的PWM信号(也是控制舵机、电调的PWM信号),周期一般是20ms,也有16ms的,正脉宽范围一般是1000us~2000us。
5,感觉上面两个图片里的描述有点矛盾,后面看到知乎这个人的评论,感觉
但是对于多旋翼,要求更高的控制频率和精度,如果PWM还是50HZ,会限制电调每秒钟调节的次数最多就50次,得不到很好的控制效果,所以多旋翼飞控在输出PWM的时候会采用更高的频率,像Pixhawk采用的是400HZ,
输入给无刷电调的PWM频率是否会影响电机的转速和控制频率等,答案是否定
前面说为了得到更高的控制频率和精度Pixhawk采用的是400HZ,后面又说PWM频率不会影响电机的转速和控制频率,有点懵了,,,,看了知乎这个人的猜测可知3:输入给电调的PWM频率不会影响电机的转速但会影响控制频率和精度
在这里插入图片描述
参考
无刷电调信号线的pwm信号是如何工作的?
在这里插入图片描述
电调有个识别的频率范围,支持50HZ~500HZ频率的PWM信号的输入,电调会把输入PWM转换成对应的油门量再做控制,电调的PWM输入是接收机或者飞控PWM的输出,遥控器的的摇杆可能也存在误差,不同遥控器的摇杆同样在拨到两端产生的AD值不一致,那它产生的PWM脉宽就不一致,假如理想是1000-2000,实际可能是900-1900,那就要根据这个实际行程来分配——油门行程校准。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值