Top

Use PS2 controller on PC and PS3 with Arduino

ITALIAN VERSION HERE.

Completely made in Italy but used in the entire world, Arduino is one of the most famous existing single-board microcontroller, it allows us to execute a lot of operations and so it is largely used in the development and prototyping of various devices.

One of the possible application that we can make of Arduino is to use it as a converter: we can convert the Play Station 2 controller into a fully compatible PC or PS3 controller.

WARNING: this tutorial is to be considered for illustrative purposes only. We don’t assume any responsability for any possible damage caused.

Let’s start! First, take all the necessary:

  • Arduino Uno (Leonardo and Mega are also good): if you haven’t already bought it, and you want  only to convert your PS2 controller, don’t do it. Converters are avaiable on the net (especially eBay) for few bucks.
  • Arduino IDE.
  • Library/firmware UnoJoy: you can download it from Google Code, selecting your OS and your Arduino model.
  • PS2X library: created by Bill Porter, it is avaiable for download from his site (there is a “Download PS2X” link).
  • Breadboard (optional but highly recommended)
  • A 10kOhm resistor.
  • And, of course, a PS2 controller that you no longer need (it is advisable to cut the connector, even if you can avoid it).

A little opening warning: the vibration won’t work (it requires the use of transistors).

FIRST STEP: let’s do the wiring!

It’s good to know that the PS2 controller has 9 wires (or 8, for the latest) that could differ in color.

The most common colors are the following (of which you can find an image on Curious Inventer):

White: unknown function (it is the missing cable on the 8-wires controllers)

Grey: vibration.

Green: acknowledge, it is used in communication between controller and PS2, we don’t need it.

BLACK: it is the common ground cable.

RED:it is the positive DC supply (3.3V).

BROWN: it is the data cable used by the controller to send data to the Play Station.

ORANGE: it  is the “command”, used by the Play Station to send commands to the controller.

YELLOW: “attention”.

BLUE: it is the clock, we use it for establishing the correct data transmission speed.

Well, now we have to make the wiring: take the breadboard and the 10kOhm resistor and let’s start.

These are the connections that we need and as you can see they are pretty simple.

Collegamenti Arduino

I have also made a Fritzing scheme (the green water is the orange wire).

collegamenti

So, we have to take a wire, strip it and wrap the conductive material around one side of the two jumpers  (leaving the other free) and put it on the breadboard. Repeat this operation for all the used wires (they are six) leaving between them 2 free breadboard holes to avoid short circuits. Then link the wires following my same order (black, red, brown, orange, yellow and blu) to avoid bad connections.

Take the black cable on the other jumper side (the one we  left free) and link it to one of the GND PINs on Arduino. Then take the 10kOhm resistor and put it on the breadboard (as in the images) and connect the red wire to one resistor side and, with another jumper, connect in series the 3.3V (on the same resistor side, check images if you haven’t understood). On the other resistor side, connect the brown cable (in my image, it is the green jumper) and in series connect it to PIN 11 (watch the scheme).

After that, connect the orange wire to PIN 9, the yellow one to PIN 8 and the blue one to PIN 10.

We have finished the wiring!

SECOND STEP: Coding

Now we  arrived to a crucial point: the Arduino program coding!

Open the Arduino IDE and import the PS2X library (that we  already downloaded and unpacked). We have to click Sketch >> Import Library >> Add Library and then select the folder PS2X_lib.

Ok, now open the UnoJoy folder (or LeoJoy or MegaJoy). There is a folder called “UnoJoyArduinoSample“, that contains a .ino and a .h file, copy and paste it and rename the duplicate file just created as you like, I called it playstation.

Open the playstation folder and rename the .ino file in playstation.ino, after that read the ino with the IDE. Delete all the code (CTRL+A and then CANC) and paste the following (you can download the file here)

After that verify and upload it to Arduino.

If there are problems during the compilation, for a missing folder, try to do Sketch >> Import librery >> PS2X_lib.

If the compiler continues to give you errors, try to look for the problem and send a comment: I’ll be happy to help you!

Well, save and close the IDE and open the UnoJoy folder. There is a subfolder named “UnoJoyProcessingVisualizer“, open it and run the executable file.

