Trying to use the PS2X library

Status
Not open for further replies.

Mr_Phelps

Member
I used a PS2 wireless game controller to run a small robot in a sensors class last term. It worked fairly well, but the controller was overkill on input/control of the bot.

However, the Teensy 3 with all those extra pins seems like it would be a great fit. I'm not building an R2D2 (yet) but there are tons of cool things possible. I'm starting by using the right analog joystick to control direction and speed of the bot.

First step was to port the sketch from the Uno into the Teensy 3 Arduino IDE.

When I did, I got these errors: (which is odd, because the library was plug and play for the Uno)
Am I doing something wrong?

G:\Project Stuff\Teensy_3\arduino-1.0.2-teensy3-beta9-windows\arduino-1.0.2\libraries\PS2X_lib\PS2X_lib.cpp: In member function 'unsigned char PS2X::_gamepad_shiftinout(char)':
G:\Project Stuff\Teensy_3\arduino-1.0.2-teensy3-beta9-windows\arduino-1.0.2\libraries\PS2X_lib\PS2X_lib.cpp:51: error: 'SREG' was not declared in this scope
G:\Project Stuff\Teensy_3\arduino-1.0.2-teensy3-beta9-windows\arduino-1.0.2\libraries\PS2X_lib\PS2X_lib.cpp: In member function 'void PS2X::read_gamepad(boolean, byte)':
G:\Project Stuff\Teensy_3\arduino-1.0.2-teensy3-beta9-windows\arduino-1.0.2\libraries\PS2X_lib\PS2X_lib.cpp:82: error: 'SREG' was not declared in this scope
G:\Project Stuff\Teensy_3\arduino-1.0.2-teensy3-beta9-windows\arduino-1.0.2\libraries\PS2X_lib\PS2X_lib.cpp: In member function 'byte PS2X::config_gamepad(uint8_t, uint8_t, uint8_t, uint8_t, bool, bool)':
G:\Project Stuff\Teensy_3\arduino-1.0.2-teensy3-beta9-windows\arduino-1.0.2\libraries\PS2X_lib\PS2X_lib.cpp:148: error: 'SREG' was not declared in this scope
G:\Project Stuff\Teensy_3\arduino-1.0.2-teensy3-beta9-windows\arduino-1.0.2\libraries\PS2X_lib\PS2X_lib.cpp: In member function 'void PS2X::sendCommandString(byte*, byte)':
G:\Project Stuff\Teensy_3\arduino-1.0.2-teensy3-beta9-windows\arduino-1.0.2\libraries\PS2X_lib\PS2X_lib.cpp:252: error: 'SREG' was not declared in this scope


Here is my sketch:
#include <PS2X_lib.h> //for ver 1.6

// Left motor driver I/O lines
const int lDir = 7;
const int PWML = 6;

// Right motor driver I/O lines
const int rDir = 4;
const int PWMR = 5;

// Create the values for the right joystick
int x_Axis = 0;
int y_Axis = 0;

// Create the float for the right joystick x axis
float x_Axis_scale = 0;

// Create PS2 controller class
PS2X ps2x;

/*
* You must have the controllers turned on when this program starts.
*/

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

// Full forward == 0, full reverse == 255
byte leftSpeed, rightSpeed;
byte leftDir = 0;
byte rightDir = 0;

void setup()
{
pinMode(lDir, OUTPUT);
pinMode(rDir, OUTPUT);
pinMode(PWML, OUTPUT);
pinMode(PWMR, OUTPUT);

analogWrite(PWML,0);
analogWrite(PWMR,0);

Serial.begin(57600);

// GamePad(clock, command, attention, data,Pressures?, Rumble?)
error = ps2x.config_gamepad(11,9,8,10, true, true);

if (error == 0){
Serial.println("Found Controller, configured Successful");
}
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");
break;
case 1:
Serial.println("DualShock Controller Found");
break;
case 2:
Serial.println("GuitarHero Controller Found");
break;
}

}

