XBox 360 Controller

Note: needs testing!

Overview

The XBox (wired and wireless) controller has 12 buttons, and two analog sticks with full 360 degree motion. This mode of interfacing is robust and easy to use. The hardware setup takes about three minutes. Button-mapping is simple, so setting up a simple control scheme for your robot with four wheels, a crane, and a grabbing mechanism is manageable.

Parts

-Arduino Nano and Nano carrier board

-LiPo battery

-4 motors

-USB XBox 360 Controller (available in lab via check-out)

-XBee pair with USB dongle

-Laptop

Setup

This setup uses the laptop as a host to the two entities: the XBee dongle and the USB controller. For your computer to translate the button presses and inputs from the controller, it requires a library and the program Processing. Downloads of both are available below. It should also be noted that this controller requires two sets of code. One for Arduino, and the other for Processing. Note: The Arduino sketch is substantially identical to the iPhone control sketch. The servo definitions for are slightly different, but the protocol for reading in the left and right servo signal is identical, with 0-127 controlling one and 128-255 controlling the other.

YOU NEED TO USE A USB CABLE TO UPLOAD YOUR PROGRAM – YOU CANNOT USE XBEE TO UPLOAD PROGRAMS TO THE BOARD. YOU ALSO NEED TO DISCONNECT THE XBEE FROM THE ARDUINO BOARD WHILE YOU UPLOAD.

Download Processing at http://processing.org/download/.The values from the XBox controller are sent to Processing. Processing also includes graphical tools. Processing is a simple way to create drawings, animations and interactive graphics. Visualization of data coming from an Arduino is fairly straightforward.

Code below tested with Processing 1.2.1.

The Processing sketch requires the proControll library, which must be placed "in your Processing sketchbook folder" which you can find by going to File -> Preference in processing.

Depending on how your computer is set up, you may have to tweak which COM port Processing uses to talk to the Arduino. You will need a XBee or a bluetooth dongle to plug into your laptop.

PC

Connection the XBox 360 wired controller to a PC. XBox Wired Controller Drivers for PC.

Connecting the XBox 360 wireless controller to PC. XBox Wireless Drivers for PC

Note: if you are unable to connect the controller to your PC, you need to manually find the drivers. Once you have the driver installed, go to the device manager and select the unknown device. You need to select "Microsoft Common Controller for Windows Class", as the driver type, and then select Xbox 360 Controller for Windows. Same goes for the wireless one.

Mac

How to connect an XBox 360 wireless/wired controller to a Mac.

Prepare the breadboard

Program the Microcontroller