A windows will pop up showing a joystick: select the right COM port and test if the controller is working properly. If no, chek the wiring!

THIRD STEP: transform Arduino into a Joystick/Controller

We  arrived at the last step: the most decisive.

Now we are going to modify the Arduino’s USBtoSerial chip, the Atmega16U2 or the Atmega8U2 (the one near the USB port)

I want to remember that I won’t assume any responsability for any damage caused and I would like to specify that this is a risky operation that can harm your Arduino (it couldn’t work anymore).

The Arduino DFU mode requires sometimes a modification to the chip consisting of the addition of a resistor, I suggest you to inform yourselves about the DFU mode of your Arduino’s model before proceeding.

First thing you have to do is to install the drivers (they are in the Drivers folder), then, if you use windows, you have to install Atmel’s FLIP.

Next, you have to put Arduino in DFU mode (at your own risk). You can do this by shortcircuiting the 2 pin nearest the USB (see the picture).

Modalità DFU

After that, your Arduino should be recognized as Atmega16U2 (or Atmega8U2). If it won’t try reinstalling the drivers.

In the DFU mode, open the UnoJoy folder and execute TurnIntoAJoystick. After few seconds you have to press a key (as requested) and next you have to unplug and replug the USB cable. Now your PS2 controller is working also on PC and PS3!

Here are some screens showing its behaviour:

unojoy

The Axis works also well, of course.

unojoy2

BACK TO ARDUINO

When you want to turn back to Arduino, the only thing you need to do is  to put the Arduino in DFU mode, execute TurnIntoAnArduino (into UnoJoy folder), wait for few seconds and then reconnect the USB: Arduino is back!

