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);
}
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);
}