宜昌老张

Makeblock搬运遥控车之SONY PS2手柄

0
阅读(5484)

1 SONY PS2手柄遥控Makeblock搬运遥控车全景图

  先用LabVIEW可视化界面,确定出Arduino编程时所需的参数。这些参数包含有搬运车夹持器爪子张合角度;直线导轨上夹持器的升降高度和速度;以及小车走直线时的左右电机PWM值。

  这篇文章就要谈谈如何用SONY PS2手柄来遥控这个MakeBlock搬运车。这些确定好的重要参数,直接会用到遥控车的Arduino程序中,比如向前拨动手柄摇杆,小车左右电机按照事先设定好的PWM值,能向前走出直线。按下手柄某个按钮,夹持器的爪子收紧到规定角度,刚好紧紧抓住物料。SONY PS2手柄来遥控MakeBlock搬运车全景图如图1所示。

     PlayStation 2,简称PS2,是日本Sony旗下的索尼电脑娱乐SCEI(Sony Computer Entertainment Inc.),于200034日推出的家用型128位游戏系统,这套系统里就包含PS2电玩手柄。这个作品就是想把平时我们用来玩电子竞技游戏的输入设备,用到遥控这台MakeBlock搬运小车。


  要应用SONY PS2电玩手柄遥控小车,首先要了解SONY PS2手柄是如何应用到Arduino控制器中的。

    2中,基于PS2手柄的遥控器组成有SONY PS2电玩手柄,手柄接收器,Arduino UNO控制器,XBee无线数传,8.4V锂聚合物电池。这个遥控器经过了两次无线数传,才把手柄上的操作命令传递给被控搬运车的Arduino MEGA2560控制器。一次是SONY手柄通过红外信号把信息传递给它的自带红外接收器,二次是与红外接收器相连的Arduino UNO控制器通过XBee无线数传模块传递给小车上的Arduino MEGA2560控制器。之所以不把SONY手柄红外接收器直接连到Arduino MEGA2560控制器,可能是因为红外接收器的工作电压为5V,而搬运车上Arduino MEGA2560控制器数字端口的电压,我用稳压扩展板调成了6V(这个电压更适合给小车上的舵机供电),总之采用一次无线通信的方法是不成功的。

       红外接收器如何用杜邦线连接到Arduino UNO控制器?请按照下面接线示意图,从PS2手柄接收器的9个引脚中找出6个引脚 用六根杜邦线 Xbee传感器扩展板的10111213数字端子以及3.3VGND端子连接起来,就可以实现Arduino控制器与PS接收器的硬件联系。对于实现这样的硬件联系,Xbee传感器扩展板非常好用,因为它具有3.3V的端子,而且所有端子都是插针,方便用现成的杜邦线连接。

3  PS2红外接收器与Arduino控制器连线示意图

   不仅硬件连线方便,而且使用专门为PS2X_lib库文件,编写程序也特别简单。

PS2X_lib库文件的zip文件请下载:yunpan.cn/QNUdyd3E27jz7(访问密码:2c9c 

   可以将zip文件下载并解压缩后,复制到Arduino安装目录下的libraries文件夹里面。然后在程序里就可以引入PS2X_lib库文件,并直接使用这个库文件中的函数,采集手柄操作信息了。

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> //引入舵机头文件

Servo clamper_servo;

//把编码器正交编码板OUTA信号连接到Arduino控制器的数字端口2

//数字端口2Arduino的外部中断0的端口。

#define PinA 2 //外部中断0

int N11 =6; //升降直流电机驱动板的电机使能端口连接到数字接口6

int N12 =7; //升降直流电机驱动板的电机转向端口连接到数字接口7

int P11_left =8; //连接小车左轮电机的PWM控制端口到数字接口8

int P12_left =9; //连接小车左轮电机的转向控制端口到数字接口9

int P21_right =10; //连接小车右轮电机的PWM控制端口到数字接口10

int P22_right =11; //连接小车右轮电机的转向控制端口到数字接口11

int Limit=12;      //夹持器上限位开关连接到数字端口12

byte working_state=0;//升降电机正反转和停止标识字节

byte Start=0xff; //数据开始传送的标识字节

int speed_flag=1; //电机速度程度标识,1为高速、0为低速

int PS_LY;//存储接受到的PS2手柄左摇杆Y轴数据

int PS_RY;//存储PS2手柄右摇杆Y轴数据

int PS_RX;//存储PS2手柄右摇杆X轴数据

int pos1; //舵机角度

int power;//电机转速PWM

//初始化

void setup()

{

   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);  

}

void left_advance(int left_val)//小车左轮前进

{

   digitalWrite(P11_left,LOW);

   analogWrite(P12_left, left_val); 

}

void left_back(int left_val) //小车左轮后退

{  

   digitalWrite(P12_left,LOW);

   analogWrite(P11_left,left_val);  

}

void right_advance(int right_val)//小车右轮前进

{

   digitalWrite(P22_right,LOW);

   analogWrite(P21_right,right_val);    

}

void right_back(int right_val)//小车右轮后退

{

   digitalWrite(P21_right,LOW);

   analogWrite(P22_right,right_val);

}

void left_stop()//小车左轮停止

{

   digitalWrite(P11_left, LOW);

   digitalWrite(P12_left, LOW);     

}  

void right_stop()//小车右轮停止

{

   digitalWrite(P21_right, LOW);

   digitalWrite(P22_right, LOW);       

}

//主程序

void loop()

{

   //如果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单片机编程。2Arduino软件语言为精简指令系统,所需掌握的指令不多,但指令的功能却很强大,往往一条指令就可以完成一整套操作,而且指令的可读性也好,属于低门槛的语言,轻松上手,快速应用。3、针对周边I/O设备的Arduino编程,由于很多I/O设备都随之带有库文件或者样例程序,所以在自己的程序中,可以引用库文件中的函数,或复制样例程序,然后修改下其中的参数,即可迅速编写出复杂的程序任务,从而放大了您的编程能力。4Arduino开源硬件在创客界十分流行。所谓开源产品定义,不仅是其软硬件底层信息完全公开,而且还在于产品的应用资讯可以从Arduino相关网站、博客里的大量共享资源里获得,所以在共享资讯的辅助下,能激发出您创意作品的灵感,并加快您创作作品的效率。5、国内在开源硬件的制造能力非常强,涌现出被意大利Arduino公司认可的代理商,如DFRobotSeeed Studio公司,这些公司提供了丰富的质优价廉Arduino及周边产品,所以在国内学习和应用Arduino具有得天独厚的硬件资源优势。