Don’t hesitate to comment if you have problems, we will try to resolve them!

  • Pingback: Usare joystick PS2 sul PC e sulla PS3 con Arduino. | TecnoMenteTecnoMente()

  • sameera

    hi i have problem with my joystick…!!problem is,i connected mine as u said in this article.but when i reached to calibrating part of joystick, all the buttons and other rotations varying without pressing anything.. can you give a solution for that? im using wireless ps2 joystick.

    • Hi,
      are you using the PS2 controller or another one?

      • sameera

        hi , thank you for replying me, im just using wireless ps2 controller which compatible for arduino.

        • I don’t know if the code works also with the PS2 wireless controller but it should!
          Are you sure to have connected the wires in the correct way?
          Is it the original controller? If it is made by another vendor the (wires) colors can be different!

          • sameera

            yes wires are correct….!! ok ill check again.. thank you

          • I have the same problem my friend. did you get it working?

  • rook

    i need help idk by but my controller stuck at button 8 and 9

    • What do you mean? Are your 8 and 9 buttons always clicked (in UnoJoyProcessingVisualizer) when they are not so? What happens if you press them ? They become unclicked?
      Probably yuo will have to edit the code!

      Can you tell me if your gamepad is the original or a bought one (not official)?

  • Kyle

    I’m trying to get this working, but I got a few errors in the code. I changed &.lt;= to <= and the code uploads fine. My computer is recognizing the controller as a joystick, but it isn't registering any buttons or analog sticks. I have checked the wiring numerous times and it should be working. Any ideas on how to fix this?

    • Hi Kyle,
      just noticed there are some encoding problems in the code, I’ll fix as soon as possibile.
      Other then the “<=", you have to correct the first two lines in:
      #include "UnoJoy.h"
      #include //remove the spaces between the brackets

      Let me now if it helps!

      EDIT: code corrected!

      • Kyle

        Hey, I also changed those ones already, but it’s still either registering no buttons pressed or a ton of buttons being pressed depending on what resistor I use (I’ve tried almost every value between 1k and 40k).

        I also noticed that changing the “type” variable to 2 seems to fix it somewhat but I have no clue what that’s actually doing. (It made button 9 always stay on and pressing other buttons would randomly make 2 of the buttons light up in the joystick settings window)

        Also, I just double checked all the connections for the wiring and for some reason, the analog led keeps flickering now and unplugging the blue or orange wires turns it off entirely

        Here’s my code right now:

        #include “UnoJoy.h”
        #include

        #define PS2_DAT 11 //14
        #define PS2_CMD 9 //15
        #define PS2_SEL 8 //16
        #define PS2_CLK 10 //17

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

        PS2X ps2x;

        int error = 0;
        byte type = 1;
        byte vibrate = 0;

        void setup(){
        setupPins();
        setupUnoJoy();
        }

        void setupPins(void){
        // Set all the digital pins as inputs
        // with the pull-up enabled, except for the
        // two serial line pins
        for (int i = 2; i <= 12; i++){
        pinMode(i, INPUT);
        digitalWrite(i, HIGH);
        }
        pinMode(A4, INPUT);
        digitalWrite(A4, HIGH);
        pinMode(A5, INPUT);
        digitalWrite(A5, HIGH);
        }

        dataForController_t getControllerData(void){

        // Set up a place for our controller data
        // Use the getBlankDataForController() function, since
        // just declaring a fresh dataForController_t tends
        // to get you one filled with junk from other, random
        // values that were in those memory locations before
        dataForController_t controllerData = getBlankDataForController();
        // Since our buttons are all held high and
        // pulled low when pressed, we use the "!"
        // operator to invert the readings from the pins
        ps2x.read_gamepad(false, vibrate);
        controllerData.triangleOn = ps2x.Button(PSB_TRIANGLE);
        controllerData.circleOn = ps2x.Button(PSB_CIRCLE);
        controllerData.squareOn = ps2x.Button(PSB_SQUARE);
        controllerData.crossOn = ps2x.Button(PSB_CROSS);
        controllerData.dpadUpOn = ps2x.Button(PSB_PAD_UP);
        controllerData.dpadDownOn = ps2x.Button(PSB_PAD_DOWN);
        controllerData.dpadLeftOn = ps2x.Button(PSB_PAD_LEFT);
        controllerData.dpadRightOn = ps2x.Button(PSB_PAD_RIGHT);
        controllerData.l1On = ps2x.Button(PSB_L1);
        controllerData.r1On = ps2x.Button(PSB_R1);
        controllerData.selectOn = ps2x.Button(PSB_SELECT);
        controllerData.startOn = ps2x.Button(PSB_START);
        controllerData.l2On = ps2x.Button(PSB_L2);
        controllerData.l3On = ps2x.Button(PSB_L3);
        controllerData.r2On = ps2x.Button(PSB_R2);
        controllerData.r3On = ps2x.Button(PSB_R3);

        // Set the analog sticks
        // Since analogRead(pin) returns a 10 bit value,
        // we need to perform a bit shift operation to
        // lose the 2 least significant bits and get an
        // 8 bit number that we can use
        controllerData.leftStickX = ps2x.Analog(PSS_LX), DEC;
        controllerData.leftStickY = ps2x.Analog(PSS_LY), DEC;
        controllerData.rightStickX = ps2x.Analog(PSS_RX), DEC;
        controllerData.rightStickY = ps2x.Analog(PSS_RY), DEC;
        // And return the data!
        return controllerData;
        }

        void loop(){
        // Always be getting fresh data
        dataForController_t controllerData = getControllerData();
        setControllerData(controllerData);
        error = ps2x.config_gamepad(PS2_CLK, PS2_CMD, PS2_SEL, PS2_DAT, pressures, rumble);
        }

        Thanks for helping!

      • Kyle

        Also, if I try it with the code below, it says this in the serial monitor:

        “No controller found, check wiring, see readme.txt to enable debug. visit http://www.billporter.info for troubleshooting tips
        Unknown Controller type found ”

        ———————-CODE————————————

        #include //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 11 //14
        #define PS2_CMD 8 //15
        #define PS2_SEL 9 //16
        #define PS2_CLK 10 //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;

        void setup(){

        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 http://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 http://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 http://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 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
        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);
        }

        • I’ve just read part of the PS2X code and found that the error you are encountering is related to a pin (mode) which isn’t behaving as it should. Do you have a warning in the serial monitor like “Expected 0x41 or 0x73, got “? If so, what there is after? If the error message isn’t there I think you should enable debugging in the PS2X lib.

          P.S. restore all the wiring and the code to the “default”, otherwise I can’t help you!

        • Kyle

          Thanks for the response!

          I have everything at default right now and I’m not getting any errors in the serial monitor. Also, I already tried debugging, but that didn’t get me anywhere