Introduction: Car Controlled With PS3 Controller

This will show you how to take a remote controlled car and, with the use of the arduino, control it with a PS3 controller.

Things you need:
wires
soldering iron
arduino
usb shield for the arduino (this can be easily found on places like amazon.  basically it attaches to the arduino and gives the arduino a usb port)
rc car
PS3 controller

Step 1: Take Apart the Car

You need to take off the casing of the car to expose the wiring so that you can easily work with the motors and insert the arduino.  Pretty much there are a bunch of screws and stuff, so just take them off and you should be ready to go.

Step 2: Figure Out the Controller

you need to connect the ps3 controller to the computer with the usb cable to figure out inputs and such.  I used the program USB view for this.  You can download at the following link: http://www.ftdichip.com/Resources/Utilities/usbview.zip
Then open the program and select the ps3 controller

The results should be something like this:
Device Descriptor:
bcdUSB:             0x0200
bDeviceClass:       0x00
bDeviceSubClass:    0x00
bDeviceProtocol:    0x00
bMaxPacketSize0:    0x40 (64)
idVendor:           0x054C (Sony Corporation)
idProduct:          0x0268
bcdDevice:          0x0100
iManufacturer:      0x01
iProduct:           0x02
iSerialNumber:      0x00
bNumConfigurations: 0x01
ConnectionStatus:   DeviceConnected
Current Config Value: 0x01
Device Bus Speed:   Full
Device Address:     0x01
Open Pipes:         2
Endpoint Descriptor:
bEndpointAddress:   0x02
Transfer Type:      Interrupt
wMaxPacketSize:     0x0040 (64)
bInterval:          0x01
Endpoint Descriptor:
bEndpointAddress:   0x81
Transfer Type:      Interrupt
wMaxPacketSize:     0x0040 (64)
bInterval:          0x01

The important stuff is that the controller gives outputs on (0x02) and receives inputs on (0x81)

Step 3: Use the Usb Library

Fortunately, I was not the first one to connect a ps3 controller to the arduino, and so a very helpful library was available.  You should get it here: https://github.com/ribbotson/USB-Host/tree/master/ps3/PS3USB

Now you should download this to find out more about the controller: https://github.com/ribbotson/USB-Host/blob/master/examples/USB_desc.pde

With this code we find out all sorts of stuff about the arduino.  
See:

Start
freeMemory() reports 683
Device descriptor:
Descriptor Length:    12
Descriptor type:      01
USB version:          0200
Device class:         00
Device Subclass:      00
Device Protocol:      00
Max.packet size:      40
Vendor  ID:           054C
Product ID:           0268
Revision ID:          0100
Mfg.string index:     01
Prod.string index:    02
Serial number index:  00
Number of conf.:      01
Configuration descriptor:
Total length:         0029
Num.intf:             01
Conf.value:           01
Conf.string:          00
Attr.:                80
Max.pwr:              FA
Interface descriptor:
Intf.number:          00
Alt.:                 00
Endpoints:            02
Intf. Class:          03
Intf. Subclass:       00
Intf. Protocol:       00
Intf.string:          00
Unknown descriptor:
Length:               09
Type:                 21
Contents:             110100012294000705
Endpoint descriptor:
Endpoint address:     02
Attr.:                03
Max.pkt size:         0040
Polling interval:     01
Endpoint descriptor:
Endpoint address:     81
Attr.:                03
Max.pkt size:         0040
Polling interval:     01
memoryMin() reports 336

Now we need to get the library and the controller synced up.  to do that, we use the following code:
typedef struct {     

    byte epAddr;        //copy from endpoint descriptor without bit 7 if set

    byte Attr;          // Endpoint transfer type.

    unsigned int MaxPktSize;    // Maximum packet size.

    byte Interval;      // Polling interval in frames.

    byte sndToggle;     //last toggle value, bitmask for HCTL toggle bits

    byte rcvToggle;     //last toggle value, bitmask for HCTL toggle bits

} EP_RECORD;

