在Arduino项目中使用PS2游戏控制器
在PS3手柄连接Arduino这篇文章中,我们了解到PS3手柄要实现与Arduino的连接,必须通过USB HOST shield扩展板,并且需要加载 USB Host Library 才能实现。今天来了解一下, 在Arduino项目中如何使用Playstation 2游戏控制器 。
PS2手柄
Playstation的游戏控制器从开发至今已经非常完美了,它设计精良且功能强大,非常适合作为Arduino项目的控制端使用,比如遥控车、机械臂和多足机器人。尽管Playstation 2游戏机已经过时了,但Playstation 2的游戏控制器却仍在大量生产,我们可以通过很低的价格购买到。
不仅如此,PS2游戏手柄可以很容易的连接到Arduino,它还包含了两个高品质的操纵杆,同时所有的按钮都是压敏的,这就为操控设备增加了更多的功能。
下面我们将演示了如何将Playstation 2游戏控制器连接到Arduino,以及如何使用PS2Xlib Arduino库轻松地控制各种设备。
将PS2游戏控制器连接到Arduino
要将PS2控制器连接到Arduino有两个选择。粗暴的方法是切断连接器的电缆,将电线直接焊接到排针上。下图中的电线颜色可以帮助我们识别电线的功能(比如白灰色的电线是震动电机7V-9V的供电线)。

另一种方法是保留手柄原有接口,购买接口电路板实现。 下图是Playstation 2手柄的接口定义。为了连接Arduino,我们只需要连接Data、Command、GND、3.3V、Attention、Clock即可。如果需要震动反馈功能,震动电机的针需要连接到7-9V的电源上。

软件方面
说到软件,就一定要提到 Bill Porter,他编写了一个针对PS2手柄的库,这个库可以方便用户通过Arduino使用Playstation 2游戏控制器。这个库就是 PS2X library ,它的源代码我们可以从Github获得。下载后,将得到一个zip文件,这时可以通过Arduino IDE的导入ZIP库文件功能,直接导入 PS2X library 。

库中包含的示例文件可以很好地展示库的功能,和利用Playstation 2控制器的所有特性,它涵盖了使用Playstation 2控制器来驱动电机、舵机、伺服器和开关所需的基本内容。
要在Arduino中使用库,需要使用以下命令调用它:
#include <PS2X_lib.h> PS2X ps2x;
在代码的 setup 部分,要让Arduino知道PS2控制器是如何连接到它的,命令如下:
ps2x.config_gamepad(5,4,3,2, false, false);
代码中的数字为Arduino的数字引脚,对应Playstation 2控制器引脚连接如下:
PS2手柄 :clock、 command、attention、 data、 压力灵敏度enabled、震动反馈 enabled。
如果想使用按钮的压力敏感功能,在上面的命令行中,你会把这个设置为“true”,如果想让震动提供反馈,也把对应值设置为“true”。要使用震动反馈特性,请详细查看PS2X library 附带的示例文件。
PS2控制器连接设置好后,Arduino就会不断地循环执行。每次循环完成后,Arduino均与PS2控制器完成通信并收集所有的输入数据。这个过程是通过以下命令完成的:
ps2x.read_gamepad();
PS2游戏手柄的按键功能
在PS2X库中使用的标签非常符合逻辑。下图显示了按钮和操作杆对应的名称。

上图中为彩色的按钮可以通过对应的名称来引用,如:
PSB_TRIANGLE, PSB_CIRCLE, PSB_CROSS, and PSB_SQUARE.
在使用模拟的压感灵敏度功能时,前缀需要用“PSAB”代替“PSB”外,键名是相同的。比如,要允许绿色三角形按钮使用压力灵敏度时,名称应该是“PSAB_GREEN”或“PSAB_TRIANGLE”。
PS2按钮的操作有很多种,比如可以按下,按住保持,或不同的压力按下,所以也有许多 methods 可以应用于按钮和操纵杆。这些 methods 在PS2X库中包括 : Button Pressed
, Button
, 和 Analog
. 下面是一些如何使用这些方法的例子。
-
ps2x.ButtonPressed(PSB_RED)
表示简单的按下红色圆圈按钮 。 -
ps2x.Button(PSB_PAD_DOWN)
表示持续按住向下按钮。 -
ps2x.Analog(PSAB_CROSS)
表示用于测量施加到“X”按钮上的压力(如果启用了压力灵敏度)。按钮前缀已经使用了“PSAB”的形式。 -
ps2x.Analog(PSS_RY)
获取垂直方向上正确的模拟摇杆读数的命令。
PS2连接Arduino的实际运用
为了更深入说明PS2X库的使用,这里引入一个示例项目,它利用直流电机、电子速度控制器、一系列伺服电机和一个7-12V的LED阵列。如果将这些应用到实际项目中,它可能是一辆带有方向盘的汽车,包含两个额外的伺服电机来控制一个平移和倾斜支架,其他高电压和大电流的设备也可以由这样的系统触发。
下面是电路元件的示意图。ESC向伺服电机提供5.6V的电源。除此之外,连接Playstation 2游戏控制器和LED晶体管需要有三个1K的电阻,图中电容器不是必须的,因为电池供电已经能够提供一个相对平稳的电源。

