Arduino Playstation 2 Controller Library Troubleshooting Guide

Posted in Arduino Libraries by Bill
27 Mar 2011
Arduino Playstation 2 Controller Library Troubleshooting Guide

Ok, if you are here, you are having trouble getting your Arduino talking to your PlayStation 2 Controller via my Handy Dandy PS2X Library. Well, never fear, I stand by my leet coding abilities (Ha! who am I kidding? Really though, the library works, there’s tons of examples using it.) and I’m here to help. The problem is there’s not much I can really do unless you live near North Florida and want to come pay me a visit. It’s hard giving help over the internet! But maybe I can guide you in the right direction with this troubleshooting guide.

I’ll walk you through some debugging steps, and you should follow through with me with DEBUG off until I tell you to enable it and using the example sketch unmodified. In-between attempts, power off the Arduino and controller for 10 seconds before testing it again.  I’ll bold the quick steps if you want to skim through.

A little background first. I have not personally reverse engineered the communications protocol a PS2 controller uses. That has been done by a few other cool guys like this one.  I used what they reported in writing the PS2X library. As far as I know Sony has never official published the communications protocol to the public, so reverse engineering efforts is all we have to go on. This has lead to a few problems; for example some controllers just don’t behave like others. From the various sources around the web, the best chance of success comes from using ‘Official’ Sony controllers, and not the cheap knock-offs, 3rd  party controllers. There’s also some links with wireless controllers not working well either. Personally I have tried a wired Sony controller, and a few wireless Guitar Hero Controllers all with success, powered at 5V and no resistors.

Therefore the first thing to consider is what controller are you using? Can you try another brand, model?

Ok, now that we are past history of controllers, I’ll tell you this: 90% of the problems people have end up being related to wiring. I can’t look at your setup, so you are going to have to use your best judgment. Does the wiring look sound? Controller wires are thin and small and tend to break easily. During prototyping, I cut the ends off my wired controllers, stripped 1/4″ insulation off and heavily tinned the wires to create solid ‘pins’ that could be pushed into the female pinheader on the Arduino. This method worked, but was fragile. Later on I bought a few $5 PS2 controller extension cables and cut off the female receptacle end. I soldered the wires from the plug to PCB board and that worked well also.

 

Don’t trust the color scheme on the wiring picture. It can vary! Instead, use a voltmeter and test continuity between pin positions in the connector and the bare wires. I’ve had a few people report odd color schemes, and a few not realize what end of the connector they were looking at and got the wiring completely backwards. A quick check is to power up the controller, and pushing the ‘Analog’ button. Either the LED should have been on when it powered up, or it should light up when you press the button. If not, the controller isn’t getting power and you probably have the wiring reversed.

Alright, so you trust the wiring job, what next?

There are discussions over whether or not the controllers are tolerant of 5V logic. I’ve never had one burn out, so I believe they can handle “receiving’ 5V, but they still won’t ‘send’ 5V to the Arduino. It seems to me the one fix that seems to work the most is adding a 10k resistor between DATA (brown wire, or pin 1 on the controller port) and VCC (try both 3.3V and 5V in that order) on the Arduino.

This will help ‘pull-up’ the data line. Also there’s disagreement on what voltage to use to power the controller. A PlayStation powers the controller at 3.4V. I have always powered my controllers at 5V and had no problems, but it is risky. Controllers are so cheap on ebay though, why not try it? Try different voltages for power, switch between 3.3V and 5V, and for each voltage try it with and without the pull-up resistor on the DATA line .

One person claimed his controller wouldn’t work without level shifting all his wires, which means he just added resistors inbetween the controller’s pins and the Arduino.

The numbers he reported success with is as follow:

  1. 5V = 180 ohm, voltage drop of 1.85V (3.15v to the controller)
  2. ATT = 5.6K ohm, voltage drop of 1.08V (3.92 to the controller)
  3. CLK = 5.6K ohm, voltage drop of 1.15V (3.85 to the controller)
  4. CMD = 860K ohm, voltage drop of 1.39V (3.61 to the controller)

so you can give that a try as well. Though really, ignore the resistor on 5V and just connect the red power wire to 3.3V.

Some people report issues using pin 13 on the Arduino for CLK. Try moving the CLK line to another pin, and editing the example sketch to match.

If you have gotten this far and still no luck, you might just be out of luck. Controllers can go bad and some people just aren’t any good at wiring. But, there’s one more thing we can try messing with.

There’s a value in the ‘PS2X_lib.h’ file that governs the speed of the bus to the controller. It’s called ‘CTRL_CLK’ and you can find it by looking for this line:

#define CTRL_CLK        4

