使用STM32F103C8T6控制舵机丝滑运转附代码

舵机原理

当你刚刚接触单片机的时候,是不是常常会看到“控制舵机”这种字样,好像控制舵机在嵌入式领域就跟今天吃的面包不是馒头一样简单,但是要是盲目乱搞结果就是狠狠熬几个大夜然后进动物园跟熊猫抢位置。

那舵机到底是什么呢?

实际上,舵机是由直流电机、减速齿轮组、传感器(可变电阻)和控制电路组成的一套自动控制系统。工作流程为: 控制信号→控制电路板→电机转动→齿轮组减速→舵盘转动→位置反馈电位计→控制电路板反馈→电机转动。

类似PID闭环控制。

其实这些也不重要,咱们现在主要考虑如何使用。

舵机只能在一定角度内转动(有最大旋转角度比如:180度,可能会有不同,但是咱们这篇文章就按180°来,后文的180°如果你的舵机有说明不是180°,就都替换掉就好。),不能一圈圈转。相比起来,直流电机是一圈圈转动的。

舵机的输入线共有三条,红色中间,是电源正线,一根棕色(有些是黑色)是电源地线,另外一根线是控制信号线,一般为桔黄色,这根就是我们输出PWM的信号线,咱们调制的PWM就是通过这根线体现效果的。

好了,下面进入重点了!注意注意!

首先你要尝试理解一句话:一般PWM的周期是20ms,那么对应的频率是50hz。改变不同的占空比就可以控制转动的角度。其中占空比从0.5-2.5ms,相对应的舵盘位置为0-180度,呈线性变化。

好家伙,你倒是挺简洁,但是为什么呢?

下面我们来逐步分析

我们使用的是STM32F103C8T6板子,自己设计的电路板,所以不存在经典电路板的使用方法的问题,各位有问题请咨询相关技术员(龟缩ing……)

好的,有了这个前提,我们知道,F103芯片频率可达72MHz。

搞PWM要用到定时器对吧,那定时器有2个比较崎岖的参数要调整,一个是period,一个是prescaler

这里令period=10000-1,prescaler=144-1

至于为什么?请别着急找原因,继续看你就知道了,但如果你看完还是有疑问,恭喜你,你已经是个热爱提问的好孩子了!进一步的解释在你未来的工程师道路上会由经验得出的,这里是为了简单,仅此而已。

至于为什么要简单?答案是,不可说,不可说……

言归正传,这样设设置之后,定时器的输出频率为72M/(period+1)/(prescaler+1)=50Hz

50Hz=>20ms

这里的20可不是我们最后需要的,我们想要的是20ms/(period+1)=0.002ms

好的,这样一来,掏出我们刚刚定义好的180°。

舵机在当前PWM比较值下能转到角度是:angle=(PWM*0.002ms-0.5ms)/(2.5ms-0.5ms)*180°

理解定时器

好了,这么解释一下,对于好奇宝宝来说还是不够的,那么接下来就要继续深入了!

PWM是什么呢?

如果你看过相关代码就会知道,这个是

__HAL_TIM_SET_COMPARE(&htimx,TIM_CHANNEL_1,100)

当中100所代表的部分,也就是所谓的PWM比较值,和

sConfigOC.Pulse=100;

是一样的作用。

好嘞,那么咱们要继续解决刚刚提出的period和prescaler喽。

TIM_Prescaler:定时器预分频器设置,时钟源经该预分频器才是定时器时钟,可设置范围为 0 至 65535,实现 1 至 65536 分频。

TIM_Period:定时器周期,实际就是设定自动重载寄存器的值,可设置范围为 0 至 65535。通过period次系统的运行,就是20ms(为什么是20ms,因为这是一个例子,和下面的一样)

时钟的频率是72MHZ,可以理解为一秒钟STM32会自己数72M次。

举个例子,如果分频系数是143,则该时钟的频率会变成72MHZ/144=500000HZ,也就意味着STM32在一秒钟会数500000次,即2us数一次。

每2us数一次,一共数10000次就得到了20ms,20ms=2us*10000,那么预装载值就是10000-1。

所以你知道为什么刚刚20ms/(period+1)=0.002ms。

OK捏!解释就到此结束啦。

实战代码

下面给出我的实验环境和实验要求:

老板让我写一个舵机控制程序,控制舵机0-90°往复运动,每次到达0°和90°停滞较长时间,一个往复count+1,要丝滑,要能准确计数。

我用的是keil,首先新建一个文件写下面的代码,你会看到有一些#define DELAY之类的,这个你自己来吧!

这个函数在头文件里面声明好之后,写在主函数main的while里面,在主函数进入while之前记得打开定时器!

HAL_TIM_PWM_Start(&htim2,TIM_CHANNEL_4);
int cnt=0;//计数值
int cmp=START;//比较值
int flag=0;//是否改变比较值的标志
int flag_last=0;//和后续按键处理有关

void count()
{
	button_key_scan();//按键检测,控制flag
	if(flag==1)
		{
			if(cmp<END)cmp++;//要严谨,不能直接飞出去了
			Key_Delay(LONG_DELAY);//延时
			__HAL_TIM_SET_COMPARE(&htim2,TIM_CHANNEL_4,cmp);//改变比较值
			if(cmp>=END)//触发一次
			{
				cmp=END;
				cnt++;//触发的话,count就会+1
				flag=2;
				printf("count=%d\n",cnt);
				HAL_Delay(SHORT_DELAY);
			}
			flag_last=flag;
		}
		else if(flag==2)
		{
			if(cmp>0)cmp--;
			Key_Delay(LONG_DELAY);
			__HAL_TIM_SET_COMPARE(&htim2,TIM_CHANNEL_4,cmp);
			if(cmp<=START)
			{
				cmp=START;
				HAL_Delay(SHORT_DELAY);
				//printf("count=\n");
				flag=1;
			}
			flag_last=flag;
		}
		else if(flag==0)
		{
			__HAL_TIM_SET_COMPARE(&htim2,TIM_CHANNEL_4,ZERO_ANGLE);
			flag_last=flag;
		}
}

大家如果任何建议或者想法,欢迎留言!

  • 14
    点赞
  • 34
    收藏
    觉得还不错? 一键收藏
  • 6
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值