电子说
舵机:
舵机一般由舵盘、减速齿轮组、位置反馈电位器、直流电机、控制电路板等组成。一般情况下舵机的信号线为黄色或者白色,电源主要常见为4.2-7.4V,不同的供电将直接影响舵机的扭矩标准。
控制方法-PWM :
PWM通过占空比来控制舵机,所谓PWM就是通过程序控制单片机IO口按照一定的时间规律输出高电平或低电平,具体可以上网查阅资料了解一下。
以下为不同的占空比时间对应的舵机角度:
对于t=0.5 - 2.5ms的产生,写程序时我们可以采用全局变量。让全局变量等于525之间,因为舵机的一个计数周期是0.1ms,这样全局变量的525正好就是0.5~2.5ms
PWM波产生思路:将信号管脚线初始化为低电平,然后写一个while循环,在循环中将该管脚置为为高电平,延时,再拉低为低电平,如此循环产生PWM波,以高电平产生时间来控制舵机转动角度。
注意:5mv以上的控制电压的变化就会引起电机的抖动。
基于单片机的控制:
单片机系统实现对舵机输出转角的控制,必须先完成两个任务:
1、产生PWM周期信号,本设计产生一个20ms的周期信号;
2、脉宽的调整,即单片机模拟PWM信号的输出,并调整占空比。
当系统中只需要实现一个舵机的控制,采用的控制方式是改变单片机的一个定时器中断的初值,将20ms分为两次中断执行,一次短定时中断和一次长定时中断。这样既节省了硬件电路,也减少了软件开销,控制系统工作效率和控制精度都很高。
具体的设计过程:例如想让舵机转向左极限的角度,它的正脉冲为2ms,则负脉冲为20ms-2ms=18ms,所以开始时在控制口发送高电平,然后设置定时器在2ms后发生中断,中断发生后,在中断程序里将控制口改为低电平,并将中断时间改为18ms,再过18ms进入下一次定时中断,再将控制口改为高电平,并将定时器初值改为2ms,等待下次中断到来,如此往复实现PWM信号输出到舵机。用修改定时器中断初值的方法巧妙形成了脉冲信号,调整时间段的宽度便可使伺服机灵活运动。
为保证软件在定时中断里采集其他信号,并且使发生PWM信号的程序不影响中断程序的运行(如果这些程序所占用时间过长,有可能会发生中断程序还未结束,下次中断又到来的后果),所以需要将采集信号的函数放在长定时中断过程中执行,也就是说每经过两次中断执行一次这些程序,执行的周期还是20ms。
如果系统中需要控制几个舵机的准确转动,可以用单片机和计数器进行脉冲计数产生PWM信号。
脉冲计数可以利用51单片机的内部计数器来实现,但是从软件系统的稳定性和程序结构的合理性看,宜使用外部的计数器,还可以提高CPU的工作效率。
下面列举一个按键控制舵机转动的程序代码:
#include
#include
typedef unsigned char uchar;
typedef unsigned int uint;
sbit KEY1=P3^4;
//按键1
sbit KEY2=P3^5;
//按键2
sbit PWM_OUT=P2^7;
//PWM输出口
uint PWM_Value;
//定义pwm值
uchar order=0;
void Delay(unsigned int s);
//延时函数声明
uchar flag;
//舵机按键标志
/ 延时函数 /
void Delay(unsigned int s)
{
unsigned int i;
for(i=0; i
for(i=0; i
}
/ 定时器初始化 /
void Init_Timer0()
{
TMOD=0x11;
TH0=(65536-1500)/256;
TL0=(65536-1500)%256;
EA = 1;
ET0 = 1;
TR0 = 1;
PT0=1;
}
/ 主函数 /
void main(void)
{
Delay(6000);
PWM_Value = 1500;
//pwm初值为1500
Init_Timer0();
while(1)
{
if((KEY1 ==0 )|(KEY2 ==0 ))
//按键1或按键2被按下
{
if(KEY1 ==0 )
//确认按键1被按下
{
flag = 1;
//标志位赋值1
}
if(KEY2 ==0 )
//确认按键2被按下
{
flag = 2;
//标志位赋值2
}
}
else
{
flag = 0;
//否则标志位为0
}
Delay(20);
//延时20ms
}
}
/ 中断程序 **/
void timer0(void) interrupt 1
{
if(flag==1) PWM_Value += 1;
//如果标志位1时,pwm的值加1
if(flag==2) PWM_Value -= 1;
//如果标志位为2时,pwm减1
if(PWM_Value>=2500)
//如果pwm的值大于2500
PWM_Value = 2500;
//则保持在2500
if(PWM_Value<=500)
//如果pwm的值小于500
PWM_Value=500;
//则保持在500
switch(order)
{
case 1:PWM_OUT=1;
TH0=(65536-PWM_Value) > >8;
TL0=(uchar)(65536-PWM_Value);
break;
case 2:PWM_OUT=0;
TH0=(65536-(5000-PWM_Value)) > >8;
TL0=(uchar)(65536-(5000-PWM_Value));
break;
case 3:
TH0=60536 > >8;
TL0=(uchar)60536;
break;
case 4:
TH0=60536 > >8;
TL0=(uchar)60536;
order=0;
break;
default: order=0;
break;
}
order++;
}
全部0条评论
快来发表一下你的评论吧 !