[搭建]Makeblock搬运遥控车之SONY PS2手柄

2014-4-28 15:06:12
103591
   前面写了三篇文章,讲解了如何用LabVIEW可视化界面,方便直观高效地确定出Arduino编程时所需的参数。这些参数包含有搬运车夹持器爪子张合角度;直线导轨上夹持器的升降高度和速度;以及小车走直线时的左右电机PWM值。这三篇文章的题目是:《Makeblock搬运遥控车之夹持器控制》,《Makeblock搬运遥控车之直线导轨控制》和《Makeblock搬运遥控车之车身行动控制》。
    下面就要谈谈如何用SONY PS2手柄来遥控这个MakeBlock搬运车。这些确定好的重要参数,直接会用到遥控车的Arduino程序中,比如向前拨动手柄摇杆,小车左右电机按照事先设定好的PWM值,能向前走出直线。按下手柄某个按钮,夹持器的爪子收紧到规定角度,刚好紧紧抓住物料。SONY PS2手柄来遥控MakeBlock搬运车全景图如图1所示。
全景图.JPG
1 SONY PS2手柄遥控Makeblock搬运遥控车全景图
     PlayStation 2,简称PS2,是日本Sony旗下的索尼电脑娱乐SCEI(Sony Computer Entertainment Inc.),于200034日推出的家用型128位游戏系统,这套系统里就包含PS2电玩手柄。这个作品就是想把平时我们用来玩电子竞技游戏的输入设备,用到遥控这台MakeBlock搬运小车。
   要应用SONYPS2电玩手柄遥控小车,首先要了解SONY PS2手柄是如何应用到Arduino控制器中的。
基于SONY PS2手柄的遥控器.jpg
2  基于PS2手柄的遥控器组成
    2中,基于PS2手柄的遥控器组成有SONYPS2电玩手柄,手柄接收器,ArduinoUNO控制器,XBee无线数传,8.4V锂聚合物电池。这个遥控器经过了两次无线数传,才把手柄上的操作命令传递给被控搬运车的Arduino MEGA2560控制器。一次是SONY手柄通过红外信号把信息传递给它的自带红外接收器,二次是与红外接收器相连的Arduino UNO控制器通过XBee无线数传模块传递给小车上的ArduinoMEGA2560控制器。之所以不把SONY手柄红外接收器直接连到Arduino MEGA2560控制器,可能是因为红外接收器的工作电压为5V,而搬运车上Arduino MEGA2560控制器数字端口的电压,我用稳压扩展板调成了6V(这个电压更适合给小车上的舵机供电),总之采用一次无线通信的方法是不成功的。
       红外接收器如何用杜邦线连接到Arduino UNO控制器?请按照下面接线示意图,从PS2手柄接收器的9个引脚中找出6个引脚 用六根杜邦线 Xbee传感器扩展板的10111213数字端子以及3.3VGND端子连接起来,就可以实现Arduino控制器与PS接收器的硬件联系。对于实现这样的硬件联系,Xbee传感器扩展板非常好用,因为它具有3.3V的端子,而且所有端子都是插针,方便用现成的杜邦线连接。
PS2接收器与Arduino控制连线示意图.jpg
3  PS2红外接收器与Arduino控制器连线示意图
   不仅硬件连线方便,而且使用专门为PS2X_lib库文件,编写程序也特别简单。
PS2X_lib库文件的zip文件请下载:http://yunpan.cn/QNUdyd3E27jz7(访问密码:2c9c
   可以将zip文件下载并解压缩后,复制到Arduino安装目录下的libraries文件夹里面。然后在程序里就可以引入PS2X_lib库文件,并直接使用这个库文件中的函数,采集手柄操作信息了。
