精华内容
下载资源
问答
  • PS2手柄驱动

    2013-05-19 22:48:40
    PS2手柄驱动
  • Arduino ps2手柄库PS2X_lib.rar
  • PS2手柄源码.zip

    2021-02-28 21:50:41
    STM32F103利用HAL库编辑PS2手柄
  • 索尼PS2手柄破解协议例程 arduino ps2遥控小车,舵机,手柄震动.
  • PS2手柄 亲测能用

    2018-11-06 15:46:01
    自己做小车买的PS2手柄 实现了PS2按键的所有功能,现在把资料贡献出来
  • 自制的基于STM32f103开发板的ps2手柄控制智能车运动程序。
  • ps2手柄arduino库文件

    2018-09-07 20:51:21
    该资源是Arduino 与ps2手柄通信的库文件,想学习SONYps2手柄Arduino 的老铁可以下载安装此库文件,祝各位老铁学习愉快。
  • PS2手柄HAL库+CubeMX源码

    2020-07-19 12:22:37
    PS2手柄HAL库+CubeMX源码 详情看:https://lindoglog.blog.csdn.net/article/details/105781595
  • PS2手柄_STM32例程

    2018-04-21 18:29:36
    索尼PS2手柄破解协议例程 STM32 keil环境 ps2遥控小车,舵机,手柄震动.
  • arduino ps2手柄操作库,用于Arduino开发,机器人小车,网上不是很好找,免费的资源不多,发出来共享一下。
  • PS2手柄通讯协议解析---附资料和源码

    万次阅读 多人点赞 2020-04-27 17:16:08
    文章目录一.PS2介绍二.PS2通讯协议介绍 一.PS2介绍 今天就带大家来认识一下PS2的通讯协议,如果你需要用PS2无线手柄搭配单面机来DIY制作,那么千万别...不知什么时候便有人打起 PS2手柄的主意,破解了通讯协议,使...
     
    

    一.PS2介绍

    今天就带大家来认识一下PS2的通讯协议,如果你需要用PS2无线手柄搭配单面机来DIY制作,那么千万别错过这篇文章。

    首先介绍一下我们今天的主角-----PS2手柄。 PS2手柄是日本SONY公司的PlayStation2 游戏机的遥控手柄。索尼的 PSX系列游戏主机在全球都很畅销。不知什么时候便有人打起 PS2手柄的主意,破解了通讯协议,使得手柄可以接在其他器件上遥控使用,比如遥控我们熟悉的机器人。突出的特点是这款手柄性价比极高,按键丰富,方便扩展到其它应用中。

    二.PS2通讯协议介绍

    PS2采用的是SPI通信协议,SPI是串行外设接口的缩写,是一种高速的、全双工、同步的通信总线,并且在芯片的管脚上只占用四根线(DI、DO、CS、CLK),节约了芯片的管脚,同时为PCB的布局上节省空间。

    (1)PS2端口介绍

    PS2接收器上一共有九根引脚,按上图从左往右,依次为:

    1.DI/DAT:信号流向,从手柄到主机,此信号是一个8bit 的串行数据,同步传送于时钟的下降沿。信号的读取在时钟由高到低的变化过程中完成。

    2.DO/CMD:信号流向,从主机到手柄,此信号和 DI相对,信号是一个 8bit 的串行数据, 同步传送于时钟的下降沿。

    3.NC:空端口。

    4.GND:电源地。

    5.VCC:接收器工作电源,电源范围 3~5V。

    6.CS/SEL:用于提供手柄触发信号。在通讯期间,处于低电平。

    7.CLK:时钟信号,由主机发出,用于保持数据同步。

    8.NC:空端口。

    9.ACK:从手柄到主机的应答信号。此信号在每个8bits数据发送的最后一个周期变低并且CS一直保持低电平,如果CS信号不变低,约60微秒PS主机会试另一个外设。在编程时未使用ACK端口。(可以忽略)

    (2)PS2通讯过程

    1. CS线在通讯期间拉低,通信过程中CS信号线在一串数据(9个字节,每个字节为8位)发送完毕后才会拉高,而不是每个字节发送完拉高。

    2. DO、DI在在CLK时钟的下降沿完成数据的发送和读取。

    下降沿:数字电平从高电平(数字“1”)变为低电平(数字“0”)的那一瞬间叫作下降沿。

    3. CLK的每个周期为12us。若在某个时刻,CLK处于下降沿,若此时DO为高电平则取“1”,低电平则取“0”。连续读8次则得到一个字节byte的数据,连续读9个字节就能得到一次传输周期所需要的数据。DI也是一样的,发送和传输同时进行。

    具体的通讯过程如下:
    在这里插入图片描述
    以STM32为例:

    1. 首先STM32拉低CS片选信号线,然后在每个CLK的下降沿读一个bit,每读八个bit(即一个byte)CLK拉高一小段时间,一共读九组bit。

    2. 第一个byte是STM32发给接收器命令“0X01” 。

    3. PS2手柄会在第二个byte回复它的ID(0x41=绿灯模式,0x73=红灯模式),同时第二个byte时STM32发给PS2一个0x42请求数据。

    红灯模式时 : 左右摇杆发送模拟值,0x00~0xFF 之间,且摇杆按下的 键值 L3 、 R3 有效;
    绿灯模式时 : 左右摇杆模拟值为无效,推到极限时,对应发送 UP、RIGHT、DOWN、 LEFT、△、○、╳、□,按键 L3 、 R3 无效;

    4. 第三个byte PS2 会给主机发送 “0x5A” 告诉STM32数据来了。

    5. 从第四个byte开始全是接收器给主机发送数据,每个byte定义如上图,当有按键按下,对应位为“0 ”,例如当键“SELECT”被按下时, Data[3]=11111110。

    对于整个通讯过程,你理解成下面的一段对话:

    对于整个通讯过程,你理解成下面的一段对话:
    首先,拉低CS,表示开始数据通信
    byte 0 :
    STM32(DO) : 0x01 ------------------------- [现在开始通信]
    PS2手柄(DI) : 空 ---------------------------- [空]
    byte 1 :
    STM32(DO) : 0x42 -------------------------- [请求发送数据]
    PS2手柄(DI) : 红灯0x73
                绿灯0X41 ---------------------[现在的ID]
    byte 2 :
    STM32(DO) : 空 ------------------------------ [空]
    PS2手柄(DI) : 0X5A ------------------------- [数据来了]
    byte 3 :
    STM32(DO) : 0X00~0XFF ------------------ [右侧小震动电机是否开启]
    PS2手柄(DI) : 00000000~11111111 ------- [SELECT、 L3 、 R3、 START 、 UP、 RIGHT、 DOWN、 LEFT 是否被按下,若被按下对应位为0]
    byte 4 :
    STM32(DO) : 0X00~0XFF ------------------ [左侧大震动电机振动幅度]
    PS2手柄(DI) : 00000000~11111111 ------- [L2 、 R2、L1 、R1、△、○、╳、□ 是否被按下,若被按下对应位为0]
    byte 5 :
    STM32(DO) : 空 -------------------------------- [空]
    PS2手柄(DI) : 0X00~0XFF ------------------ [左侧X轴摇杆模拟量]
    byte 6 :
    STM32(DO) : 空 -------------------------------- [空]
    PS2手柄(DI) : 0X00~0XFF ------------------ [左侧Y轴摇杆模拟量]
    byte 7 :
    STM32(DO) : 空 -------------------------------- [空]
    PS2手柄(DI) : 0X00~0XFF ------------------ [右侧X轴摇杆模拟量]
    byte 8 :
    STM32(DO) : 空 -------------------------------- [空]
    PS2手柄(DI) : 0X00~0XFF ------------------ [右侧Y轴摇杆模拟量]
    注:在手柄通信前还需要一系列的初始化(是否启动振动电机、是否进行锁存等),详情可以参考下面代码。当然,不进行初始化也是可以的,手柄会默认之前的配置。

    注意:
    1.模拟量只对红灯模式下有效,绿灯模式下摇杆推至极限分别对应 UP、RIGHT、DOWN、 LEFT、△、○、╳、□ 。
    2. L3、R3只对红灯模式下有效,在绿灯模式下无效。

    三.基于STM32的PS2通信源码

    //采用模拟SPI通信
    /*DI->PB12;
      DO->PB13;
      CS->PB14;
      CLK->PB15
    */
    void PS2_Init(void) { 
    // 输入 DI->PB12
     RCC->APB2ENR|=1<<3; // 使能 PORTB 时钟 
     GPIOB->CRH&=0XFFF0FFFF;//PB12 设置成输入 默认下拉
     GPIOB->CRH|=0X00080000; 
     // DO->PB13 CS->PB14 CLK->PB15 
     RCC->APB2ENR|=1<<3; // 使能 PORTB 时钟 
     GPIOB->CRH&=0X000FFFFF;
     GPIOB->CRH|=0X33300000; //PB13、 PB14 、 PB15 推挽输出 
      } 
      //端口初始化,PB12 为输入,PB13 、PB14 、PB15 为输出。
      
    // 向手柄发送命令
    void PS2_Cmd(u8CMD) 
    {
      volatile u16 ref=0x01; 
      Data[1]=0; 
      for(ref=0x01;ref<0x0100;ref<<=1) 
      {
        if(ref&CMD) 
        {
         DO_H; // 输出一位控制位
        }
        else DO_L; 
        CLK_H; // 时钟拉高 
        delay_us(10); 
        CLK_L; 
        delay_us(10); 
        CLK_H; 
        if(DI) 
        {Data[1]=ref|Data[1];}
      }
     delay_us(16);
    }
    
    // 判断是否为红灯模式,0x41=模拟绿灯,0x73=模拟红灯 
    // 返回值;0,红灯模式 
    // 其他,其他模式
    u8PS2_RedLight(void) 
    {
      CS_L; 
      PS2_Cmd(Comd[0]); // 开始命令
      PS2_Cmd(Comd[1]); // 请求数据
      CS_H; 
      if( Data[1]== 0X73) return 0else return 1}
    
    // 读取手柄数据 
    void PS2_ReadData(void) 
    {
      volatile u8 byte=0; 
      volatile u16 ref=0x01; 
      CS_L; 
      PS2_Cmd(Comd[0]); // 开始命令
      PS2_Cmd(Comd[1]); // 请求数据
      for(byte=2;byte<9;byte++) // 开始接受数据 
      {
        for(ref=0x01;ref<0x100;ref<<=1) 
        { 
          CLK_H; 
          delay_us(10); 
          CLK_L; 
          delay_us(10); 
          CLK_H; 
          if(DI) 
          {Data[byte]= ref|Data[byte];}
        }
        delay_us(16);
      }
      CS_H;
    }   
    
    /*
    上面两个函数分别为主机向手柄发送数据、手柄向主机发送数据。手柄向主机发送的数据缓存在数组 Data[]中,
    数组中共有9个元素,每个元素的意义请见表1。
    还有一个函数是用来判断手柄的发送模式,也就是判断 ID(红灯还是绿灯模式) 即 Data[1]的值。
    */
    
    
    // 对读出来的 PS2 的数据进行处理,只处理按键部分
    //按下为0,未按下为1
    u8PS2_DataKey() 
    {
      u8 index; 
      PS2_ClearData(); 
      PS2_ReadData(); 
      Handkey=(Data[4]<<8)|Data[3]; // 这是 16个按键 按下为 0 , 未按下为 1 
      for(index=0;index<16;index++) 
      {
        if((Handkey&(1<<(MASK[index]-1)))==0) 
        returnindex+1;
      }
      return 0; // 没有任何按键按下
    }
    
    // 得到一个摇杆的模拟量 范围 0~256 
    u8PS2_AnologData(u8 button) 
    {
      return Data[button];
    }
    
    
    // 清除数据缓冲区
    void PS2_ClearData() 
    {
      u8 a; 
      for(a=0;a<9;a++) 
        {Data[a]=0x00;}
    }
    
    /*
    8 位数 Data[3]与 Data[4],分别对应着 16个按键的状态,按下为 0,未按下为 1。
    通过 对这两个数的处理,得到按键状态并返回键值。
    另一个函数的功能就是返回模拟值,只有在“红灯模式”下值才是有效的,拨动摇杆, 值才会变化,这些值分别存储在 Data[5]、Data[6]、
    Data[7]、 Data[8]。 
    */
    
    
    //手柄配置初始化: 
    void PS2_ShortPoll(void) 
    {
      CS_L; 
      delay_us(16); 
      PS2_Cmd(0x01); 
      PS2_Cmd(0x42); 
      PS2_Cmd(0X00); 
      PS2_Cmd(0x00); 
      PS2_Cmd(0x00); 
      CS_H; 
      delay_us(16);
    }
    
    
    //进入配置
    void PS2_EnterConfing(void) 
    {
      CS_L;
      delay_us(16); 
      PS2_Cmd(0x01); 
      PS2_Cmd(0x43); 
      PS2_Cmd(0X00); 
      PS2_Cmd(0x01); 
      PS2_Cmd(0x00); 
      PS2_Cmd(0X00);
      PS2_Cmd(0X00); 
      PS2_Cmd(0X00); 
      PS2_Cmd(0X00); 
      CS_H; 
      delay_us(16);
    }
    
    
    // 发送模式设置 
    void PS2_TurnOnAnalogMode(void) 
    {
      CS_L; 
      PS2_Cmd(0x01); 
      PS2_Cmd(0x44); 
      PS2_Cmd(0X00); 
      PS2_Cmd(0x01);//analog=0x01;digital=0x00 软件设置发送模式 
      PS2_Cmd(0xEE);//Ox03 锁存设置,即不可通过按键“MODE ”设置模式。        //0xEE 不锁存软件设置,可通过按键“MODE ”设置模式。 
      PS2_Cmd(0X00); 
      PS2_Cmd(0X00); 
      PS2_Cmd(0X00); 
      PS2_Cmd(0X00); 
      CS_H; 
      delay_us(16);
    }
    
    
    // 振动设置
    void PS2_VibrationMode(void) 
    {
      CS_L; 
      delay_us(16); 
      PS2_Cmd(0x01); 
      PS2_Cmd(0x4D); 
      PS2_Cmd(0X00); 
      PS2_Cmd(0x00); 
      PS2_Cmd(0X01); 
      CS_H; 
      delay_us(16);
    }
    
    
    // 完成并保存配置
    void PS2_ExitConfing(void)
    {
      CS_L;
      delay_us(16);
      PS2_Cmd(0x01);
      PS2_Cmd(0x43); 
      PS2_Cmd(0X00);
      PS2_Cmd(0x00); 
      PS2_Cmd(0x5A); 
      PS2_Cmd(0x5A); 
      PS2_Cmd(0x5A);
      PS2_Cmd(0x5A); 
      PS2_Cmd(0x5A); 
      CS_H; 
      delay_us(16);
    }
    
    // 手柄配置初始化
    void PS2_SetInit(void) 
    {
      PS2_ShortPoll();
      PS2_ShortPoll();
      PS2_ShortPoll(); 
      PS2_EnterConfing(); // 进入配置模式 
      PS2_TurnOnAnalogMode(); // “红绿灯”配置模式,并选择是否保存 
      PS2_VibrationMode(); // 开启震动模式 
      PS2_ExitConfing(); // 完成并保存配置
    }
    /*
    可以看出配置函数就是发送命令,发送这些命令后,手柄就会明白自己要做什么了,发送命令时,不需要考虑手柄发来的信息。
    手柄配置初始化,PS2_ShortPoll()被执行了3次,主要是为了建立和恢复连接。
    具体的配置方式请看注释。
    */
    void PS2_Vibration(u8motor1,u8motor2)
    {
       CS_L; 
       delay_us(16); 
       PS2_Cmd(0x01); // 开始命令
       PS2_Cmd(0x42);// 请求数据
       PS2_Cmd(0X00);
       PS2_Cmd(motor1);
       PS2_Cmd(motor2); 
       PS2_Cmd(0X00); 
       PS2_Cmd(0X00); 
       PS2_Cmd(0X00); 
       PS2_Cmd(0X00); 
       CS_H; 
       delay_us(16);
    } 
    //只 有 在 初 始 化 函 数 void PS2_SetInit(void) 中 , 对 震 动 电 机 进 行 了初 始 化 (PS2_VibrationMode();//开启震动模式),这个函数命令才会被执行。 
    

    四.文档与源码下载链接

    1.PS2参考文档CSDN:PS2解码通讯手册.pdf
    注:文档里面有PS2的通讯原理的解析,还有上面代码块的代码都在里面,如果在CSDN里看代码比较累,建议下载PDF文档直接看PS2代码例程。

    2.这里还有一份我写的源码:PS2源码HAL库+CubeMX+Stm32F103C8

    注:

    1. 里面除了PS2的源码还加了延时实验的源码,HAL库本身没有微秒级的延时,所以需要自己写微秒级的延时函数,详情看源码。至于延时的原理参考另一篇博客:Stm32延时与计时方法(HAL库)
    2. 为防止与PS2通信过快而乱码导致延迟,需要在主函数的while(1)中延时50ms,即加一句delay_ms(50)。(原工程中没有,需要自行加上)
    展开全文
  • ps2手柄控制智能车

    2018-12-02 10:12:50
    基于STM32战舰正点原子开发板PS2手柄遥控智能车程序 。
  • PS2手柄基于stc8G1K08.rar

    2021-09-04 10:27:18
    PS2手柄程序移植到STC8G1K08上,并可以进行串口调试。赠送资料(51程序 32程序等)
  • PS2手柄 通信 协议解析..............................................................................................................................
  • pc支持ps2手柄震动驱动 pc支持ps2手柄震动驱动 pc支持ps2手柄震动驱动
  • 主控板为STMF407ZGT6,PS2手柄驱动代码,注释齐全,采用结构体方式跨文件传输数据。也预留全局变量跨文件传输数据。 //不太懂地方联系qq:277746470
  • PS2手柄的STM32应用

    2018-07-17 14:44:05
    PS2手柄的解析,以及在STM32单片机的应用,包括STM32的手柄应用程序
  • ps2手柄控制麦克纳木轮小车程序,是用c语言写的,可以用手柄远程控制
  • 咸鱼ZTMR实例—PS2手柄

    2020-04-21 12:26:07
    咸鱼ZTMR实例—PS2手柄 主控板:ZTMR开发板 PS2手柄 PS2 手柄是游戏机的遥控手柄。psx 系列游戏主机在全球很是畅销。不知什么时候便有人打起 PS2手柄的主意,破解了通讯协议,使得手柄可以接在其他器件上遥控使用,...

    咸鱼ZTMR实例—PS2手柄


    主控板:ZTMR开发板

    PS2手柄

    PS2 手柄是游戏机的遥控手柄。psx 系列游戏主机在全球很是畅销。不知什么时候便有人打起 PS2手柄的主意,破解了通讯协议,使得手柄可以接在其他器件上遥控使用,比如遥控我们熟悉的机器人。突出的特点是现在这款手柄性价比极高。按键丰富,方便扩展到其它应用中。

    在这里插入图片描述

    PS2 由手柄与接收器两部分组成,手柄主要负责发送按键信息。都接通电源并打开手柄开关时,手柄与接收器自动配对连接,在未配对成功的状态下,接收器绿灯闪烁,手柄上的灯也会闪烁,配对成功后,接收器上绿灯常亮,手柄上灯也常亮,这时可以按“MODE”键,选择手柄发送模式,红灯模式:遥杆输出模拟值;绿灯模式:遥杆对应上面四个按键,只有四个极限方向对应。
    接收器和主机(单片机)相连,实现主机与手柄之间的通讯。

    接收器引脚输出:
    在这里插入图片描述

    123456789
    DI/DATDO/CMDNCGNDVDDCS/SELCLKNCACK

    例程:串口打印PS2按钮信息
    main.py

    # main.py -- put your code here!
    import ps2
    
    
    def main():
      while True:
        pyb.delay(100)
        print('xycs:',ps2.ps2_key())
    if __name__ == '__main__':
        main()
    
    

    网上已经有开源的PS2手柄定义了, 我们保存成ps2.py文件直接保存起来就好了

    ps2.py

    from machine import Pin
    import time
    def ps2_test():
      print('test ok')
    di=Pin(Pin.cpu.C6,Pin.IN,Pin.PULL_DOWN)                     
    do=Pin(Pin.cpu.C7,Pin.OUT, )                                             
    cs=Pin(Pin.cpu.B0,Pin.OUT,)     #PULL_UP                                          
    clk=Pin(Pin.cpu.B1,Pin.OUT,) 
    
    #D0 16  dat=DI
    #D2 04  cmd=DO
    #D3  0  CS =CS
    #D4  02  CLK=CLK                                                      
    def DO_H():
      do.value(1)
    def DO_L():
      do.value(0)
    def CS_H ():
      cs.value(1)
    def CS_L():
      cs.value(0)
    def CLK_H ():
      clk.value(1)
    def CLK_L():
      clk.value(0)
    
    #常量按钮
    PSB_SELECT     = 1
    PSB_L3         = 2
    PSB_R3         = 3
    PSB_START      = 4
    PSB_PAD_UP     = 5
    PSB_PAD_RIGHT  = 6
    PSB_PAD_DOWN   = 7
    PSB_PAD_LEFT   = 8
    PSB_L2         = 9
    PSB_R2         = 10
    PSB_L1         = 11
    PSB_R1         = 12
    PSB_GREEN      = 13
    PSB_RED        = 14
    PSB_BLUE       = 15
    PSB_PINK       = 16
    PSB_TRIANGLE   = 13
    PSB_CIRCLE     = 14
    PSB_CROSS      = 15
    PSB_SQUARE     = 26
    # 左摇杆
    PSS_RX = 5                
    PSS_RY = 6
    PSS_LX = 7
    PSS_LY = 8
    mask=[
    PSB_SELECT,
        PSB_L3,
        PSB_R3 ,
        PSB_START,
        PSB_PAD_UP,
        PSB_PAD_RIGHT,
        PSB_PAD_DOWN,
        PSB_PAD_LEFT,
        PSB_L2,
        PSB_R2,
        PSB_L1,
        PSB_R1 ,
        PSB_GREEN,
        PSB_RED,
        PSB_BLUE,
        PSB_PINK]
    comd=[0x01,0x42]
    data=[0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00]
    def ps2_init():
      CLK_H()
      DO_H()
      time.sleep_ms(10)
    def ps2_cmd(cmd):
      global data
      data[1]=0
      for ref in (1,2,4,8,16,32,64,128):
        if ( ref & cmd):
         DO_H()
        else:
         DO_L()
        CLK_H ()
        time.sleep_us(50)
        CLK_L()
        time.sleep_us(50)
        CLK_H ()
        if(di.value()==1):
         data[1]=ref|data[1]
    def ps2_red():
      global data
      global comd
      CS_L()
      ps2_cmd(comd[0])
      ps2_cmd(comd[1])
      CS_H()
      if(data[1]==57):
        return 0#red light
      else:
        return 1#not red
    def ps2_read():
      global data
      global comd
      byte=0
      ref=0x01
      CS_L()
      ps2_cmd(comd[0])
      ps2_cmd(comd[1])
      for byte in (2,3,4,5,6,7,8):
        for ref in (1,2,4,8,16,32,64,128):
         CLK_H ()
         CLK_L()
         time.sleep_us(50)
         CLK_H ()
         if(di.value()==1):
          data[byte]= ref|data[byte]
        time.sleep_us(50)
      CS_H ()
    def ps2_clear():#ok
      global data
      for i in range(0,9,1):
        data[i]=0
    
    def ps2_andata(button):
      global data
      return data[button]
    def ps2_key():
      global data
      global mask
      ps2_clear()
      ps2_read()
      handkey=(data[4]<<8)|data[3]
      for index in (0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15):
        if (( handkey&(1<<(mask[index]-1)))==0):
         return index+2
      return 0
    

    串口效果
    在这里插入图片描述

    展开全文
  • PS2手柄按键测试

    万次阅读 2019-12-08 18:23:18
    arduino的PS2手柄控制测试: #include <PS2X_lib.h> //电机引脚 #define PWMA 12 //A电机转速 #define DIRA1 34 #define DIRA2 35 //A电机方向 #define PWMB 8 //B电机转速 #define DIRB1 37 #...

    arduino的PS2手柄控制测试:

     #include <PS2X_lib.h>
    //电机引脚
    #define PWMA 12    //A电机转速
    #define DIRA1 34 
    #define DIRA2 35  //A电机方向
    #define PWMB 8    //B电机转速
    #define DIRB1 37 
    #define DIRB2 36  //B电机方向
    #define PWMC 9   //C电机转速
    #define DIRC1 43 
    #define DIRC2 42  //C电机方向
    #define PWMD 5    //D电机转速
    #define DIRD1 26  
    #define DIRD2 27  //D电机方向
    
    //PS2控制器
    #define PS2_DAT        52  //14    
    #define PS2_CMD        51  //15
    #define PS2_SEL        53  //16
    #define PS2_CLK        50  //17
    
    PS2X ps2x; // create PS2 Controller Class
    
    
    #define MOTORA_FORWARD(pwm)    do{digitalWrite(DIRA1,LOW); digitalWrite(DIRA2,HIGH);analogWrite(PWMA,pwm);}while(0)
    #define MOTORA_STOP(x)         do{digitalWrite(DIRA1,LOW); digitalWrite(DIRA2,LOW); analogWrite(PWMA,0);}while(0)
    #define MOTORA_BACKOFF(pwm)    do{digitalWrite(DIRA1,HIGH);digitalWrite(DIRA2,LOW); analogWrite(PWMA,pwm);}while(0)
    
    #define MOTORB_FORWARD(pwm)    do{digitalWrite(DIRB1,LOW); digitalWrite(DIRB2,HIGH);analogWrite(PWMB,pwm);}while(0)
    #define MOTORB_STOP(x)         do{digitalWrite(DIRB1,LOW); digitalWrite(DIRB2,LOW); analogWrite(PWMB,0);}while(0)
    #define MOTORB_BACKOFF(pwm)    do{digitalWrite(DIRB1,HIGH);digitalWrite(DIRB2,LOW); analogWrite(PWMB,pwm);}while(0)
    
    #define MOTORC_FORWARD(pwm)    do{digitalWrite(DIRC1,LOW); digitalWrite(DIRC2,HIGH);analogWrite(PWMC,pwm);}while(0)
    #define MOTORC_STOP(x)         do{digitalWrite(DIRC1,LOW); digitalWrite(DIRC2,LOW); analogWrite(PWMC,0);}while(0)
    #define MOTORC_BACKOFF(pwm)    do{digitalWrite(DIRC1,HIGH);digitalWrite(DIRC2,LOW); analogWrite(PWMC,pwm);}while(0)
    
    #define MOTORD_FORWARD(pwm)    do{digitalWrite(DIRD1,LOW); digitalWrite(DIRD2,HIGH);analogWrite(PWMD,pwm);}while(0)
    #define MOTORD_STOP(x)         do{digitalWrite(DIRD1,LOW); digitalWrite(DIRD2,LOW); analogWrite(PWMD,0);}while(0)
    #define MOTORD_BACKOFF(pwm)    do{digitalWrite(DIRD1,HIGH);digitalWrite(DIRD2,LOW); analogWrite(PWMD,pwm);}while(0)
    
    #define SERIAL  Serial
    
    #define MAX_PWM   200
    #define MIN_PWM   100
    int Motor_PWM = 130;
    
    //控制电机运动    宏定义
    
    //    ↑A-----B↑   
    //     |  ↑  |
    //     |  |  |
    //    ↑C-----D↑
    void ADVANCE(){
      MOTORA_FORWARD(Motor_PWM);MOTORB_FORWARD(Motor_PWM);    
      MOTORC_FORWARD(Motor_PWM);MOTORD_FORWARD(Motor_PWM);    
    }
    
    //    ↓A-----B↓   
    //     |  |  |
    //     |  ↓  |
    //    ↓C-----D↓
    void BACK(){
      MOTORA_BACKOFF(Motor_PWM);MOTORB_BACKOFF(Motor_PWM);
      MOTORC_BACKOFF(Motor_PWM);MOTORD_BACKOFF(Motor_PWM);
    }
    
    //    =A-----B↑   
    //     |   ↖ |
    //     | ↖   |
    //    ↑C-----D=
    void LEFT_1(){
      MOTORA_FORWARD(Motor_PWM);MOTORB_STOP(Motor_PWM);
      MOTORC_STOP(Motor_PWM);MOTORD_FORWARD(Motor_PWM);
    }
    
    //    ↓A-----B↑   
    //     |  ←  |
    //     |  ←  |
    //    ↑C-----D↓
    void LEFT_2(){
      MOTORA_BACKOFF(Motor_PWM);MOTORB_FORWARD(Motor_PWM);
      MOTORC_FORWARD(Motor_PWM);MOTORD_BACKOFF(Motor_PWM);
    }
    
    //    ↓A-----B=   
    //     | ↙   |
    //     |   ↙ |
    //    =C-----D↓
    void LEFT_3(){
      MOTORA_BACKOFF(Motor_PWM);MOTORB_STOP(Motor_PWM);
      MOTORC_STOP(Motor_PWM);MOTORD_BACKOFF(Motor_PWM);
    }
    
    //    ↑A-----B=   
    //     | ↗   |
    //     |   ↗ |
    //    =C-----D↑
    void RIGHT_1(){
      MOTORA_FORWARD(Motor_PWM);MOTORB_STOP(Motor_PWM);
      MOTORC_STOP(Motor_PWM);MOTORD_FORWARD(Motor_PWM);
    }
    
    //    ↑A-----B↓   
    //     |  →  |
    //     |  →  |
    //    ↓C-----D↑
    void RIGHT_2(){
      MOTORA_FORWARD(Motor_PWM);MOTORB_BACKOFF(Motor_PWM);
      MOTORC_BACKOFF(Motor_PWM);MOTORD_FORWARD(Motor_PWM);
    }
    
    //    =A-----B↓   
    //     |   ↘ |
    //     | ↘   |
    //    ↓C-----D=
    void RIGHT_3(){
      MOTORA_STOP(Motor_PWM);MOTORB_BACKOFF(Motor_PWM);
      MOTORC_BACKOFF(Motor_PWM);MOTORD_STOP(Motor_PWM);
    }
    
    //    =A-----B=  
    //     |  =  |
    //     |  =  |
    //    =C-----D=
    void STOP(){
      MOTORA_STOP(Motor_PWM);MOTORB_STOP(Motor_PWM);
      MOTORC_STOP(Motor_PWM);MOTORD_STOP(Motor_PWM);
    }
    
    void UART_Control(){
      char Uart_Date=0;
     if(SERIAL.available())
      {
       Uart_Date = SERIAL.read();
      }
      switch(Uart_Date)
      {
         case 'A':  ADVANCE();              break;
         case 'B':  RIGHT_1();              break;
         case 'C':  RIGHT_2();              break;
         case 'D':  RIGHT_3();              break;
         case 'E':  BACK();                 break;
         case 'F':  LEFT_3();               break;
         case 'G':  LEFT_2();               break;
         case 'H':  LEFT_1();               break;
         case 'Z':  STOP();                 break;
         case 'L':  Motor_PWM = 240;        break;
         case 'M':  Motor_PWM = 130;        break;
       }
    }
    
    void IO_init(){
      pinMode(PWMA, OUTPUT);
      pinMode(DIRA1, OUTPUT);
      pinMode(DIRA2, OUTPUT);
      pinMode(PWMB, OUTPUT);
      pinMode(DIRB1, OUTPUT);
      pinMode(DIRB2, OUTPUT);
      pinMode(PWMC, OUTPUT);
      pinMode(DIRC1, OUTPUT);
      pinMode(DIRC2, OUTPUT);
      pinMode(PWMD, OUTPUT);
      pinMode(DIRD1, OUTPUT);
      pinMode(DIRD2, OUTPUT);
      STOP();
    }
    
    void setup(){
      int error,type;
      Serial.begin(9600);
      delay(300) ;//added delay to give wireless ps2 module some time to startup, before configuring it
      //CHANGES for v1.6 HERE!!! **************PAY ATTENTION*************
      ps2x.config_gamepad(PS2_CLK, PS2_CMD, PS2_SEL, PS2_DAT, false, false);
    
      type = ps2x.readType();
      switch (type) {
      case 0:
        Serial.print("Unknown Controller type found ");
        break;
      case 1:
        Serial.print("DualShock Controller found ");
        break;
      case 2:
        Serial.print("GuitarHero Controller found ");
        break;
      case 3:
        Serial.print("Wireless Sony DualShock Controller found ");
        break;
      }
      IO_init();
    }
    
    void loop() {
      byte vibrate = 0;
      UART_Control();//串口接收处理 
      ps2x.read_gamepad(false, vibrate); //read controller and set large motor to spin at 'vibrate' speed
    //start 开始运行,电机初PWM为120;
        if (ps2x.Button(PSB_START))  {
          Serial.println("Start");
         Motor_PWM = 90;
          ADVANCE();
        }
    // 电机正转;
        if (ps2x.Button(PSB_PAD_UP)) {
          Serial.println("Up held this hard: ");
          Motor_PWM = 120;
         ADVANCE();
        }
    
    // 电机反转;
        if (ps2x.Button(PSB_PAD_DOWN)) {
          Serial.println("Down held this hard: ");
           Motor_PWM = 120;
          BACK();
        }
    
    //左转;
        if (ps2x.Button(PSB_PAD_LEFT)) {
          Serial.println("turn left ");
            Motor_PWM = 120;//200
          LEFT_1();
        }
    
    //右转;
        if (ps2x.Button(PSB_PAD_RIGHT)) {
          Serial.println("turn right");
            Motor_PWM = 120;//200
          RIGHT_1();
        }
    // Stop
        if (ps2x.Button(PSB_SELECT)) {
          Serial.println("stop");
          STOP();
        }
    // 左平移
        if (ps2x.Button(PSB_PINK)) {
          Serial.println("motor_pmove_left");
          LEFT_2();
        }
    // 右平移
        if (ps2x.Button(PSB_RED)) {
          Serial.println("motor_pmove_right");
          RIGHT_2();
        }
    
        vibrate = ps2x.Analog(PSAB_CROSS);  //this will set the large motor vibrate speed based on how hard you press the blue (X) button
        if (ps2x.NewButtonState()) {        //will be TRUE if any button changes state (on to off, or off to on)
          if(ps2x.Button(PSB_L3))
            Serial.println("L3 pressed");
          if(ps2x.Button(PSB_R3))
            Serial.println("R3 pressed");
          if(ps2x.Button(PSB_L2))
            Serial.println("L2 pressed");
          if(ps2x.Button(PSB_R2))
            Serial.println("R2 pressed");
          if(ps2x.Button(PSB_TRIANGLE))
            Serial.println("Triangle pressed");        
        }
    
        // 摇杆测试
        int LX,LY,RX,RY;
        LY=ps2x.Analog(PSS_LY);  //中间值127
        LX=ps2x.Analog(PSS_LX);  //中间值128
        RY=ps2x.Analog(PSS_RY);  //中间值127
        RX=ps2x.Analog(PSS_RX);  //中间值128
        Serial.print("Stick Values:");
        Serial.print(LY);
        Serial.print(LX);
        Serial.print(RY);
        Serial.println(RX);
        delay(20);
    }
    
    

    ps

    展开全文
  • PS2手柄遥控Arduino小车

    万次阅读 多人点赞 2017-08-17 13:53:53
    使用手柄遥控小车是经常要用到的,看到PS2手柄很6,就拿来尝试一下。 PS2手柄是索尼的PlayStation2游戏机的遥控手柄,因为这款手柄性价比较高,按键丰富,方便扩展到其它应用中,后来有人将其通讯协议破解,使得...

    使用手柄遥控小车是经常要用到的,看到PS2手柄很6,就拿来尝试一下。
    PS2手柄是索尼的PlayStation2游戏机的遥控手柄,因为这款手柄性价比较高,按键丰富,方便扩展到其它应用中,后来有人将其通讯协议破解,使得手柄可以用在遥控其他电器上,比如遥控控制机器人小车。

    最主要的是这款手柄,拿来就可以用,有人已经将其通讯协议破解了。
    具体可以参考极客工坊。 其PS2X_lib库,可以参见Github.
    这种摇杆有无线的和有线的,都是连接到Arduino上,我用的是有线的。

    这里写图片描述

    1. 手柄测试

    将库文件放入Arduino IDE的安装的libaries文件夹中。 然后可以使用其中的example 例程测试一下。
    程序如下:

    #include <PS2X_lib.h>  //for v1.6
    
    /******************************************************************
     * set pins connected to PS2 controller:
     *   - 1e column: original 
     *   - 2e colmun: Stef?
     * replace pin numbers by the ones you use
     ******************************************************************/
    #define PS2_DAT        13  //14    
    #define PS2_CMD        11  //15
    #define PS2_SEL        10  //16
    #define PS2_CLK        12  //17
    
    /******************************************************************
     * select modes of PS2 controller:
     *   - pressures = analog reading of push-butttons 
     *   - rumble    = motor rumbling
     * uncomment 1 of the lines for each mode selection
     ******************************************************************/
    //#define pressures   true
    #define pressures   false
    //#define rumble      true
    #define rumble      false
    
    PS2X ps2x; // create PS2 Controller Class
    
    //right now, the library does NOT support hot pluggable controllers, meaning 
    //you must always either restart your Arduino after you connect the controller, 
    //or call config_gamepad(pins) again after connecting the controller.
    
    int error = 0;
    byte type = 0;
    byte vibrate = 0;
    
    // Reset func 
    void (* resetFunc) (void) = 0;
    
    void setup(){
    
      Serial.begin(115200);
    
      delay(500);  //added delay to give wireless ps2 module some time to startup, before configuring it
    
      //CHANGES for v1.6 HERE!!! **************PAY ATTENTION*************
    
      //setup pins and settings: GamePad(clock, command, attention, data, Pressures?, Rumble?) check for error
      error = ps2x.config_gamepad(PS2_CLK, PS2_CMD, PS2_SEL, PS2_DAT, pressures, rumble);
    
      if(error == 0){
        Serial.print("Found Controller, configured successful ");
        Serial.print("pressures = ");
        if (pressures)
          Serial.println("true ");
        else
          Serial.println("false");
        Serial.print("rumble = ");
        if (rumble)
          Serial.println("true)");
        else
          Serial.println("false");
        Serial.println("Try out all the buttons, X will vibrate the controller, faster as you press harder;");
        Serial.println("holding L1 or R1 will print out the analog stick values.");
        Serial.println("Note: Go to www.billporter.info for updates and to report bugs.");
      }  
      else if(error == 1)
        Serial.println("No controller found, check wiring, see readme.txt to enable debug. visit www.billporter.info for troubleshooting tips");
    
      else if(error == 2)
        Serial.println("Controller found but not accepting commands. see readme.txt to enable debug. Visit www.billporter.info for troubleshooting tips");
    
      else if(error == 3)
        Serial.println("Controller refusing to enter Pressures mode, may not support it. ");
    
      type = ps2x.readType(); 
      switch(type) {
        case 0:
          Serial.println("Unknown Controller type found ");
          break;
        case 1:
          Serial.println("DualShock Controller found ");
          break;
        case 2:
          Serial.println("GuitarHero Controller found ");
          break;
        case 3:
          Serial.println("Wireless Sony DualShock Controller found ");
          break;
       }
    }
    
    void loop() {
      /* You must Read Gamepad to get new values and set vibration values
         ps2x.read_gamepad(small motor on/off, larger motor strenght from 0-255)
         if you don't enable the rumble, use ps2x.read_gamepad(); with no values
         You should call this at least once a second
       */  
      if(error == 1){ //skip loop if no controller found
        resetFunc();
      }
    
      if(type == 2){ //Guitar Hero Controller
        ps2x.read_gamepad();          //read controller 
    
        if(ps2x.ButtonPressed(GREEN_FRET))
          Serial.println("Green Fret Pressed");
        if(ps2x.ButtonPressed(RED_FRET))
          Serial.println("Red Fret Pressed");
        if(ps2x.ButtonPressed(YELLOW_FRET))
          Serial.println("Yellow Fret Pressed");
        if(ps2x.ButtonPressed(BLUE_FRET))
          Serial.println("Blue Fret Pressed");
        if(ps2x.ButtonPressed(ORANGE_FRET))
          Serial.println("Orange Fret Pressed"); 
    
        if(ps2x.ButtonPressed(STAR_POWER))
          Serial.println("Star Power Command");
    
        if(ps2x.Button(UP_STRUM))          //will be TRUE as long as button is pressed
          Serial.println("Up Strum");
        if(ps2x.Button(DOWN_STRUM))
          Serial.println("DOWN Strum");
    
        if(ps2x.Button(PSB_START))         //will be TRUE as long as button is pressed
          Serial.println("Start is being held");
        if(ps2x.Button(PSB_SELECT))
          Serial.println("Select is being held");
    
        if(ps2x.Button(ORANGE_FRET)) {     // print stick value IF TRUE
          Serial.print("Wammy Bar Position:");
          Serial.println(ps2x.Analog(WHAMMY_BAR), DEC); 
        } 
      }
      else { //DualShock Controller
        ps2x.read_gamepad(false, vibrate); //read controller and set large motor to spin at 'vibrate' speed
    
        if(ps2x.Button(PSB_START))         //will be TRUE as long as button is pressed
          Serial.println("Start is being held");
        if(ps2x.Button(PSB_SELECT))
          Serial.println("Select is being held");      
    
        if(ps2x.Button(PSB_PAD_UP)) {      //will be TRUE as long as button is pressed
          Serial.print("Up held this hard: ");
          Serial.println(ps2x.Analog(PSAB_PAD_UP), DEC);
        }
        if(ps2x.Button(PSB_PAD_RIGHT)){
          Serial.print("Right held this hard: ");
          Serial.println(ps2x.Analog(PSAB_PAD_RIGHT), DEC);
        }
        if(ps2x.Button(PSB_PAD_LEFT)){
          Serial.print("LEFT held this hard: ");
          Serial.println(ps2x.Analog(PSAB_PAD_LEFT), DEC);
        }
        if(ps2x.Button(PSB_PAD_DOWN)){
          Serial.print("DOWN held this hard: ");
          Serial.println(ps2x.Analog(PSAB_PAD_DOWN), DEC);
        }   
    
        vibrate = ps2x.Analog(PSAB_CROSS);  //this will set the large motor vibrate speed based on how hard you press the blue (X) button
        if (ps2x.NewButtonState()) {        //will be TRUE if any button changes state (on to off, or off to on)
          if(ps2x.Button(PSB_L3))
            Serial.println("L3 pressed");
          if(ps2x.Button(PSB_R3))
            Serial.println("R3 pressed");
          if(ps2x.Button(PSB_L2))
            Serial.println("L2 pressed");
          if(ps2x.Button(PSB_R2))
            Serial.println("R2 pressed");
          if(ps2x.Button(PSB_TRIANGLE))
            Serial.println("Triangle pressed");        
        }
    
        if(ps2x.ButtonPressed(PSB_CIRCLE))               //will be TRUE if button was JUST pressed
          Serial.println("Circle just pressed");
        if(ps2x.NewButtonState(PSB_CROSS))               //will be TRUE if button was JUST pressed OR released
          Serial.println("X just changed");
        if(ps2x.ButtonReleased(PSB_SQUARE))              //will be TRUE if button was JUST released
          Serial.println("Square just released");     
    
        if(ps2x.Button(PSB_L1) || ps2x.Button(PSB_R1)) { //print stick values if either is TRUE
          Serial.print("Stick Values:");
          Serial.print(ps2x.Analog(PSS_LY), DEC); //Left stick, Y axis. Other options: LX, RY, RX  
          Serial.print(",");
          Serial.print(ps2x.Analog(PSS_LX), DEC); 
          Serial.print(",");
          Serial.print(ps2x.Analog(PSS_RY), DEC); 
          Serial.print(",");
          Serial.println(ps2x.Analog(PSS_RX), DEC); 
        }     
      }
      delay(50);  
    }

    在IDE中编译后下载到Arduino中,打开串口监视器,如果顺利,会看到显示下列提示:

    如果提示未发现控制器,那就需要检查自己的连线等是不是有问题了,我在用的时候,因为杜邦线的问题,一直提示找不到控制器,我还怀疑是不是买的手柄有问题,又拿Stm32的板子来测试,折腾了半天竟然是线的问题。

    连接后,按下手柄上的各个键都会有相应提示,可以看出哪个按键定义的什么名字。
    在上述代码中,左边的四个按键只是显示按键按下,不会根据力的大小输出相应数值的,如果想要,就需要修改下列代码:

    上述程序第20行到23行将注释调换一下条改为:

    #define pressures   true
    //#define pressures   false
    #define rumble      true
    //#define rumble      false

    这样就可以实现通过按左侧”上下左右“按键的力度,输出不同的模拟值。

    2. 小车电机控制

    电机:有刷直流电机
    驱动器:L298n逻辑
    控制器:Arduino Mega2560

    程序功能实现:
    - 按下START键,开始前进;
    - 通过按PS2手柄左边的“上下左右”键实现前进 、后退、左转、右转。
    - 按SELECT键停止;

    #include <PS2X_lib.h>  //for v1.6
    
    /******************************************************************
     * set pins connected to PS2 controller:
     *   - 1e column: original 
     *   - 2e colmun: Stef?
     * replace pin numbers by the ones you use
     ******************************************************************/
    //PS2手柄引脚;
    #define PS2_DAT        13  //14    
    #define PS2_CMD        11  //15
    #define PS2_SEL        10  //16
    #define PS2_CLK        12  //17
    
    // 电机控制引脚;
    #define IN1 4
    #define IN2 5
    #define IN3 6
    #define IN4 7
    
     //PWM控制引脚;
      int speedPinA = 8;
      int speedPinB = 9;
    
    int speed;
    
    /******************************************************************
     * select modes of PS2 controller:
     *   - pressures = analog reading of push-butttons 
     *   - rumble    = motor rumbling
     * uncomment 1 of the lines for each mode selection
     ******************************************************************/
    #define pressures   true
    //#define pressures   false
    #define rumble      true
    //#define rumble      false
    
    PS2X ps2x; // create PS2 Controller Class
    
    //right now, the library does NOT support hot pluggable controllers, meaning 
    //you must always either restart your Arduino after you connect the controller, 
    //or call config_gamepad(pins) again after connecting the controller.
    
    int error = 0;
    byte type = 0;
    byte vibrate = 0;
    
     void setup(){
    
       pinMode(IN1, OUTPUT);
       pinMode(IN2, OUTPUT);
       pinMode(IN3, OUTPUT);
       pinMode(IN4, OUTPUT);
    
       speed =200;
    
       Serial.begin(57600);
       delay(300) ; //added delay to give wireless ps2 module some time to startup, before configuring it
       //CHANGES for v1.6 HERE!!! **************PAY ATTENTION*************
    
      //setup pins and settings: GamePad(clock, command, attention, data, Pressures?, Rumble?) check for error
      error = ps2x.config_gamepad(PS2_CLK, PS2_CMD, PS2_SEL, PS2_DAT, pressures, rumble);
    
      if(error == 0){
        Serial.print("Found Controller, configured successful ");
        Serial.print("pressures = ");
      if (pressures)
        Serial.println("true ");
      else
        Serial.println("false");
      Serial.print("rumble = ");
      if (rumble)
        Serial.println("true)");
      else
        Serial.println("false");
        Serial.println("Try out all the buttons, X will vibrate the controller, faster as you press harder;");
        Serial.println("holding L1 or R1 will print out the analog stick values.");
        Serial.println("Note: Go to www.billporter.info for updates and to report bugs.");
      }  
      else if(error == 1)
        Serial.println("No controller found, check wiring, see readme.txt to enable debug. visit www.billporter.info for troubleshooting tips");
    
      else if(error == 2)
        Serial.println("Controller found but not accepting commands. see readme.txt to enable debug. Visit www.billporter.info for troubleshooting tips");
    
      else if(error == 3)
        Serial.println("Controller refusing to enter Pressures mode, may not support it. ");
    
     //  Serial.print(ps2x.Analog(1), HEX);
    
      type = ps2x.readType(); 
      switch(type) {
        case 0:
          Serial.print("Unknown Controller type found ");
          break;
        case 1:
          Serial.print("DualShock Controller found ");
          break;
        case 2:
          Serial.print("GuitarHero Controller found ");
          break;
      case 3:
          Serial.print("Wireless Sony DualShock Controller found ");
          break;
       }
    }
    
     void turnLeft(){
       digitalWrite(IN1,HIGH);
       digitalWrite(IN2, LOW);
       digitalWrite(IN3, LOW);
       digitalWrite(IN4,HIGH);
    }
     void turnRight(){
      digitalWrite(IN1, LOW);
      digitalWrite(IN2, LOW);
      digitalWrite(IN3, HIGH);
      digitalWrite(IN4, LOW);      
    }
    
     void forward(){
      digitalWrite(IN1, HIGH);
      digitalWrite(IN2, LOW);
      digitalWrite(IN3, HIGH);
      digitalWrite(IN4, LOW);      
    }
    
     void back(){
      digitalWrite(IN1, LOW);
      digitalWrite(IN2, HIGH);
      digitalWrite(IN3, LOW);
      digitalWrite(IN4, HIGH);     
    }
    
     void loop(){
       /* You must Read Gamepad to get new values and set vibration values
         ps2x.read_gamepad(small motor on/off, larger motor strenght from 0-255)
         if you don't enable the rumble, use ps2x.read_gamepad(); with no values
         You should call this at least once a second
       */  
      if(error == 1) //skip loop if no controller found
        return; 
    
      if(type == 2) {//Guitar Hero Controller
      return;
      }
      else  { //DualShock Controller
        ps2x.read_gamepad(false, vibrate); //read controller and set large motor to spin at 'vibrate' speed
    
    
    //start 开始运行,电机初PWM为120;
        if(ps2x.Button(PSB_START))  {
           Serial.println("Start is being held");
           speed = 120;
           analogWrite(speedPinA, speed);
           analogWrite(speedPinB, speed);
           forward();                  
        }
    // 电机正转;
        if(ps2x.Button(PSB_PAD_UP)){
          Serial.println("Up held this hard: ");
          speed= 200;
          analogWrite(speedPinA, speed);
          analogWrite(speedPinB, speed);
          forward();                  
        }
    
    // 电机反转;
        if(ps2x.Button(PSB_PAD_DOWN)){
          Serial.print("Down held this hard: ");
          speed= 200;
          analogWrite(speedPinA, speed);
          analogWrite(speedPinB, speed);
          back();                  
        }
    
     //左转;   
        if(ps2x.Button(PSB_PAD_LEFT)){
           Serial.println("turn left ");
           analogWrite(speedPinA, speed);
           analogWrite(speedPinB, 0);
          turnLeft();        
        }
    
    //右转;
       if(ps2x.Button(PSB_PAD_RIGHT)){
        Serial.println("turn right");
        analogWrite(speedPinA, 0);
        analogWrite(speedPinB, speed);
        turnRight();
       }
    // Stop
       if(ps2x.Button(PSB_SELECT)){
       Serial.println("stop");
       speed = 0;
       analogWrite(speedPinA,speed);
       analogWrite(speedPinB,speed);
       }
    
      }
    }

    目前是拿来尝试一下,还是基于按键的实现,后面用摇杆来控制方向的速度。

    3. 摇杆控制

    功能实现:

    • 通过按PS2摇杆的“上下左右”移动实现前进 、后退、左转、右转。
    • 速度随摇杆位置变化而变化;
    
    
    /* 功能:通过按PS2摇杆的“上下左右”移动实现前进 、后退、左转、右转。
     * 
     * 作者:lcl;
     */
    #include <PS2X_lib.h>  //for v1.6
    /******************************************************************
     * set pins connected to PS2 controller:
     *   - 1e column: original
     *   - 2e colmun: Stef?
     * replace pin numbers by the ones you use
     ******************************************************************/
    //PS2手柄引脚;
    #define PS2_DAT        13  //14   
    #define PS2_CMD        11  //15
    #define PS2_SEL        10  //16
    #define PS2_CLK        12  //17
    // 电机控制引脚;
    #define IN1 4
    #define IN2 5
    #define IN3 6
    #define IN4 7
      int speedPinA = 8;
      int speedPinB = 9;
    int speed;
    //speed =200;
    /******************************************************************
     * select modes of PS2 controller:
     *   - pressures = analog reading of push-butttons
     *   - rumble    = motor rumbling
     * uncomment 1 of the lines for each mode selection
     ******************************************************************/
    #define pressures   true
    //#define pressures   false
    #define rumble      true
    //#define rumble      false
    PS2X ps2x; // create PS2 Controller Class
    //right now, the library does NOT support hot pluggable controllers, meaning
    //you must always either restart your Arduino after you connect the controller,
    //or call config_gamepad(pins) again after connecting the controller.
    int error = 0;
    byte type = 0;
    byte vibrate = 0;
     void setup(){
    
       pinMode(IN1, OUTPUT);
       pinMode(IN2, OUTPUT);
       pinMode(IN3, OUTPUT);
       pinMode(IN4, OUTPUT);
    
    
       Serial.begin(57600);
       delay(300) ; //added delay to give wireless ps2 module some time to startup, before configuring it
       //CHANGES for v1.6 HERE!!! **************PAY ATTENTION*************
    
      //setup pins and settings: GamePad(clock, command, attention, data, Pressures?, Rumble?) check for error
      error = ps2x.config_gamepad(PS2_CLK, PS2_CMD, PS2_SEL, PS2_DAT, pressures, rumble);
    
      if(error == 0){
        Serial.print("Found Controller, configured successful ");
        Serial.print("pressures = ");
      if (pressures)
        Serial.println("true ");
      else
        Serial.println("false");
      Serial.print("rumble = ");
      if (rumble)
        Serial.println("true)");
      else
        Serial.println("false");
        Serial.println("Try out all the buttons, X will vibrate the controller, faster as you press harder;");
        Serial.println("holding L1 or R1 will print out the analog stick values.");
        Serial.println("Note: Go to www.billporter.info for updates and to report bugs.");
      } 
      else if(error == 1)
        Serial.println("No controller found, check wiring, see readme.txt to enable debug. visit www.billporter.info for troubleshooting tips");
    
      else if(error == 2)
        Serial.println("Controller found but not accepting commands. see readme.txt to enable debug. Visit www.billporter.info for troubleshooting tips");
      else if(error == 3)
        Serial.println("Controller refusing to enter Pressures mode, may not support it. ");
    
     //  Serial.print(ps2x.Analog(1), HEX);
    
      type = ps2x.readType();
      switch(type) {
        case 0:
          Serial.print("Unknown Controller type found ");
          break;
        case 1:
          Serial.print("DualShock Controller found ");
          break;
        case 2:
          Serial.print("GuitarHero Controller found ");
          break;
      case 3:
          Serial.print("Wireless Sony DualShock Controller found ");
          break;
       }
    }
     void turnLeft() //左转
     {     
      digitalWrite(IN1,HIGH);
      digitalWrite(IN2, LOW);
      digitalWrite(IN3, LOW);
      digitalWrite(IN4,LOW);
      delay(20);
    }
     void turnRight()//右转
     {
       digitalWrite(IN1, LOW);
       digitalWrite(IN2, LOW);
       digitalWrite(IN3, HIGH);
       digitalWrite(IN4, LOW);
      delay(20);     
    }
     void forward() // 前进
     {
      digitalWrite(IN1, HIGH);
      digitalWrite(IN2, LOW);
      digitalWrite(IN3, HIGH);
      digitalWrite(IN4, LOW);  
      delay(20);  
    }
    void stop() // 停止;
     {
      digitalWrite(IN1, LOW);
      digitalWrite(IN2, LOW);
      digitalWrite(IN3, LOW);
      digitalWrite(IN4, LOW);
      delay(20);
    }
     void back()  //后退
     {
      digitalWrite(IN1, LOW);
      digitalWrite(IN2, HIGH);
      digitalWrite(IN3, LOW);
      digitalWrite(IN4, HIGH);    
    }
     void loop(){
       /* You must Read Gamepad to get new values and set vibration values
         ps2x.read_gamepad(small motor on/off, larger motor strenght from 0-255)
         if you don't enable the rumble, use ps2x.read_gamepad(); with no values
         You should call this at least once a second
       */ 
      if(error == 1) //skip loop if no controller found
        return;
    
      if(type == 2) {//Guitar Hero Controller
      return;
         }
      else  { //DualShock Controller
        ps2x.read_gamepad(false, vibrate); //read controller and set large motor to spin at 'vibrate' speed
        if(ps2x.Button(PSB_L1) || ps2x.Button(PSB_R1)) { //print stick values if either is TRUE
               Serial.print("Stick Values:");
               Serial.print(ps2x.Analog(PSS_LY), DEC); //Left stick, Y axis. Other options: LX, RY, RX
               Serial.print(",");
               Serial.print(ps2x.Analog(PSS_LX), DEC);
               Serial.print(",");
               Serial.print(ps2x.Analog(PSS_RY), DEC);
               Serial.print(",");
               Serial.println(ps2x.Analog(PSS_RX), DEC);
    
                 int LY=ps2x.Analog(PSS_LY);
                 int LX=ps2x.Analog(PSS_LX);
                 int RY=ps2x.Analog(PSS_RY);
                 int RX=ps2x.Analog(PSS_RX);
    
                 if (LY<128)  //前进
                 {
    
                        speed = 2*(127-LY);
                        //speed = LY;
                        analogWrite(speedPinA, speed);
                        analogWrite(speedPinB, speed);
                        forward();   
                 }
                 //后退
                 if (LY>128)
                 {
                        speed=2*(LY-128);
                        analogWrite(speedPinA, speed);
                        analogWrite(speedPinB, speed);
                        back();
                 }
                 //左转
                 if (LX<128)
                 {
                        speed = 2*(127-LX);
                        analogWrite(speedPinA, speed);
                        analogWrite(speedPinB, speed);
                        turnLeft();
                 }
                 //右转
                 if (LX>128)
                 {
                        speed=2*(LX -128);
                        analogWrite(speedPinA, speed);
                        analogWrite(speedPinB, speed);
                        turnRight();
                 }
                 //如果摇杆居中
                 if (LY>=128 && LY<=128 && LX>=128 && LX<=128)
                 {
                 stop();
                 }
        }
      }
    

    相关参考:
    1. http://yfrobot.com/forum.php?mod=viewthread&tid=11561&highlight=ps2
    2. Sony PS2游戏手柄遥控智能小车https://sanwen8.cn/p/375swwM.html
    3. SONY PS2电玩手柄遥控乐高小车

    展开全文
  • Arduino-PS2手柄汉化注释程序文件,网上大都是全英文的,这边汉化注释及串口通讯信息便于理解和移植。
  • PS2手柄代码移植 1、PS2手柄端口及通讯协议 PS2手柄的通讯协议是SPI协议是一种高速的、全双工、同步的通信总线,并且在芯片的管脚上只占用四根线(DI、DO、CS、CLK),PS2手柄的通讯协议破解后在C51、STM32、Arduino...
  • 最近做毕设,使用k64做四足机器人,想用ps2手柄来控制,根据协议和stm32的例程编写了ps2手柄与k60/k64-mcu通信例程和库。
  • 这份代码使我们参加2018Robocon 飞龙绣球编写的, 主要的作用就是操控手动车 包含 麦轮的驱动算法 4路编码器配置 中断配置 基于IIC的 OLED12864 以及 激光测距模块的 驱动 手动车的遥控是PS2 手柄这份代码凝聚了我们...
  • 咸鱼ZTMR实例—PS2手柄控制板载LED 之前在串口中输出了按钮的值。我们尝试使用这些值来做一些简单的操作,比如控制板载LED。来了解PS手柄使用方法。这个了解完成后我们就可以控制小车了。 主控板:ZTMR开发板 PS2...
  • 用cube移植PS2手柄--HAL库

    千次阅读 2019-11-28 22:34:06
    用cube移植PS2手柄–HAL库 STM32F4 PS2手柄移植HAL库,利用Cube进行设置 请按以下步骤进行 配置GPIO D0 input D1 output D2 output D3 output 详见下图 然后配置工程文件生成格式 生成MDK文件并用keil打开 ...
  • PS2手柄通讯协议解析—附资料和源码
  • PS2手柄驱动,索尼的,安装一下可以用遥感........
  • PS2手柄电脑驱动

    2013-06-27 18:35:04
    可以用PS2手柄在电脑上玩游戏。推荐使用。

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 781
精华内容 312
关键字:

ps2手柄