void loop()
{
/* You must Read Gampad to get new values
* You should call this at least once a second
*/

if(error == 1) // Skip loop if no controller found
return;

/* Read controller and set large motor to 'vibrate'. This will set the large motor vibrate speed
* based on how hard you press the blue (X) button.
*/

//ps2x.read_gamepad(false, vibrate); Not ready for this yet
//vibrate = ps2x.Analog(PSAB_BLUE);

// Get the right x-axis value and display it
x_Axis = ps2x.Analog(PSS_RX);
y_Axis = ps2x.Analog(PSS_RY);
Serial.print ("Right X axis ");
Serial.println(x_Axis);
Serial.print ("Right Y axis ");
Serial.println(y_Axis);

/*************************************************************************
***
*** My new section with just x-axis driving
***/

/* Get the right X axis and use it to set base speed and forward or reverse */

// Forward - Will generate values of 1 to 100 in speed
// Dir - 1 for forward, 0 for reverse
if (y_Axis < 101) {
rightSpeed = 100 - y_Axis;
leftSpeed = 100 - y_Axis;
rightDir = 1;
leftDir = 1;
}

// Neutral - Set speed and direction to 0
else if (y_Axis < 156) {
rightSpeed = 0;
leftSpeed = 0;
rightDir = 1;
leftDir = 1;
}

// Reverse - Will generate values of 1 to 100 in speed
else {
rightSpeed = y_Axis - 156;
leftSpeed = y_Axis - 156;
rightDir = 0;
leftDir = 0;
}

/* Get the right X axis use it to determine left, right or straight */

// Left turn
if (x_Axis < 100) {
// Make it 1 - 100 so it is easier to wrap my brain around
x_Axis = 100 - x_Axis;
// Turn it into a fraction for scaling the drive motors
x_Axis_scale = x_Axis/100;
// Forward
if (y_Axis < 101) {
leftSpeed = leftSpeed * x_Axis_scale;
}
// Reverse
else if (y_Axis > 155) {
rightSpeed = rightSpeed * x_Axis_scale;
}
// Stopped
else {
rightSpeed = 60;
leftSpeed = 60;
rightDir = 1;
leftDir = 0;
}
}

// Right turn
else if (x_Axis > 155) {
// Make it 1 - 100 so it is easier to wrap my brain around
x_Axis = 255 - x_Axis;
// Turn it into a fraction for scaling the drive motors
x_Axis_scale = x_Axis/100;
// Forward
if (y_Axis < 101) {
rightSpeed = rightSpeed * x_Axis_scale;
}
// Reverse
else if (y_Axis > 155) {
leftSpeed = leftSpeed * x_Axis_scale;
}
// Stopped
else {
rightSpeed = 60;
leftSpeed = 60;
rightDir = 0;
leftDir = 1;
}
}

// Now set the Left driver direction lines and PWM
digitalWrite(lDir, leftDir);
//constrain (leftSpeed,0,125);
Serial.print ("Left speed ");
Serial.print(leftSpeed);
Serial.print(" :: leftDir = ");
Serial.println(leftDir);
analogWrite(PWML, leftSpeed);

// Set Right motor driver directions and PWM
digitalWrite(rDir, rightDir);
Serial.print ("Right speed ");
Serial.print(rightSpeed);
Serial.print(" :: rightDir = ");
Serial.println(rightDir);
analogWrite(PWMR, rightSpeed);

// Some debug output
Serial.print (leftSpeed, DEC);
Serial.println (rightSpeed, DEC);

delay (50);
}
 
Is this library likely to be ported? I'm just starting into Arduino/Teensy coding and need to know if I should just drop back to the Uno.
 
Sorry about the long delay. I finally looked at this.

Here's an updated avr emulation to support this library.

http://www.pjrc.com/teensy/beta/avr_emulation.h

This file goes into hardware/teensy/cores/teensy3, to replace the existing copy. It allows the PS2X library to compile. Of course, I can't actually test since I don't have the hardware. Please let me know if this makes it work?
 
Last edited:
I'll work on trying it tomorrow. Been slammed at work and going back to school. But will be fun to use this for a little tank bot running into the prof's office firing ping pongs. :)
 
Still no luck.

I switched the board to Uno and to Teensy 2.0++ and both compile. But when I switch to the Teensy 3.0 it still crashes with the same error.

I'll try it on the laptop at work this week and if it still doesn't compile I'll see about bringing the laptop to the next Dorkbot meeting.
 
Digging around a bit more and I'm starting to think I should chase just doing an SPI implimentation. New at this, so that is probably going to be something of an adventure. I really want the flexibility of the controller for the little robot I'm working on.

I found a suggestion on this site: http://forums.leaflabs.com/topic.php?id=2428

Why they're bit banging SPI, I'm not sure, but you can quickly implement the PS2X controller using SPI. Looks like it's mode 1 (clock line idles high) and the adapter needs to be connected like so:

Attention to NSS
Command to MOSI
Data to MISO
Clock to SCK

I'm guessing this is where you got the library?
http://www.billporter.info/playstation-2-controller-arduino-library-v1-0/

The functions you'll need to translate to use SPI are
boolean Button(uint16_t);
unsigned int ButtonDataByte();
boolean NewButtonState();
boolean NewButtonState(unsigned int);
boolean ButtonPressed(unsigned int);
boolean ButtonReleased(unsigned int);
void read_gamepad();
void read_gamepad(boolean, byte);
byte config_gamepad(uint8_t, uint8_t, uint8_t, uint8_t);
void enableRumble();
void enablePressures();
byte Analog(byte);

