第一次小小的尝试——舵机控制

去年第二届机器人擂台赛不知怎么地打了酱油,看到生命童鞋基本上是独立做出了遥控小车——以手机为 上位机,通过蓝牙进行串口数据传送,搭建直流稳压模块和以 lm298n作为驱动模块(老实说,这些东西我是在这次才懂得,当初忘了在忙啥了,神马都没有主动去了解⊙﹏⊙b汗),对于那会的生命,这些东西独立捣鼓出来完全不是问题,因为现在我觉得我都能勉勉强强做出来(不过估计很多细节需要请教的。。。),除了焊了51单片机的最小系统外,本人的焊工经验基本等于0  =.=
这次比赛的分工着实让我充满动力和成就感! 生命,作为队长,将5个人分工为五个模块:阿杜负责驱动舵机的317驱动模块,子维兄则尝试用Altium Designer画出lm298驱动电路的pcb图,作为备用板,william和生命继续搞机(机械部分).....,而我就负责武器中舵机的控制和选购O(∩_∩)O    这样分工的感觉简直就像是一个项目团队的模块化分工,感觉振奋呐!(前段时间看了《疯狂的程序员》,原谅博主的打鸡血反应~)
由于寒假的时候,曾宅在房间里玩 高级流水灯,里面涉及了PWM的应用,因此对舵机的控制程序也有所熟悉。写程序时才发现,一般pwm信号的产生是在while中循环实现的,但是操作小车的时候不可能一直卡在舵机控制函数中,使用了舵机意味着直接进入死循环! 问题困扰了我几天,有空余零散的时间就去想,最后在洗澡中找到了方法!(博主绝对洗干净的..)通过count来控制脉冲数目, while里的条件改为count次数维持一定时间,如此避免了死循环!因为舵机需要有脉冲输入才能维持角度,但是小车只需要两种状态,一是上抬武器,二是归位,归位无需维持角度,所以重点攻克对象是上抬状态。既然不能通过进入while来产生,那就直接嵌入主程序里! 既然不能并行操作,那我就直接一路串下来! 通过一个 flag状态变量,来表示舵机状态,在进入主程序,检查flag,如果为1,则维持脉冲。在switch中的case后设置flag的改变。至此,舵机控制函数完成!(嗷嗷~~~ 骄傲下~~)

接下来贴出源代码以供参考
#include<reg52.h>
#define uchar unsigned char
#define uint unsigned int 
#define N 5  // 脉冲数
uchar count_ms=0,ms1=0; //ms1为0.1ms  
uchar flag; // flag为1表示舵机已抬起
sbit Sign_out=P2^0; //舵机信号输出口
sbit Test=P2^1;

uchar angle_0=5;    //0.5ms-------------0度
uchar angle_45=10;   //1.0ms------------45度;
uchar angle_90=15; //1.5ms------------90度;
uchar angle_135=18; //2.0ms-----------135度;
uchar angle_180=25; //2.5ms-----------180度;

sbit EN1=P1^0;
sbit EN2=P1^1;
sbit A1=P1^2;
sbit A2=P1^3;
sbit B1=P1^4;
sbit B2=P1^5;

void Time1() interrupt 1
{
TH0=(65536-100)/256;
TL0=(65536-100)%256;//重新赋值
count_ms++;
if(count_ms==1)
{
count_ms=0;ms1++;
}
}

void Move(uchar angle)//舵机角度移动
{
uchar count=0;
while(count<=N) //count记录脉冲数
{
TR0=1;
if(ms1<=angle) //时间小于angle时,拉高Sign_out
Sign_out=1;
else
Sign_out=0;
if(ms1>=200) //总时间长度为20ms,到达时间则关闭定时器,count累加,完成一个脉冲周期
{
ms1=0;
TR0=0;
count++;
}
}
}
unsigned char a;
void main()
{
TMOD=0x21;
TH1=0xfd;
TL1=0xfd;
TH0=(65536-100)/256;  
TL0=(65536-100)%256; //二、 装初值
TR1=1;
REN=1;//开始接收
SM0=0;//8位UART
SM1=1;
EA=1;//中断
ES=1;
ET0=1;//2 定时器0中断
while(1)
{
if(flag==1)
{
Move(angle_135);  //维持舵机上抬的状态
}
if(Test==1)a=5;
if(Test==0)a=6;
switch(a)
{
case 1:EN1=1;EN2=1;A1=1;A2=0;B1=1;B2=0;//w
case 2:EN1=1;EN2=1;A1=0;A2=1;B1=0;B2=1;//s
case 3:EN1=1;EN2=1;A1=1;A2=0;B1=0;B2=1;break;//a
case 4:EN1=1;EN2=1;A1=0;A2=1;B1=1;B2=0;break;//d
case 0:EN1=0;EN2=0;break;//stop
case 6:EN1=1;EN2=1;A1=1;A2=0;B1=1;B2=0;Move(angle_0);flag=0;break; //舵机归位
case 5:EN1=1;EN2=1;A1=1;A2=0;B1=1;B2=0;Move(angle_135);flag=1;break;//舵机上抬
case 7:EN1=1;EN2=1;A1=1;A2=0;B1=1;B2=0;break;  
}
}
}
void mhp() interrupt 4//串口中断
{
    RI=0;
P1=SBUF;
a=SBUF;
}


预祝这次比赛拿到奖金!!(Fight!  Iron!,we are Iron Man!)
  • 2
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值