The PlayStation 2 talks to its controllers at 500kHz, or a value of ‘2’ in my library. Arduino tends to have issues setting a value that low, so by default I have it set at 4. You can try using 2 instead, and I’d also try using some higher number for a slower bus speed. Go from 2-20 and even 200 to see if you can get the controller talking. Remember to save the .h file every time you edit it, and re-compile the sketch.

Still no luck? Man you are killing me. I’ve dropped all my suggestions into this guide, so there’s not much else I can say even if you ask really nicely. Florida is nice year round, so feel free to come visit me and I will help you in person. Otherwise, you can try to enable debug. It won’t really help diagnosing wiring problems (or bad controllers) because all you will see is all FF’s or 0’s. But if you are getting some values, they may be something else going on. Drop the output in the Support Forum and I’ll see if I can help.

My last fleeting thoughts include removing the checks in the example. At the end of the setup function (after the switch statement and before the closing curly bracket ‘}’ ), add the following code:

error = 0;

type = 1;

This will bypass the error checking and run the code anyway. What do you get? Try pressing reset on the Arduino without disconnecting the controller. Anything?

Still need help?

Use the Support Forum to ask for help. Please don’t use the comments below.

Share
  1. 180 Comments.

    • Kurt EckhardtNo Gravatar says:

      Yes there is problems between these two libraries. All you need to do is to use the two libraries, set one servo lets say to 90 degrees and then start calling the Read_gamepad function.

      I am already in the process of debugging it and know the problem has to do with the functions/Macros Set/CLR which are not atomic. Example: with the Set the code, will do something like:
      Fetch current value
      Or in the new value
      Put the value back out.

      The problem is suppose the servo interrupt happens after the fetch and this function sets a new value for the servo and returns. Your code will then do the or and store the value back out (for the 8 IO pins) and tromp on what the Servo interrupt did.

      Hope that makes sense. I do have logic analyzer output showing it being tromped.

      Kurt

    • Kurt EckhardtNo Gravatar says:

      Follow on to previous post. If I change the two functions (Read_gamepad and the shiftinout…) to disable/enable interrupts, the test programs servo output looks much much better. All changes marked with *** KJE ***

      unsigned char PS2X::_gamepad_shiftinout (char byte) {
      uint8_t old_sreg = SREG; // *** KJE *** save away the current state of interrupts

      unsigned char tmp = 0;
      cli(); // *** KJE *** disable for now
      for(i=0;i 1500) //waited to long
      reconfig_gamepad();

      if(temp < read_delay) //waited too short
      delay(read_delay – temp);

      last_buttons = buttons; //store the previous buttons states

      if(motor2 != 0x00)
      motor2 = map(motor2,0,255,0×40,0xFF); //noting below 40 will make it spin

      cli(); //*** KJE ***
      SET(*_cmd_oreg,_cmd_mask);
      SET(*_clk_oreg,_clk_mask);
      CLR(*_att_oreg,_att_mask); // low enable joystick
      SREG = old_sreg; // *** KJE *** – Interrupts may be enabled again

      delayMicroseconds(CTRL_BYTE_DELAY);
      //Send the command to send button and joystick data;
      char dword[9] = {0x01,0x42,0,motor1,motor2,0,0,0,0};
      byte dword2[12] = {0,0,0,0,0,0,0,0,0,0,0,0};

      for (int i = 0; i<9; i++) {
      PS2data[i] = _gamepad_shiftinout(dword[i]);
      }
      if(PS2data[1] == 0x79) { //if controller is in full data return mode, get the rest of data
      for (int i = 0; i<12; i++) {
      PS2data[i+9] = _gamepad_shiftinout(dword2[i]);
      }
      }

      cli();
      SET(*_att_oreg,_att_mask); // HI disable joystick
      SREG = old_sreg; // Interrupts may be enabled again

      #ifdef PS2X_COM_DEBUG
      Serial.println("OUT:IN");
      for(int i=0; i<9; i++){
      Serial.print(dword[i], HEX);
      Serial.print(":");
      Serial.print(PS2data[i], HEX);
      Serial.print(" ");
      }
      for (int i = 0; i<12; i++) {
      Serial.print(dword2[i], HEX);
      Serial.print(":");
      Serial.print(PS2data[i+9], HEX);
      Serial.print(" ");
      }
      Serial.println("");
      #endif

      buttons = *(uint16_t*)(PS2data+3); //store as one value for multiple functions
      last_read = millis();
      }

      byte PS2X::config_gamepad(uint8_t clk, uint8_t cmd, uint8_t att, uint8_t dat) {
      return config_gamepad(clk, cmd, att, dat, false, false);
      }

    • JDCNo Gravatar says:

      Thanks! The pull-up resistor on the DATA wire got it working for me. I was worried because my PS2 controller had crappy wires so I’m glad I actually managed to set that up correctly.

    • BillNo Gravatar says:

      I rolled Kurt’s changes into a new version, should help with servo jitter.

      I guess I should look into proper repositories if I keep getting help with code like this. Thanks Kurt!

    • Bill MNo Gravatar says:

      Hi bill
      Great effort and library.
      I have a new “EtherTen” and new “Sony PS2 wired controller SCPH-10010/97026”
      After much time with no success, I changed the I/O pins to 7,5,4,6, and had an immediate success with resistors from 1k to 5k on DATA only, “2.2k is best for me” DATA3.3v or 5v about 99% of the time when I plug it into the arduino or reset it.
      I have sixteen button functions that seemed to work right. My issue is the analog light comes on at startup and the button does not turn it off? I can’t figure out how to get the joysticks to respond, other than the joystick buttons. Any thoughts will be greatly appreciated.

      • BillNo Gravatar says:

        The light should be coming on, and shouldn’t be able to be turned off. That is proper operation, as my library locks the controller in that mode.

        But the joysticks don’t work? Can you enable both levels of debug and email me the first few seconds of what comes out of the serial window? Email address at the bottom of the page.

    • ValerioNo Gravatar says:

      Hello Bill!
      Your project is really fantastic, I tried it and it works very well!!
      congratulations! 🙂
      I wanted to ask your help to turn the project into a real joystick DUALSHOCK for computer games. is it possible? how?
      ps. I have Arduino 2009.

      thank you!

      • BillNo Gravatar says:

        Yes it’s possible but I have never done it nor how to do it in detail. You would have to have the Ardunio setup to look like a HID device to the computer. The newer Arduinos without the FTDI chips can do this I believe. Then you would have write the sketch so that it read the controller and sent the data to the computer like an HID.

      • ftoramaNo Gravatar says:

        Hi…

        just did it yesterday with a Teensy++ 2.0 (and this fantastic lib).

        Actually, I had to change the CTRL_CLK to get it to work. When I slowed down the Teensy, it appeared to work too…

        The only problem I meet is that I can’t calibrate both sliders (mapped to L1 and R1 buttons). Certainly a driver problem….

        • BillNo Gravatar says:

          What do you mean by calibrate? The PS2 Gamepad analog sticks have a history of bad centering and random drift. To reall make use of the data, you have to add a dead band in the middle at least.

          • ftoramaNo Gravatar says:

            well, I must be really lucky…I tried with two different third-party controllers and both worked perfectly… One is the wireless remote from Lynxmotion. I don’t remind for the second one, but I’ll check if you’re interested…

            Anyway, the dead-band handling can be done in the Teensy to provide a fully operational controller.

    • ValerioNo Gravatar says:

      ok! Thanks for Everything! Goodbye!!!!

    • JeromeNo Gravatar says:

      What are the pin outs to connect to motors and such. I’ve checked all available pins, none have voltage coming out. Do I need to do something to the code, I can’t finding anything online!

      PS2 controller is detected and sending all the right commande.

      • BillNo Gravatar says:

        Jerome, are you asking how you then connect the Arduino to motors to be controlled by the PS2 controller?

        My library only lets you read the controller. It’s up to you to write code to use that information to do things using other libraries and things like servos.

    • Kurt EckhardtNo Gravatar says:

      I am pretty sure that Bill mentions this site as well. But for questions like this, I always go up to: http://store.curiousinventor.com/guides/ps2

      Kurt

    • mark langfildNo Gravatar says:

      i have a problem when i connect the ps2 controller, the debug output is as following:
      OUT:IN
      1:FF 42:FF 0:FF 0:FF 0:FF 0:FF 0:FF 0:FF 0:FF 0:0 0:0 0:0 0:0 0:0 0:0 0:0 0:0 0:0 0:0 0:0 0:0
      OUT:IN
      1:FF 42:1 0:10 0:FE 0:FF 0:FF 0:FF 0:FF 0:FF 0:0 0:0 0:0 0:0 0:0 0:0 0:0 0:0 0:0 0:0 0:0 0:0
      Controller mode not matched or no controller found
      Expected 0x41 or 0x73, got 1
      No controller found, check wiring, see readme.txt to enable debug. visit http://www.billporter.info for troubleshooting tips
      OUT:IN Configure
      1:FF 43:1 0:10 1:FE 0:FF
      OUT:IN Configure
      1:FF 43:FF 0:FF 0:FF 5A:FF 5A:FF 5A:FF 5A:FF 5A:FF
      Unknown Controller type
      OUT:IN Configure
      1:FF 43:E3 0:10 1:0 0:0
      OUT:IN Configure
      1:FF 4D:E3 0:10 0:0 1:0
      OUT:IN Configure
      1:FF 43:E3 0:10 0:0 5A:0 5A:0 5A:0 5A:0 5A:0
      OUT:IN Configure
      1:FF 43:1 0:10 1:FE 0:FF
      OUT:IN Configure
      1:FF 4F:E3 0:10 FF:0 FF:0 3:0 0:0 0:0 0:0
      OUT:IN Configure
      1:FF 43:E3 0:10 0:0 5A:0 5A:0 5A:0 5A:0 5A:0
      OUT:IN
      1:FF 42:1 0:10 0:FE 0:FF 0:FF 0:FF 0:FF 0:FF 0:0 0:0 0:0 0:0 0:0 0:0 0:0 0:0 0:0 0:0 0:0 0:0
      OUT:IN
      1:FF 42:1 0:10 0:FE 0:FF 0:FF 0:FF 0:FF 0:FF 0:0 0:0 0:0 0:0 0:0 0:0 0:0 0:0 0:0 0:0 0:0 0:0
      Controller refusing Pressures mode, may not support it.

      please solve my problem.

    • KurtENo Gravatar says:

      Hi Bill,

      Recently I thought I would try one of the ChipKit UNO32 boards which is based on Pic32 and maybe try porting one of my Robots to run on it. Since most of my robots that run on Arduinos use your library I ported your code over. For the most part the only thing that needed to change was bit set/clear/test functions/macros. Also the code would fault, when the line “buttons = *(uint16_t*)(PS2data+3);” was run. I believe it was probably some form of alignment fault as the processor is 32 bits… I was able to fix by simply:”buttons = (uint16_t)(PS2data[4] << 8) + PS2data[3];".

      Question is: should I post a version of this that works up on their forum(http://www.chipkit.org/forum), to allow others to play with it? and/or would you prefer that I email the changes to you such that maybe you can incorporate them in the main source base?

      Thanks again
      Kurt

      • BillNo Gravatar says:

        Hey Kurt,

        I don’t mind whatever you do with it. I moved all my code to GitHub, with little experience using GitHub, but I did it to allow other people like you add features and bugfixes (Or formatting if you really want 🙂 without my major involvement.

        If you want to post it somewhere else, that’s fine, and let me know about it so I can link to it as well. Or you could add it to my source base as a push request on github. Up to you.

    • TrulsNo Gravatar says:

      Thanks for a great library. Couldn’t get it working at first, but after setting a 10k pull up on the data channel it started working flawlessly.

      Thanks to your library I just got my playstation controllers working on my C64!

    • squarismNo Gravatar says:

      Thank you so much for the library and the troubleshooting guide. I followed each step and eventually got it with a combination of the pin13 and 10k trick. Fairly sure that it was pin 13 all along. But just wanted to say thank you for the quality of this guide. It’s extremely helpful for a ‘software’ person such as myself.

    • RewkNo Gravatar says:

      It worked fine for me, and helped me building my own lib using hardware SPI.
      Anyways, 10K resistor pull seems to much when working at 250kHz. It seems that the controller was to slow to set the value to HIGH when responding with 10K. I was thus systematically missing the first bit set to 1 of any bits sequence. It took me a while to figure out why hardware SPI did not work. 🙂
      I used a 1K resistor, and it went fine. I guess i should narrow the required value.

    • PollyNo Gravatar says:

      I have a Logitech wireless controller that won’t stay in analog mode when using the builtin servo.h library. The mode light on the controller will stay on for a cycle and turn off. The wireless controller works fine with the PS2X example. An official PS2 wired controller also works with the servo library.

      I am wiring the wireless transmitter/receiver to 3.3V with a 10K resistor on DATA.

      Here is my example code:

      #include
      #include

      //servo
      Servo myservo; // create servo object to control a servo
      int pos = 90; // variable to store the servo position

      // PS2 controller
      PS2X ps2x; // create PS2 Controller Class
      int error = 0;

      void setup()
      {
      Serial.begin(57600);
      myservo.attach(9); // attaches the servo on pin 9 to the servo object
      error = ps2x.config_gamepad(4,5,6,3, true, false); //setup pins and settings: GamePad(clock, command, attention, data, Pressures?, Rumble?) check for error
      }

      void loop()
      {
      Serial.println(pos);
      myservo.write(pos);
      delay(15);
      ps2x.read_gamepad(false,vibrate);
      pos = map(ps2x.Analog(PSS_LX),0,255,0,180);
      }

Leave a Reply