But should require minimal work.

You can look at the SPI documentation here:
http://leaflabs.com/docs/spi.html

I'll dig a bit more when I get a chance.
 
I switched the board to Uno and to Teensy 2.0++ and both compile. But when I switch to the Teensy 3.0 it still crashes with the same error.

You've installed Beta12, right? Please double check.

I just compiled the program from the first message in this thread, without any error. Here's a screenshot:

ps2x_screenshot.png
 
Huzzah, got it to compile! Thanks for your help!

Profs shall fear the wrath of *Ping-bot*! :)

Though just software so far and a moving platform. Once the 3d printer is up and running I'll be printing the treads for the rebuild as a tank. I'll work on posting code as I develop it.

See ya at Dorkbot.
 
Hi. I have the most recent teensy instalation and I'm trying to use the ps2x library with the teensy 3

getting the errors below.

this is from the most recent version of the library downloaded from github. The version directly linked in http://www.billporter.info/2010/06/05/playstation-2-controller-arduino-library-v1-0/ as the download link compiles but I get zero serial activity when running the example sketch.

This report would have more information with
"Show verbose output during compilation"
enabled in File > Preferences.
Arduino: 1.0.5 (Windows NT (unknown)), Board: "Teensy 3.0"
C:\Users\jake\Documents\Arduino\libraries\PS2X_lib\PS2X_lib.cpp: In member function 'byte PS2X::config_gamepad(uint8_t, uint8_t, uint8_t, uint8_t, bool, bool)':
C:\Users\jake\Documents\Arduino\libraries\PS2X_lib\PS2X_lib.cpp:184:47: error: cannot convert 'volatile uint8_t* {aka volatile unsigned char*}' to 'volatile uint32_t* {aka volatile long unsigned int*}' in assignment
C:\Users\jake\Documents\Arduino\libraries\PS2X_lib\PS2X_lib.cpp:185:47: error: cannot convert 'volatile uint8_t* {aka volatile unsigned char*}' to 'volatile uint32_t* {aka volatile long unsigned int*}' in assignment
C:\Users\jake\Documents\Arduino\libraries\PS2X_lib\PS2X_lib.cpp:189:47: error: cannot convert 'volatile uint8_t* {aka volatile unsigned char*}' to 'volatile uint32_t* {aka volatile long unsigned int*}' in assignment
C:\Users\jake\Documents\Arduino\libraries\PS2X_lib\PS2X_lib.cpp:190:47: error: cannot convert 'volatile uint8_t* {aka volatile unsigned char*}' to 'volatile uint32_t* {aka volatile long unsigned int*}' in assignment
C:\Users\jake\Documents\Arduino\libraries\PS2X_lib\PS2X_lib.cpp:194:47: error: cannot convert 'volatile uint8_t* {aka volatile unsigned char*}' to 'volatile uint32_t* {aka volatile long unsigned int*}' in assignment
C:\Users\jake\Documents\Arduino\libraries\PS2X_lib\PS2X_lib.cpp:195:47: error: cannot convert 'volatile uint8_t* {aka volatile unsigned char*}' to 'volatile uint32_t* {aka volatile long unsigned int*}' in assignment
C:\Users\jake\Documents\Arduino\libraries\PS2X_lib\PS2X_lib.cpp:198:15: error: cannot convert 'volatile uint8_t* {aka volatile unsigned char*}' to 'volatile uint32_t* {aka volatile long unsigned int*}' in assignment
C:\Users\jake\Documents\Arduino\libraries\PS2X_lib\PS2X_lib.cpp: At global scope:
C:\Users\jake\Documents\Arduino\libraries\PS2X_lib\PS2X_lib.cpp:447:18: error: expected constructor, destructor, or type conversion before '|=' token
C:\Users\jake\Documents\Arduino\libraries\PS2X_lib\PS2X_lib.cpp:448:1: error: expected declaration before '}' token


any help would be great!

Thanks,
Jake
 
Here is the PS2X lib I updated for Arduino 1.03. It should work for teensy.
I removed a lot of stuff I didn't want, such as the GuitarHero buttons.
You will probably need to change the pins, but I think it will work
https://github.com/btmcmahan/PS2X.git

Awesome thanks! I'll check it out later today. I've been testing with a teensy 2.0 for now but if I could get this to work with a teensy 3 that would definitely be great.

Thanks,
Jake
 
Did you get this working? Mine is compiling but not working.
I think I'm gonna take a step back, and rewrite part of the library to use the SPI stuff that is already pretty solid.
I think it will clean things up some, but it's gonna take me until next week probably, unless someone else tackles it first.
 