and also this:
device_descriptor = (USB_DEVICE_DESCRIPTOR *) &buf;

    if(

    (device_descriptor->idVendor != PS3_VID) ||(device_descriptor->idProduct != PS3_PID)  ) {

        Serial.println("Unsupported USB Device");

          while(1);  //stop

Step 4: Now We Set the Controller to Give Input!

we want the controller to be able to give input at any time to the arduino, and so we use the following code:

#define PS3_F4_REPORT_LEN 4
#define HID_REPORT_FEATURE 3
#define PS3_F4_REPORT_ID  0xF4
prog_char feature_F4_report[] PROGMEM = {0x42, 0x0c, 0x00, 0x00};

  /* Set the PS3 controller to send reports */
    for (i=0; i<ps3_F4_REPORT_LEN; i++) buf[i] = pgm_read_byte_near( feature_F4_report + i);
    rcode = Usb.setReport( PS3_ADDR, ep_record[ CONTROL_PIPE ].epAddr, PS3_F4_REPORT_LEN,  PS3_IF, HID_REPORT_FEATURE, PS3_F4_REPORT_ID , buf );
    if( rcode ) {
        Serial.print("Set report error: ");
        Serial.println( rcode, HEX );
        while(1);  //stop
    }

If you're feeling like doing a little extra work just to be cool, you can also set the LED 1 on the ps3 controller on.  This looks more pro since when you connect the controller to a ps3, the LED turns on, but other than aesthetics, this doesn't do much.  (Note: you can also make the controller rumble with the arduino, pretty cool!) Here's the code for the LED:

#define PS3_01_REPORT_LEN 48
#define HID_REPORT_OUTPUT  2
#define PS3_01_REPORT_ID  0x01
prog_char output_01_report[] PROGMEM = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                                     0x00, 0x02, 0xff, 0x27, 0x10, 0x00, 0x32, 0xff,
                                     0x27, 0x10, 0x00, 0x32, 0xff, 0x27, 0x10, 0x00,
                                     0x32, 0xff, 0x27, 0x10, 0x00, 0x32, 0x00, 0x00,
                                     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                                     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};

   /* Set the PS3 controller LED 1 On */
    for (i=0; i<ps3_01_REPORT_LEN; i++) buf[i] = pgm_read_byte_near( output_01_report + i);
    rcode = Usb.setReport( PS3_ADDR, ep_record[ CONTROL_PIPE ].epAddr, PS3_01_REPORT_LEN,  PS3_IF, HID_REPORT_OUTPUT, PS3_01_REPORT_ID , buf );
    if( rcode ) {
        Serial.print("Set report error: ");
        Serial.println( rcode, HEX );
        while(1);  //stop
    }

More importantly, the arduino needs to process the signals from the controller.  Use this code:

void PS3_poll( void )

{
    byte rcode = 0;     //return code
    /* poll PS3 */
    rcode = Usb.inTransfer(PS3_ADDR, ep_record[ INPUT_PIPE ].epAddr, PS3_01_REPORT_LEN, buf );
    if( rcode != 0 ) {
       return;
    }
    process_report();
    return;
}

Step 5: Big Finale: Hooking Up the Arduino to the Car

So, every car is different.  In my project, I had a very simple car, with only four control option (forward, reverse, left, right) and each of these only allowed one value, ie there was only one allowed acceleration.  So create code accordingly.  I just used the directional buttons on the controller since I figured that would be simplest.  It is also possible to use the accelerometers for turning, the control sticks for going forward, etc.  Basically you can choose whatever control configuration you want.  I will explain how to do  this shortly.

But now, we need to hook up the arduino to the car.  My car had two motors.  One in back to go forward and backward, and one in front to turn the wheels.  You need to determine how these motors work.  If they are like mine, they will have two wires connected, and you'll want to remove those and solder wires from the outputs of the arduino onto them.  If your car is different, well hopefully it won't be too difficult to figure out.

Now that we have wired the arduino onto the car, we need to make code to tell the car what to do.  As I mentioned above, this will vary on both your preferences, and the individual car.  So now I will present a bunch of code that will be useful no matter what the situation is.  first off, we want methods to read the button inputs.  we can use the following:
#define buSelect 0
#define buLAnalog 1
#define buRAnalog 2
#define buStart 3
#define buUp 4
#define buRight 5
#define buDown 6
#define buLeft 7
#define buL2 8
#define buR2 9
#define buL1 10
#define buR1 11
#define buTriangle 12
#define buCircle 13
#define buCross 14
#define buSquare 15
#define buPS 16

These return true if the specified button is pressed.  So for mine I used buUp, buDown, etc.  
If you want to be fancier, and perhaps have a range of input values so you can have more than one force of acceleration, you can use the accelerometers.  These are their methods:

#define AccelerometerX 0
#define AccelerometerY 1
#define AccelerometerZ 2
#define GyrometerZ 3

The values for these go from 0 to 1023, with 512 being neutral

At any rate, once you do this, you just have to tell the arduino to give output at the desired output, and the car will go!
Hope you have enjoyed this little project.