//----------------------------start Arduino code--------------------------------
#include <Servo.h> // include servo headers
// using 4 motors to drive robot
#define SERVOFR 2
#define SERVOFL 3
#define SERVORR 4
#define SERVORL 5
// global variables
Servo servoFR;
Servo servoFL;
Servo servoRR;
Servo servoRL;
int message = 0; // This will hold one byte of the serial message
// played around with values that sets the servos to neutral position
// these values need to be set for each servo!!!
const int servoneutralLeft = 1515;
const int servoneutralRight = 1520;
// set neutral range for servos
const int minneutral = 1400;
const int maxneutral = 1600;
//--- Function: Setup ()
void setup()
{
    pinMode(SERVOFR, OUTPUT);
    pinMode(SERVOFL, OUTPUT);
    pinMode(SERVORR, OUTPUT);
    pinMode(SERVORL, OUTPUT);
    servoFR.attach(SERVOFR);
    servoFL.attach(SERVOFL);
    servoRR.attach(SERVORR);
    servoRL.attach(SERVORL);
    servoFR.writeMicroseconds(servoneutralLeft); // set servo to mid-point
    servoFL.writeMicroseconds(servoneutralRight); // set servo to mid-point
    servoRR.writeMicroseconds(servoneutralLeft); // set servo to mid-point
    servoRL.writeMicroseconds(servoneutralRight); // set servo to mid-point
    Serial.begin(9600); //set serial to 9600 baud rate
}
//--- Function: loop ()
void loop()
{
    // Check if there is a new message
    if (Serial.available() > 0)
    {
        message = Serial.read(); // Put the serial input into the message
        int val=message; // val to match pwm delay in ms
        int tempval=0; // temp storage
        // we can send values from 0 to 255 to the arduino.
        // both fadders are set up to go from 0 to 1.
        // left servo: 0-127, right servo 128-255. should be enough resolution
        int minpulse = 127*8/2; // max storage is 0-255.
        // Begin LEFT servo code
        if (val <= 127)
        {
            // scale everything from 1000 to 2000
            tempval = val*8 + servoneutralLeft - minpulse;
            if (tempval > minneutral && tempval < maxneutral)
            {
                // Creates dead zone at midpoint of the
                servoFL.writeMicroseconds(servoneutralLeft); // fader range (neutral) and trims input to neutral
                 servoRL.writeMicroseconds(servoneutralLeft); // fader range (neutral) and trims input to neutral 
             }
        else
        {
            servoFL.writeMicroseconds(tempval);
            servoRL.writeMicroseconds(tempval); 
        }
       } // End LEFT servo code
        // Begin RIGHT servo code
        if (val > 128)
        {
            // scale everything from 1000 to 2000
            tempval = val*8 + servoneutralRight - minpulse - 128*8;
            if (tempval > minneutral && tempval < maxneutral)
            {
                servoFR.writeMicroseconds(servoneutralRight);
                servoRR.writeMicroseconds(servoneutralRight); 
                // fader range (neutral) and trims input to neutral value
            }
        else
        {
            servoFR.writeMicroseconds(tempval);
            servoRR.writeMicroseconds(tempval); 
        }
       } // End RIGHT servo code 
    }
}
//----------------------------end Arduino code--------------------------------

Processing Sketch

//---------------------------start processing code------------------------------------
import procontroll.*;
import net.java.games.input.*;
import processing.serial.*; // Load serial library
Serial arduinoPort; // Set arduinoPort as serial connection
ControllIO controllIO;
ControllDevice joypad;
ControllStick stick1;
ControllStick stick2;
int val1 = 0; // Fader 1 value
int val2 = 0; // Fader 2 value
//--- Function: setup
void setup()
{
  arduinoPort = new Serial(this, Serial.list()[1], 9600); // Set arduinoPort to 9600 baud
  controllIO = ControllIO.getInstance(this);
  joypad = controllIO.getDevice("Wireless 360 Controller");
  stick1 = joypad.getStick(0);
  stick2 = joypad.getStick(1);
}
//--- Function: draws servo on/off
void draw()
{
  val1 = (int) (stick1.getY() * 63.5 + 63.5);
  val2 = (int) (-stick2.getY() * 63.5 + 191.5);
  arduinoPort.write(val1); // Sends val1 to Arduino, left servo
  arduinoPort.write(val2); // Sends val2 to Arduino, right servo
}
//---------------------------end processing code------------------------------------

Determine your Device

//---------------------------start processing code------------------------------------
import procontroll.*;
import java.io.*;
ControllIO controll;
void setup(){
  size(400,400);
  
  controll = ControllIO.getInstance(this);
  controll.printDevices();
  
  for(int i = 0; i < controll.getNumberOfDevices(); i++)
  {
    ControllDevice device = controll.getDevice(i);
    
    println(device.getName()+" has:");
    println(" " + device.getNumberOfSliders() + " sliders");
    println(" " + device.getNumberOfButtons() + " buttons");
    println(" " + device.getNumberOfSticks() + " sticks");
    
    device.printSliders();
    device.printButtons();
    device.printSticks();
  }
}
//---------------------------end processing code------------------------------------

Known Devices:

Wireless 360 Controller, Logitech Dual Action, Logitech RumblePad 2 USB, Twin USB Joystick, Logitech Force 3D Pro, Saitek ST290 Pro, Afterglow controller for PS3, 4-axis 8-button joystick, Twin USB Vibration Gamepad, etc...