Last edited:
You need the female part of a ps2 controller. very cheap on ebay.
PS2 Controller Adapter
ps2_Adapter_zpsda13c4a5.jpg
crack the shell open to get to the pins.

*Keep in mind that this pinout is opposite, because it is a picture of the male end.
And you don't have to use the pin 9 acknowledge...just
+3.3, Com, Clock, Command, Data, and Attention is all you "need".
ps2wiring_zps7ce7715c.jpg
 
Last edited:
So, I've been trying to figure this out for a couple of weeks now. I've been using the SPI Library that I made up, and I'm (fairly) confident that my SPI lib works fine. I've been sending the basic polling data to the PS2 controller, but I'm not getting back the data I expected.
Here's the polling string, for when the controller isn't in analog mode:
0x01, 0x42, 0x00, 0x00, 0x00

The controller returns data at the same time it is receiving it (full duplex).

This is what I SHOULD be receiving
Send - Receive
0x01 - 0xFF
0x42 - 0x73
0x00 - 0x5A
0x00 - 0xFE
0x00 - 0xFF

This is what I am actually getting
Send - Receive
0x01 - 0x01
0x42 - 0x42
0x00 - 0x00
0x00 - 0x00
0x00 - 0x00

As you can see, I'm getting back the same data I'm sending out. I've tried several different things, including a logic level converter since arduino opperates at 5v and Teensy3.0 is at 3.3v. I've also started asigning a different chip-select pin, so that I can leave the CS low for all 5 bytes to be sent, then raise it high again. Nothing seems to get me the return data I'm looking for.

Anyone have any ideas? I feel like I'm missing something simple here. Basically, I'm stumped & frustrated.

Here is a very basic version of my logic.

Code:
#include <t3spi.h>
#include "mk20dx128.h"
T3SPI SPI_MASTER;

void setup(){
  
  Serial.begin(115200);
  
  //This is my CS pin, to controller's ATTENTION
  pinMode(16, OUTPUT);
  digitalWrite(16, HIGH);
  
  //Clock=13, MOSI=11, MISO=12, CS=9
  SPI_MASTER.begin_MASTER(SCK, MOSI, MISO, CS1, CS_ActiveLOW);
  
  //Clock @ 375Khz & 50% duty
  SPI_MASTER.setCTAR(CTAR0,8,SPI_MODE3,LSB_FIRST,SPI_CLOCK_DIV128);

  delay(3000);
}

void loop(){
    poll();
    delay(2000);
}

void poll(){
  volatile  uint8_t data[1] = {0};
  digitalWrite(16, LOW);
  delayMicroseconds(2);
 
  data[0]=0x01;
  SPI_MASTER.tx8(data, 1, CTAR0, CS1);  //Send 0x01
  Serial.println(SPI0_POPR,HEX);        //See what comes back
  
  data[0]=0x42;
  SPI_MASTER.tx8(data, 1, CTAR0, CS1);  //Send 0x42
  Serial.println(SPI0_POPR,HEX);        //See what comes back
  
  data[0]=0x00;
  SPI_MASTER.tx8(data, 1, CTAR0, CS1);  //Send 0x00
  Serial.println(SPI0_POPR,HEX);        //See what comes back
  
  data[0]=0x00;
  SPI_MASTER.tx8(data, 1, CTAR0, CS1);  //Send 0x00
  Serial.println(SPI0_POPR,HEX);        //See what comes back
  
  data[0]=0x00;
  SPI_MASTER.tx8(data, 1, CTAR0, CS1);  //Send 0x00
  Serial.println(SPI0_POPR, HEX);        //See what comes back
  
  delayMicroseconds(2);
  Serial.println();
  digitalWrite(16, LOW);
}
 
Last edited:
For me also the PSX2 library does not work, it compiles fine with Arduino 1.05 and Teensy 1.16, however I could not communicate with the controller.

However I found a code from David Wegmuller that works! Here is a quick adaptation which shows in serial that all buttons and joysticks are responding (I haven't hooked the motors). Still I have to understand the SPI calls that are made, the initialisation part , and would like to transform the code to use SPI.h

View attachment PSX_01.zip

I also found the "CuriousInventor" blog which explains in great detail the protocol.

The wiring is not straightforward, I had to used 120 Ohms resistors for each pin (as explained by Paul in another thread), and the data line needs a pull-up of maximum 3.3K Ohms. Else the data is not accurate and very noisy.

photo (1).JPG
 
OKay, I think I got this working. I'm out of town until next week, but I'll try to work up the logic and post a solution.
 
I've got my PS2 Controller working, using my Teensy 3.0 SPI library. I'm gonna start working on a basic library now. I think it is a lot cleaner method than the original PS2X lib, because it uses straight SPI. I'll post again when I have something more.
 
Status
Not open for further replies.
Back
Top