├── .gitignore ├── Configuration.png ├── library.properties ├── examples ├── gamepad_servo │ └── gamepad_servo.ino └── gamepad_RX │ └── gamepad_RX.ino ├── gamepad_ps4bt.h ├── gamepad_ps4bt.cpp └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | .dropbox 3 | -------------------------------------------------------------------------------- /Configuration.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/semuadmin/Gamepad_PS4BT/HEAD/Configuration.png -------------------------------------------------------------------------------- /library.properties: -------------------------------------------------------------------------------- 1 | name=Gamepad_PS4BT 2 | version=0.2.0 3 | author=semuadmin 4 | maintainer=semuadmin 5 | sentence=Library for PS3/4 controller via Bluetooth Serial adapter 6 | paragraph= 7 | category=Sensors 8 | url=https://github.com/semuconsulting/Gamepad_PS4BT.git 9 | architectures=* 10 | -------------------------------------------------------------------------------- /examples/gamepad_servo/gamepad_servo.ino: -------------------------------------------------------------------------------- 1 | /* 2 | PS3/4 Bluetooth Gamepad Controller servo test 3 | I2C interface 4 | 5 | Using Hobbytronics USB Host adapter configured with PS3/4 Bluetooth software running in I2C mode 6 | http://www.hobbytronics.co.uk/usb-host/ps3-ps4-controller-bluetooth 7 | 8 | */ 9 | 10 | #include "gamepad_ps4bt.h" 11 | #include 12 | 13 | Gamepad_PS4BT ps4 = Gamepad_PS4BT(0x29); 14 | 15 | uint8_t ledpin = LED_BUILTIN; 16 | uint8_t xpin = 2; 17 | uint8_t ypin = 3; 18 | uint16_t lastx = 128; 19 | uint16_t lasty = 128; 20 | PWMServo xservo; 21 | PWMServo yservo; 22 | 23 | 24 | void setup() { 25 | // initialize serial communication at 57600 bits per second: 26 | // this is best rate for xbee radios 27 | 28 | pinMode(ledpin, OUTPUT); 29 | digitalWrite(ledpin, LOW); 30 | 31 | xservo.attach(xpin); 32 | yservo.attach(ypin); 33 | 34 | } 35 | 36 | //************************************************************************************** 37 | // Main loop 38 | //************************************************************************************** 39 | void loop() { 40 | 41 | if (ps4.get_data() == 0){ 42 | 43 | // set the servo according to the left joystick Y value 44 | setServoHead(ps4.l_joystick_x, ps4.l_joystick_y); 45 | 46 | // set the LED according to the L1 button press 47 | setLED(ps4.button_l1); 48 | 49 | } 50 | 51 | delay(50); 52 | 53 | } 54 | 55 | void setServoHead (uint16_t x, uint16_t y) { 56 | 57 | if (abs(lastx - x) > 15) { 58 | lastx = x; 59 | x = map(x, 0, CTL_MAX, 0, 180); 60 | xservo.write(x); 61 | 62 | } 63 | 64 | if (abs(lasty - y) > 15) { 65 | lasty = y; 66 | y = map(y, 0, CTL_MAX, 0, 180); 67 | yservo.write(y); 68 | 69 | } 70 | 71 | } 72 | 73 | void setLED (bool val) { 74 | 75 | digitalWrite(ledpin, val); 76 | 77 | } 78 | -------------------------------------------------------------------------------- /gamepad_ps4bt.h: -------------------------------------------------------------------------------- 1 | /* 2 | PS4 Bluetooth Gamepad Controller 3 | I2C Interface 4 | 5 | Using Hobbytronics USB Host adapter configured with PS3/4 Bluetooth software running in I2C Mode 6 | http://www.hobbytronics.co.uk/usb-host/ps3-ps4-controller-bluetooth 7 | 8 | */ 9 | 10 | #ifndef _GAMEPAD_PS4BT_H_ 11 | #define _GAMEPAD_PS4BT_H_ 12 | 13 | #include 14 | #include 15 | 16 | #define DEFAULT_I2C_ADDRESS 0x29 17 | #define POLL_INTERVAL 20 // poll every 20 milliseconds 18 | #define CTL_MAX 255 // maximum analogue control value (8-bit = 255, 10-bit = 1023) 19 | #define PS4_I2C_LEN 14 20 | #define PS4_OK 0 21 | 22 | class Gamepad_PS4BT { 23 | 24 | public: 25 | 26 | unsigned char l_joystick_x; 27 | unsigned char l_joystick_y; 28 | unsigned char r_joystick_x; 29 | unsigned char r_joystick_y; 30 | unsigned char accel_x; 31 | unsigned char accel_y; 32 | unsigned char l2; 33 | unsigned char r2; 34 | 35 | unsigned char button_left; 36 | unsigned char button_down; 37 | unsigned char button_right; 38 | unsigned char button_up; 39 | unsigned char button_square; 40 | unsigned char button_x; 41 | unsigned char button_circle; 42 | unsigned char button_triangle; 43 | 44 | unsigned char button_l1; 45 | unsigned char button_r1; 46 | unsigned char button_l2; 47 | unsigned char button_r2; 48 | unsigned char button_share; 49 | unsigned char button_options; 50 | unsigned char button_l3; 51 | unsigned char button_r3; 52 | 53 | unsigned char button_ps4; 54 | unsigned char button_tpad; 55 | 56 | unsigned char tpad_x; 57 | unsigned char tpad_y; 58 | unsigned char battery; 59 | 60 | Gamepad_PS4BT(uint8_t i2c_addr = DEFAULT_I2C_ADDRESS); 61 | uint8_t get_data(void); 62 | void decode_data(void); 63 | 64 | private: 65 | 66 | uint8_t _i2c_addr; 67 | unsigned char _ps4_ic2[PS4_I2C_LEN]; 68 | 69 | }; 70 | 71 | #endif 72 | -------------------------------------------------------------------------------- /examples/gamepad_RX/gamepad_RX.ino: -------------------------------------------------------------------------------- 1 | /* 2 | Test of USB Host board with PS3/4 Bluetooth software in I2C mode 3 | */ 4 | 5 | #include "gamepad_ps4bt.h" 6 | 7 | #define baudRate 57600 8 | 9 | unsigned long time; 10 | String buttons; 11 | Gamepad_PS4BT ps4 = Gamepad_PS4BT(0x29); 12 | 13 | void setup() { 14 | 15 | SerialUSB.begin(baudRate); 16 | time = 0; 17 | while (!SerialUSB); 18 | SerialUSB.println("good to go"); 19 | 20 | } 21 | 22 | void loop() { 23 | 24 | if (ps4.get_data() == 0) { 25 | 26 | //Print out some of the data 27 | SerialUSB.print ("Left Joystick X = "); 28 | SerialUSB.print(ps4.l_joystick_x); 29 | SerialUSB.print(", Y = "); 30 | SerialUSB.println(ps4.l_joystick_y); 31 | SerialUSB.print ("Right Joystick X = "); 32 | SerialUSB.print(ps4.r_joystick_x); 33 | SerialUSB.print(", Y = "); 34 | SerialUSB.println(ps4.r_joystick_y); 35 | 36 | SerialUSB.print ("Tpad X = "); 37 | SerialUSB.println(ps4.tpad_x); 38 | SerialUSB.print ("Tpad Y = "); 39 | SerialUSB.println(ps4.tpad_y); 40 | 41 | SerialUSB.print ("Left 2 Pressure = "); 42 | SerialUSB.println(ps4.l2); 43 | SerialUSB.print ("Right 2 Pressure = "); 44 | SerialUSB.println(ps4.r2); 45 | 46 | buttons = "Buttons pressed: "; 47 | 48 | if (ps4.button_l3) { 49 | buttons = buttons + " JR "; 50 | } 51 | if (ps4.button_r3) { 52 | buttons = buttons + " Start "; 53 | } 54 | if (ps4.button_l1) { 55 | buttons = buttons + " L1 "; 56 | } 57 | if (ps4.button_l2) { 58 | buttons = buttons + " L2 "; 59 | } 60 | if (ps4.button_r1) { 61 | buttons = buttons + " R1 "; 62 | } 63 | if (ps4.button_r2) { 64 | buttons = buttons + " R2 "; 65 | } 66 | if (ps4.button_up) { 67 | buttons = buttons + " UP "; 68 | } 69 | if (ps4.button_down) { 70 | buttons = buttons + " DOWN "; 71 | } 72 | if (ps4.button_left) { 73 | buttons = buttons + " LEFT "; 74 | } 75 | if (ps4.button_right) { 76 | buttons = buttons + " RIGHT "; 77 | } 78 | if (ps4.button_triangle) { 79 | buttons = buttons + " Triangle "; 80 | } 81 | if (ps4.button_circle) { 82 | buttons = buttons + " Circle "; 83 | } 84 | if (ps4.button_x) { 85 | buttons = buttons + " X "; 86 | } 87 | if (ps4.button_square) { 88 | buttons = buttons + " Square "; 89 | } 90 | if (ps4.button_share) { 91 | buttons = buttons + " Select "; 92 | } 93 | if (ps4.button_options) { 94 | buttons = buttons + " JL "; 95 | } 96 | if (ps4.button_ps4) { 97 | buttons = buttons + " PS3 "; 98 | } 99 | 100 | SerialUSB.println (buttons); 101 | 102 | } 103 | 104 | delay(POLL_INTERVAL); 105 | 106 | } 107 | -------------------------------------------------------------------------------- /gamepad_ps4bt.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | PS4 Bluetooth Gamepad Controller 3 | I2C interface 4 | 5 | Using Hobbytronics USB Host adapter configured with PS3/4 Bluetooth software running in I2C Mode 6 | http://www.hobbytronics.co.uk/usb-host/ps3-ps4-controller-bluetooth 7 | 8 | */ 9 | 10 | #include 11 | 12 | //************************************************************************ 13 | // Class creator for both transmitter and receiver 14 | //************************************************************************ 15 | Gamepad_PS4BT::Gamepad_PS4BT(uint8_t i2c_addr) { 16 | 17 | _i2c_addr = i2c_addr; 18 | 19 | } 20 | 21 | uint8_t Gamepad_PS4BT::get_data(void) { 22 | 23 | // Get data from PS4 DualShock Controller via I2C 24 | // We only want single byte values (0 to 255) 25 | 26 | unsigned char i2c_index=0; 27 | Wire.beginTransmission(_i2c_addr); // transmit to device 28 | Wire.write(0); // Start receiving data from register 0 29 | Wire.endTransmission(); // end transmission 30 | 31 | Wire.requestFrom(_i2c_addr, PS4_I2C_LEN); // request PS4_I2C_LEN bytes from PS4 32 | while(Wire.available()) 33 | { 34 | _ps4_ic2[i2c_index++] = Wire.read(); // receive a byte and increment index 35 | } 36 | 37 | decode_data(); 38 | 39 | return PS4_OK; 40 | 41 | } 42 | 43 | // Decode PS4 Data and move to struct 44 | void Gamepad_PS4BT::decode_data(void){ 45 | 46 | l_joystick_x = _ps4_ic2[0]; 47 | l_joystick_y = _ps4_ic2[1]; 48 | r_joystick_x = _ps4_ic2[2]; 49 | r_joystick_y = _ps4_ic2[3]; 50 | accel_x = _ps4_ic2[4]; 51 | accel_y = _ps4_ic2[5]; 52 | l2 = _ps4_ic2[6]; 53 | r2 = _ps4_ic2[7]; 54 | 55 | if(((_ps4_ic2[8]&0x0F)==5) || ((_ps4_ic2[8]&0x0F)==6) || ((_ps4_ic2[8]&0x0F)==7)) button_left=1; else button_left=0; //W 56 | if(((_ps4_ic2[8]&0x0F)==3) || ((_ps4_ic2[8]&0x0F)==4) || ((_ps4_ic2[8]&0x0F)==5)) button_down=1; else button_down=0; //S 57 | if(((_ps4_ic2[8]&0x0F)==1) || ((_ps4_ic2[8]&0x0F)==2) || ((_ps4_ic2[8]&0x0F)==3)) button_right=1; else button_right=0; //E 58 | if(((_ps4_ic2[8]&0x0F)==0) || ((_ps4_ic2[8]&0x0F)==1) || ((_ps4_ic2[8]&0x0F)==7)) button_up=1; else button_up=0; //N 59 | button_square =((_ps4_ic2[8]&0b00010000)>>4); // SQUARE 60 | button_x =((_ps4_ic2[8]&0b00100000)>>5); // X 61 | button_circle =((_ps4_ic2[8]&0b01000000)>>6); // CIRCLE 62 | button_triangle=((_ps4_ic2[8]&0b10000000)>>7); // TRIANGLE 63 | 64 | button_l1 =((_ps4_ic2[9]&0b00000001)); // L1 65 | button_r1 =((_ps4_ic2[9]&0b00000010)>>1); // R1 66 | button_l2 =((_ps4_ic2[9]&0b00000100)>>2); // L2 67 | button_r2 =((_ps4_ic2[9]&0b00001000)>>3); // R2 68 | button_share =((_ps4_ic2[9]&0b00010000)>>4); // SHARE 69 | button_options=((_ps4_ic2[9]&0b00100000)>>5); // OPTIONS 70 | button_l3 =((_ps4_ic2[9]&0b01000000)>>6); // L3 71 | button_r3 =((_ps4_ic2[9]&0b10000000)>>7); // R3 72 | 73 | button_ps4 =((_ps4_ic2[10]&0b00000001)); // PS4 74 | button_tpad =((_ps4_ic2[10]&0b00000010)>>1); // TPAD 75 | 76 | tpad_x = _ps4_ic2[11]; 77 | tpad_y = _ps4_ic2[12]; 78 | battery = _ps4_ic2[13]; 79 | 80 | } 81 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | # Gamepad_PS4BT 3 | 4 | Arduino library for standard PS3 or PS4 gamepad controller in conjunction with a [Hobbytronics USB Host adapter loaded with PS3/4 Bluetooth software running 5 | in I2C mode](http://www.hobbytronics.co.uk/usb-host/ps3-ps4-controller-bluetooth). 6 | 7 | ![Configuration](/Configuration.png) 8 | 9 | **This is a personal project and I am in no way affiliated to Hobbytronics.** 10 | 11 | Two example sketches are provided for the receiving MCU - gamepad_RX.ino provides a basic test facility; gamepad_servo.ino illustrates how to control a servo and LED 12 | using a gamepad joystick and button. 13 | 14 | Some of the code has been adapted from the ps4_hex header example provided by Hobbytronics, 15 | with the intention of providing a comparable gamepad class library to the companion [DFRobot (Leonardo/XBee) gamepad 16 | library](https://github.com/semuconsulting/Gamepad_DFRobot) and allowing end users to adopt one or other type of controller more or less interchangeably. 17 | 18 | **SEMU Consulting 2018** 19 | 20 | ## Wiring Connections for receiving device 21 | 22 | * 5V on USB Host board --> 5V on Arduino 23 | * 0V on USB Host board --> GND on Arduino 24 | * SDA on USB Host board --> SDA on Arduino (pin A4 on Uno) 25 | * SCL on USB Host board --> SCL on Arduino (pin A5 on Uno) 26 | * USB on USB Host board --> USB Bluetooth dongle 27 | 28 | **NB:** if you are stacking multiple I2C devices, ensure: 29 | * Each device has a unique I2C address. You can use the [I2C_Scanner](https://playground.arduino.cc/Main/I2cScanner/) utility to check current 30 | I2C device addresses. 31 | * The SDA and SCL lines have adequate PULL-UP provision. It may be necessary to 32 | add 4k7ohm resistors between VCC (3.3V / 5V) and the SDA and SCL lines for stability. 33 | 34 | ## Enabling I2C mode on the USB Host board 35 | 36 | **NB:** the Hobbytronics USB Host boards normally come pre-configured in I2C mode. 37 | If this has been changed to Serial at any point, it will be necessary to change the 38 | settings via the USB Host board's UART port, typically via an [FTDI USB-Serial adapter](http://www.hobbytronics.co.uk/prototyping/usb-serial-adapter/ftdi-basic). 39 | If a suitable FTDI adapter is not available, the configuration can be done using an Arduino UNO as a makeshift USB-Serial adapter. 40 | 41 | ### Configuring the USB Host board via an FTDI USB-Serial adapter: 42 | 43 | Remove any USB device from the Host board. Connect to the FTDI adapter as follows: 44 | 45 | * 5V on FTDI adapter --> 5V on Host board 46 | * 0V on FTDI adapter --> GND on Host board 47 | * TX on FTDI adapter --> RX on Host board 48 | * RX on FTDI adapter --> TX on Host board 49 | * USB on FTDI adapter --> USB port on PC (make a note of the COM port used) 50 | 51 | Connect to the relevant COM port using a terminal utility like PuTTY (Windows) or Screen (MacOS), 52 | configured for Serial comms on the relevant port at 9600 baud. Type ? or HELP at the 53 | command prompt - you should see a settings report as follows. 54 | 55 | ``` 56 | USB Host Ps4 Dual Shock Controller v1.04 57 | 58 | DEVICE - Select Playstation controller that will be connected 59 | (PS4) [PS3|PS4] 60 | SERIAL - Set Serial Data Output On/Off 61 | (ON) - [ON|OFF] 62 | HEX - Set Serial Data Output Hexadecimal On/Off 63 | (ON) - [ON|OFF] 64 | BAUD - Set Serial Port Baud Rate 65 | [2400|4800|9600|14400|19200|38400|57600|115200] 66 | I2C - Set I2C Address 67 | (41 ) [1 - 127] 68 | RGB - Set PS4 LED RGB value when connected (PS4 only) 69 | (0000A0) 70 | SYNC - Display SYNC how-to information for specified controller 71 | HELP or ? - display help 72 | ``` 73 | 74 | 1. Enter the command BAUD 57600 and click Send. Then reset the baud rate on the terminal session to 57600 and reconnect. 75 | 2. Enter the command SERIAL OFF and click Send. 76 | 3. Enter the command HEX OFF and click Send. 77 | 4. Then type ? or HELP again and you should see that SERIAL and HEX modes are now both ON. 78 | ``` 79 | SERIAL - Set Serial Data Output On/Off 80 | (OFF) - [ON|OFF] 81 | HEX - Set Serial Data Output Hexadecimal On/Off 82 | (OFF) - [ON|OFF] 83 | ``` 84 | 85 | ### Configuring the USB Host board using an Arduino as a USB-Serial adapter: 86 | 87 | **(This temporary configuration is only necessary if not using an FTDI adapter)** 88 | 89 | * 5V on Arduino --> 5V on Host board 90 | * 0V on Arduino --> GND on Host board 91 | * TX on Arduino --> TX on Host board (i.e. opposite way round to normal) 92 | * RX on Arduino --> RX on Host board 93 | * RESET pin on Arduino --> GND on Arduino (this is to bypass the Arduino's internal UART chip so we're talking directly to the Host board) 94 | 95 | 1. Remove any device from the USB port of the Host board 96 | 2. Open up the Serial Monitor in the Arduino IDE and set the line mode to "Carriage return" and the baud rate to 9600. 97 | 3. Follow the series of commands listed above in the FTDI configuration section. 98 | 4. Once complete, turn everything off, insert the Bluetooth dongle in the USB Host board and reconnect as per the normal wiring connections shown above. 99 | 100 | 101 | 102 | ## Compatibility 103 | 104 | 105 | MCU | Tested Works | Doesn't Work | Not Tested | Notes 106 | ------------------- | :----------: | :----------: | :---------: | ----- 107 | Arduino UNO | X | | | 108 | Arduino Micro | X | | | 109 | Arduino Zero | X | | | 110 | Arduino DUE | X | | | 111 | Teensy 3.2 @ 72MHz | X | | | 112 | Teensy 3.6 @ 96MHz | X | | | 113 | Teensy 4.0 @ 600MHz | X | | | 114 | 115 | 116 | --------------------------------------------------------------------------------