PS2连接Arduino的实际运用
接下来,定义我们想要使用的功能项,包括:一个用于开关LED的功能,两个模拟操纵杆来驱动伺服电机和ESC。对应PS2手柄,功能项对应按键如下图:

控制代码
/* 以下代码演示了如何使用PS2游戏控制器来控制一系列伺服电机和电子速度控制器(ESC)和一个LED灯。 对应的接口连接如下: 1、Arduino 3.3V ——> PS2 3.3V 2、Arduino 5V ——> 两个1K上拉电阻的中点 3、Arduino D02 ——> PS2 data 4、Arduino D03 ——> PS2 attention 5、Arduino D04 ——> PS2 command 6、Arduino D05 ——> PS2 clock 7、Arduino D06 ——> ESC Signal 8、Arduino D07 ——> 转向舵机 Signal 9、Arduino D08 ——> Servo 1 Signal 10、Arduino D09 ——> Servo 2 Signal 11、ArduinoPin D13 ——> LED 晶体管基极 该代码使用了Bill Porter开发的PS2X库。 控制关系为: 右侧摇杆:X-axis = Steering Servo left/right, Y-axis = ESC forward/backward 左侧摇杆:X-axis = Servo 2 left/right, Y-axis = Servo 1 left/right 三角形按钮(Triangle) = Toggle the LED */ #include <Servo.h> //引入servo库 #include <PS2X_lib.h> // 引入PS2X库 PS2X ps2x; //PS2控制器类 Servo SteeringServo; //创建表示转向舵机的对象 Servo ServoN1; //创建表示舵机1的对象 Servo ServoN2; //创建表示舵机2的对象 Servo ESCcontrol; //创建代表ESC的对象 const int LEDpin = 13; //绿色LED在数字引脚13上 volatile boolean LEDHdlts; //LED开关 int PlyStnRStickUpDn = 0; //读取PS2右侧摇杆向上/向下的值. int PlyStnRStickLtRt = 0; //读取PS2右侧摇杆向左/向右的值. int PlyStnLStickUpDn = 0; //读取PS2左侧摇杆向上/向下的值. int PlyStnLStickLtRt = 0; //读取PS2左侧摇杆向左/向右的值. int ESCSetting = 90; //设置ESC(角度). int StrServoSetting = 90; //转向舵机的角度设置 int ServoN1Setting = 90; //舵机1的角度设置 int ServoN2Setting = 90; //舵机2的角度设置 void setup() { ps2x.config_gamepad(5,4,3,2, false, false); //手柄的针设置:clock, command, attention, data, Pressures, Rumble //禁用了压力灵敏度和震动反馈. pinMode(LEDpin, OUTPUT); //设置LED输出 LEDHdlts = false; //车头灯关闭 SteeringServo.attach(7);// 将转向舵机连接到数字7脚 ServoN1.attach(8);// 将舵机1连接到数字8脚 ServoN2.attach(9);// 将舵机2连接到数字8脚 ESCcontrol.attach(6,150,2250);// 将ESC连接到数字6脚 //上面的ESC命令还包括信号设置,值为ESC的最大值和最小值. //不同的ESC这个值会不一样. //将ESC和舵机置中90度. ESCcontrol.write(90); SteeringServo.write(90); ServoN1.write(90); ServoN2.write(90); delay(5000); //延迟5秒,等待ESC和控制器完全初始化. } void loop() { ps2x.read_gamepad(); //至少每秒调用一次,以便从控制器获取数据. if(ps2x.ButtonPressed(PSB_GREEN)) //三角按钮按下 { LEDHdlts = !LEDHdlts; //切换LED灯标记 } //Analogue Stick readings PlyStnRStickUpDn = ps2x.Analog(PSS_RY); //右侧摇杆上/下 PlyStnRStickLtRt = ps2x.Analog(PSS_RX); //右侧摇杆左/右 PlyStnLStickUpDn = ps2x.Analog(PSS_LY); //左侧摇杆上/下 PlyStnLStickLtRt = ps2x.Analog(PSS_LX); //左侧摇杆左/右 //PS2控制器的读数从0到255,中性点是128.对于x轴运动,0点在左边,对于y轴运动,0点在上面. //变量,用于存储ESCs和Servos的值. //PS2摇杆的值将映射到0到180度. ESCSetting = map(PlyStnRStickUpDn,-256,256,0,179); StrServoSetting = map(PlyStnRStickLtRt,-256,256,0,179); ServoN1Setting = map(PlyStnLStickUpDn,-256,256,0,179); ServoN2Setting = map(PlyStnLStickLtRt,-256,256,0,179); //将值写入到Servos或ESCs ESCcontrol.write(ESCSetting); SteeringServo.write(StrServoSetting); ServoN1.write(ServoN1Setting); ServoN2.write(ServoN2Setting); digitalWrite(LEDpin,LEDHdlts); //根据LED灯的状态标志点亮LED delay(15); }
当一切就绪后,连接电池后,就能够通过按下三角形按钮来点亮LED,移动操纵杆来控制舵机和运行电机了。