使用手柄遙控小車(chē)是經(jīng)常要用到的,看到PS2手柄很6,就拿來(lái)嘗試一下。
PS2手柄是索尼的PlayStation2游戲機的遙控手柄,因為這款手柄性?xún)r(jià)比較高,按鍵豐富,方便擴展到其它應用中,后來(lái)有人將其通訊協(xié)議破解,使得手柄可以用在遙控其他電器上,比如遙控控制機器人小車(chē)。
最主要的是這款手柄,拿來(lái)就可以用,有人已經(jīng)將其通訊協(xié)議破解了。
具體可以參考極客工坊。 其PS2X_lib庫,可以參見(jiàn)Github.
這種搖桿有無(wú)線(xiàn)的和有線(xiàn)的,都是連接到Arduino上,我用的是有線(xiàn)的。
將庫文件放入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 falsePS2X 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中,打開(kāi)串口監視器,如果順利,會(huì )看到顯示下列提示:
如果提示未發(fā)現控制器,那就需要檢查自己的連線(xiàn)等是不是有問(wèn)題了,我在用的時(shí)候,因為杜邦線(xiàn)的問(wèn)題,一直提示找不到控制器,我還懷疑是不是買(mǎi)的手柄有問(wèn)題,又拿Stm32的板子來(lái)測試,折騰了半天竟然是線(xiàn)的問(wèn)題。
連接后,按下手柄上的各個(gè)鍵都會(huì )有相應提示,可以看出哪個(gè)按鍵定義的什么名字。
在上述代碼中,左邊的四個(gè)按鍵只是顯示按鍵按下,不會(huì )根據力的大小輸出相應數值的,如果想要,就需要修改下列代碼:
上述程序第20行到23行將注釋調換一下條改為:
#define pressures true//#define pressures false#define rumble true//#define rumble false這樣就可以實(shí)現通過(guò)按左側”上下左右“按鍵的力度,輸出不同的模擬值。
電機:有刷直流電機
驅動(dòng)器:L298n邏輯
控制器:Arduino Mega2560
程序功能實(shí)現:
- 按下START鍵,開(kāi)始前進(jìn);
- 通過(guò)按PS2手柄左邊的“上下左右”鍵實(shí)現前進(jìn) 、后退、左轉、右轉。
- 按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 falsePS2X 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 開(kāi)始運行,電機初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); } }}目前是拿來(lái)嘗試一下,還是基于按鍵的實(shí)現,后面用搖桿來(lái)控制方向的速度。
功能實(shí)現:
/* 功能:通過(guò)按PS2搖桿的“上下左右”移動(dòng)實(shí)現前進(jìn) 、后退、左轉、右轉。 * * 作者: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 falsePS2X 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() // 前進(jìn) { 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) //前進(jìn) { 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(); } } }相關(guān)參考:
1. http://yfrobot.com/forum.php?mod=viewthread&tid=11561&highlight=ps2
2. Sony PS2游戲手柄遙控智能小車(chē)https://sanwen8.cn/p/375swwM.html
3. SONY PS2電玩手柄遙控樂(lè )高小車(chē)
聯(lián)系客服