SONY PS2电玩手柄.jpg
4 PS2电玩手柄
    4电玩手柄遥控操作方法:按下PS2手柄前端的R2按钮时,搬运小车驱动电机设置高速,按下PS2手柄前端的L2按钮时,驱动电机设置低速。PS2手柄的circle按钮按下时,设置舵机角度为120度,夹持器处于打开状态, Rectangle按钮按下时,设置舵机角度为16度,夹持器处于夹紧状态。Triangle按钮处于按下状态时,每0.05s以舵机角度加4度的速度打开夹持器, error按钮处于按下状态时,每0.05s以舵机角度减4度的速度夹紧夹持器。上下拨动PS2手柄左摇杆,控制夹持器升降电机正转或者反转,使夹持器下降或者上升。上下左右拨动PS2手柄右摇杆,则控制搬运车前后左右行驶。
遥控器主机程序:
//程序任务:PS2手柄数据采集,发送给搬运车接收机
//电机速度程度、小车行驶方向、升降电机转向、舵机角度信息。
#include <PS2X_lib.h>  //声明PS2X库文件
PS2X ps2x; // 定义ps2xPS2X类变量
int speed_flag=1;//电机速度程度标识,1为高速、0为低速
int PS_LY;//PS2手柄左摇杆Y轴数据
int PS_RY;//PS2手柄右摇杆Y轴数据
int PS_RX;//PS2手柄右摇杆X轴数据
int servo_angle=90; //初始化舵机角度为90
//初始化
void setup(){
Serial.begin(9600); //启动串行通信
//初始化PS2Arduino控制器接口
ps2x.config_gamepad(13,11,10,12,true,true);   
}
//主程序
void loop(){   
   ps2x.read_gamepad();//PS2数据
   //如果按下PS2手柄前端的R2按钮时
   if(ps2x.NewButtonState(PSB_R2))
      speed_flag=1;//搬运小车电机设置高速
   //如果按下PS2手柄前端的L2按钮时
   if(ps2x.NewButtonState(PSB_L2))
      speed_flag=0;//搬运小车电机设置低速  
   //如果PS2手柄的circle按钮按下时
   if(ps2x.NewButtonState(PSB_RED))
   //设置舵机角度为120度,夹持器处于打开状态   
     servo_angle=120;
  //如果PS2手柄的Rectangle按钮按下时
  if(ps2x.NewButtonState(PSB_PINK))
  //设置舵机角度为16度,夹持器处于夹紧状态   
     servo_angle=16;   
  //如果PS2手柄的Triangle按钮处于按下状态时
  if(ps2x.Button(PSB_GREEN))
  {
    if(servo_angle>=16)
    {
       //0.05s,以舵机角度加4度的速度打开夹持器
       servo_angle=servo_angle+4;
       if(servo_angle>120)
         servo_angle=120;
       delay(50);
    }
  }
  //如果PS2手柄的error按钮处于按下状态时
  if(ps2x.Button(PSB_BLUE))
  {
    if(servo_angle<=120)
    {
       //0.05s,以舵机角度减4度的速度夹紧夹持器
       servo_angle=servo_angle-4;
       if(servo_angle<16)
         servo_angle=16;
       delay(50);
    }
  }
  //PS2手柄左摇杆Y轴数据读到变量PS_LY
  PS_LY=ps2x.Analog(PSS_LY);
  //PS2手柄右摇杆Y轴数据读到变量PS_RY
  PS_RY=ps2x.Analog(PSS_RY);
  //PS2手柄右摇杆X轴数据读到变量PS_RX
  PS_RX=ps2x.Analog(PSS_RX);
   //PS2手柄操作数据从遥控器发到搬运车的接收端
  Serial.write(0xff); //发送数据开始传送的标识字节
  //发送搬运小车的电机速度程度标识
  Serial.write(speed_flag);
  //发送用于判断夹持器升降电机是正转还是反转的数据
  Serial.write(PS_LY);
  Serial.write(PS_RY); //发送用于判断搬运车是前进还是后退的数据   
  Serial.write(PS_RX); //发送用于判断搬运车是右转还是左转的数据
  Serial.write(servo_angle);//发送实时舵机角度字节
   delay(100); //等待数据发送成功
}
被控搬运车从机程序:
/*程序任务:接受遥控器发送的数据,并控制小车行驶、夹持器的升降。
夹持器夹紧程度。*/
#include<Servo.h> //引入舵机头文件
Servoclamper_servo;
//把编码器正交编码板OUTA信号连接到Arduino控制器的数字端口2
//数字端口2Arduino的外部中断0的端口。
#definePinA 2 //外部中断0
intN11 =6; //升降直流电机驱动板的电机使能端口连接到数字接口6
intN12 =7; //升降直流电机驱动板的电机转向端口连接到数字接口7
intP11_left =8; //连接小车左轮电机的PWM控制端口到数字接口8
intP12_left =9; //连接小车左轮电机的转向控制端口到数字接口9
intP21_right =10; //连接小车右轮电机的PWM控制端口到数字接口10
intP22_right =11; //连接小车右轮电机的转向控制端口到数字接口11
intLimit=12;      //夹持器上限位开关连接到数字端口12
byteworking_state=0;//升降电机正反转和停止标识字节
byteStart=0xff; //数据开始传送的标识字节
intspeed_flag=1; //电机速度程度标识,1为高速、0为低速
intPS_LY;//存储接受到的PS2手柄左摇杆Y轴数据
intPS_RY;//存储PS2手柄右摇杆Y轴数据
intPS_RX;//存储PS2手柄右摇杆X轴数据
intpos1; //舵机角度
intpower;//电机转速PWM
//初始化
voidsetup()
{
   Serial1.begin(9600);  //串口波特率设置,开始串口通信  
   pinMode(PinA,INPUT); //升降伺服电机正交编码板的OUTA信号端设置为输入模式
   pinMode(N11, OUTPUT);   //升降直流电机驱动板的控制端口设置为输出模式
   pinMode(N12, OUTPUT);
   digitalWrite(N11, LOW); //升降电机停止
   digitalWrite(N12, LOW);
      delay(20);  
   pinMode(Limit,INPUT); //夹持器上限位开关数字端口12设置为输入模式
   pinMode(P21_right, OUTPUT); //小车直流电机驱动板的控制端口设置为输出模式
   pinMode(P22_right, OUTPUT);
   pinMode(P11_left, OUTPUT);
   pinMode(P12_left, OUTPUT);
   digitalWrite(P21_right, LOW); //小车右电机停止
   digitalWrite(P22_right, LOW);
      delay(20);
   digitalWrite(P11_left, LOW); //小车左电机停止
   digitalWrite(P12_left, LOW);
      delay(20);  
   clamper_servo.attach(4); //初始化舵机角度为90
   clamper_servo.write(90);   
}
voidleft_advance(int left_val)//小车左轮前进
{
   digitalWrite(P11_left,LOW);
   analogWrite(P12_left, left_val);  
}
voidleft_back(int left_val) //小车左轮后退
{   
   digitalWrite(P12_left,LOW);
   analogWrite(P11_left,left_val);   
}
voidright_advance(int right_val)//小车右轮前进
{
   digitalWrite(P22_right,LOW);
   analogWrite(P21_right,right_val);     
}
voidright_back(int right_val)//小车右轮后退
{
   digitalWrite(P21_right,LOW);
   analogWrite(P22_right,right_val);
}
voidleft_stop()//小车左轮停止
{
   digitalWrite(P11_left, LOW);
   digitalWrite(P12_left, LOW);      
}   
voidright_stop()//小车右轮停止
{
   digitalWrite(P21_right, LOW);
   digitalWrite(P22_right, LOW);        
}
//主程序
voidloop()
{
   //如果Arduino控制板的读缓冲区中存在上位机下达的字节
   if(Serial1.available()>0)
   {
     delay(30);
     Start=Serial1.read();
     //如果接受到用于标识数据开始传送的字节0xff
     //则接下来读取遥控器发来的数据。
     if(Start==0xff)
     {  
        //电机速度程度标识,1为高速、0为低速
        speed_flag=Serial1.read();
        //PS2手柄左摇杆Y轴数据用于控制升降电机转向
        PS_LY=Serial1.read();
        //PS2手柄右摇杆Y轴数据用于控制小车前进或后退
        PS_RY=Serial1.read();
        //PS2手柄右摇杆Y轴数据用于控制小车左转或右转
        PS_RX=Serial1.read();
        pos1= Serial1.read();
     }
    if(speed_flag==1)
       power=180;   //设置为高速,高速时,电机PWM值为180
    if(speed_flag==0)
       power=100;   //设置为低速,高速时,电机PWM值为100  
     // 如果左摇杆向前摇动
     if(PS_LY<37)      
     {
       working_state=2;  //升降电机反转   
     }
      //如果左摇杆向后摇动
     if(PS_LY>217)         
     {
      working_state=1;  //升降电机正转            
     }   
    //  如果左摇杆居中
    if(PS_LY>=37 && PS_LY<=217)
    {
      working_state=0;  //升降电机停止            
    }
    if(working_state==1)
    {
      analogWrite(N11,power); //升降电机以PWM值为180的转速转动
       digitalWrite(N12,LOW); //电机正转        
    }
    else if(working_state==2)
    {   
      digitalWrite(N11,LOW); //升降电机反转
       analogWrite(N12,power); //电机以PWM值为180的转速转动      
    }
    else if(working_state==0)
    {
       digitalWrite(N11, LOW); //升降电机停止
       digitalWrite(N12, LOW);
    }
    //如果电机处于反转状态,同时夹持器又触碰到上限位开关
    if (digitalRead(Limit) == LOW&&  working_state==2 )
    {   
      digitalWrite(N11, LOW); //升降电机停止
      digitalWrite(N12, LOW);         
      working_state=0;
    }  
    // 如果右摇杆向前摇动
      if(PS_RY<37)  //小车前进
       {
         left_advance(power);
         right_advance(power);
       }
      // 如果右摇杆向后摇动
        if(PS_RY>217) //小车后退
       {
         left_back(power);
         right_back(power);
       }
       // 如果右摇杆向左摇动
       if(PS_RX<37) //小车左转
       {
         left_advance(0);
         right_advance(power);
       }
      // 如果右摇杆向右摇动
        if(PS_RX>217) //小车右转
       {
         left_advance(power);
         right_advance(0);
       }
        // 如果右摇杆居中
       if(PS_RY>=37 && PS_RY<=217&& PS_RX>=37 && PS_RX<=217)
       {
          left_stop(); //小车停止
          right_stop();
       }   
       clamper_servo.write(pos1);//控制夹持器上的舵机动作
   }
}
    Arduino为啥这么红,我想Arduino单片机较其他微控制器有以下5点优势:1、您学习Arduino单片机可以完全不需要了解其内部硬件结构和寄存器设置,仅仅知道它的端口作用即可,所以不需要硬件知识,只要会C语言,就可立即为Arduino单片机编程。2、Arduino软件语言为精简指令系统,所需掌握的指令不多,但指令的功能却很强大,往往一条指令就可以完成一整套操作,而且指令的可读性也好,属于低门槛的语言,轻松上手,快速应用。3、针对周边I/O设备的Arduino编程,由于很多I/O设备都随之带有库文件或者样例程序,所以在自己的程序中,可以引用库文件中的函数,或复制样例程序,然后修改下其中的参数,即可迅速编写出复杂的程序任务,从而放大了您的编程能力。4、Arduino开源硬件在创客界十分流行。所谓开源产品定义,不仅是其软硬件底层信息完全公开,而且还在于产品的应用资讯可以从Arduino相关网站、博客里的大量共享资源里获得,所以在共享资讯的辅助下,能激发出您创意作品的灵感,并加快您创作作品的效率。5、国内在开源硬件的制造能力非常强,涌现出被意大利Arduino公司认可的代理商,如DFRobot、Seeed Studio公司,这些公司提供了丰富的质优价廉Arduino及周边产品,所以在国内学习和应用Arduino具有得天独厚的硬件资源优势。

收藏
1 条回帖
happystock注册会员2014-6-2 09:57:07
老张老师的文章最详细,学习了。
需要登陆后才可进行回复 登录

返回顶部
现在加入我们,注册一个账号 账号登陆 QQ账号登陆 微博账号登陆