PS2 controller on Axon.

Submitted by dunk on September 7, 2008 - 4:26pm.

Background reading.

This HowTo is based on my PSx controller firmware for the ATmega8 found here: http://mrdunk.googlepages.com/ps2controlleronanavr.

There are several useful pages on the Internet you will need to digest as well if you want to modify the firmware:

http://www.geocities.com/digitan000/Hardware/22/e22_page.html

http://www.gamesx.com/controldata/psxcont/psxcont.htm

http://www.curiousinventor.com/guides/ps2

http://www.webx.dk/robot-crawler/ps-joy.htm

In particular make sure you know what the Data, Command and Clock lines do on a PSx controller.

Also make sure you understand how a PSx controller packet is formed and know where to look up the various control codes that can be sent to and from it. (All this is explained in the links above.)

 

PS2 controller on AVR



What this HowTo does?

This allows you to read the PS2 controllers output registers over the serial port using any terminal emulation software such as Hyperterminal.

I'm sure people can think up loads of cool robotics related uses for this...

It would also be fairly easy to write a driver to interpret this as a Joystick with minimal modification of the firmware.

 

How to build this project.

This was my first time using the Axon, AVR Studio and all related tools. (I usually use GCC under Linux for AVR programming.)

I built and tested this project in a newly installed virtual machine running windows XP with all the recommended Axon software installed according to http://www.societyofrobots.com/axon/axon_getting_started_bootloader.shtml.

You will need an Axon, a genuine Sony PS2 controller and a bit of patience.

 

Hardware setup.

The included Axon firmware works with genuine Sony controllers but for some reason the timing is not right for my fake Chinese import controller.

My firmware for the ATmega8 http://mrdunk.googlepages.com/ps2controlleronanavr works fine with fake controllers at 8MHz. I presume the difference is the clock speed.

I have no doubt this firmware could be made work on the 16MHz Axon with fake controllers by anyone willing to spend more time debugging it than me.

If you want an easy time of it, use a genuine Sony controller.

The pinout of connecting the PS2 controller to the Axon is documented in the #defines section of the firmware.

In addition to these you need to know the +5V wire is red and 0V is grey black. As the controller needs 5Volts, use the regulated header pins for powering the PS2 controller.

I believe the black grey wire is power for the rumble vibration motors although I have had no need to experiment with those.

Other than the connectors to attach the PS2 controller to the Axon, no additional hardware is needed. 

 

PS2 to AVR

 

The firmware.

As I've already covered, the firmware below works on the SOR Axon with no additional hardware other than the required connectors.

There is no reason it will not run on any ATmega640 running at 16MHz.

The pin connections can be read in the #defines section.

Some of the formatting might be missing in the HTML below so you can also downloadit here: Axon.c.

 

/****************************************************************************
*
*   This file is based on the SOR Axon applicaation note
*   Copyright (c) 2008 www.societyofrobots.com
*
*   and my ATmega8 PS2 controller code.
*   http://mrdunk.googlepages.com/ps2controlleronanavr
*
*   This program is free software; you can redistribute it and/or modify
*   it under the terms of the GNU General Public License version 2 as
*   published by the Free Software Foundation.
*
*   Alternatively, this software may be distributed under the terms of BSD
*   license.
*
****************************************************************************/

//SoR Include
#include "SoR_Utils.h" //includes all the technical stuff
#include "hardware.c" //declare hardware variables and ports
//#include "CMUcam.c" //not yet written
#include "sensors.c" //not yet written, sensor libraries for sonar, sharp IR, etc.
//#include "Blackfin_Axon.c" //files for Blackfin Robot camera
#include "control.c" //your code goes in here
//#include "axon_test.c" //include this is doing a function test for the Axon
//#include "axon_oscope_test.c" //include this is doing a function test for the Axon
#include "Axon.h"


/****************AVR pin defines****************/
#define PSclock                3               // PA3    blue wire
#define PSdata                 4               // PA4    brown
#define PSacknowledge          5               // PA5    green
#define PScommand           6               // PA6    orange
#define PSattention         7               // PA7    yellow

int gameByte(short int );


int main(void)
    {
    //declare variables here
    int i=0;//useless variable
    int j=0;//useless variable


    /****************INITIALIZATIONS*******************/
    //other stuff Im experimenting with for SoR
    uartInit();  // initialize the UART (serial port)
    uartSetBaudRate(0, 38400); // set UARTE speed, for Bluetooth
    uartSetBaudRate(1, 115200); // set UARTD speed, for USB connection
    uartSetBaudRate(2, 38400); // set UARTH speed
    uartSetBaudRate(3, 38400); // set UARTJ speed, for Blackfin
    //G=Ground, T=Tx (connect to external Rx), R=Rx (connect to external Tx)

    rprintfInit(uart1SendByte);// initialize rprintf system and configure uart1 (USB) for rprintf

    timer0Init(); // initialize the timer system
    timer2Init(); // initialize the timer system
    
    configure_ports(); // configure which ports are analog, digital, etc.

    a2dInit(); // initialize analog to digital converter (ADC)
    a2dSetPrescaler(ADC_PRESCALE_DIV32); // configure ADC scaling
    a2dSetReference(ADC_REFERENCE_AVCC); // configure ADC reference voltage

    LED_on();

    rprintf(" System Warming Up");

    //let system stabelize for X time
    for(i=0;i<=16;i++)
        {
        delay_cycles(5000);
        rprintf(".");
        }

    delay_cycles(6000);

    //read each ADC once to get it working accurately
    for(i=0;i<16;i++)
        j=a2dConvert8bit(i);

    reset_timer_0();
    reset_timer_2();

    LED_off();

    
    rprintf("Axon initialization Complete. ");
    rprintf("Now initialising  PS2 controller.... ");


    // PSx controller I/O pin setup:
    sbi(DDRA, PSclock);                // clock. output. (blue)

    cbi(DDRA, PSdata);                 // data. input. (brown)
    sbi(PORTA, PSdata);                //    enable pullup resistor

    cbi(DDRA, PSacknowledge);            // acknowledge. input. (green)
    sbi(PORTA, PSacknowledge);           //    enable pullup resistor

    sbi(DDRA, PScommand);              // command. output. (orange)

    sbi(DDRA, PSattention);            // attention. output. (yellow)


    // enable interupts
    sei();

    // this loop continues to put PSx controller into analouge mode untill the
    // controller responds with 0x73 in the 2nd byte.
    // (PS2 controller responds with 0x73 when in analouge mode.)
    // the status LEDs will continue to count upwards untill a controller is found.
    // if everything is working correctly this should happen on the first pass of
    // this loop but occasionally errors occur and a 2nd or 3rd itteration happen.
    unsigned char chk_ana =1;
    unsigned int cnt=0;
    while(chk_ana != 0x73){
       // put controller in config mode
       sbi(PORTA, PScommand);
       sbi(PORTA, PSclock);
       cbi(PORTA, PSattention);

       gameByte(0x01);
       gameByte(0x43);
       gameByte(0x00);
       gameByte(0x01);
       gameByte(0x00);

       sbi(PORTA, PScommand);
       delay_us(1);
       sbi(PORTA, PSattention);

       delay_ms(1);

       // put controller in analouge mode
       sbi(PORTA, PScommand);
       sbi(PORTA, PSclock);
       cbi(PORTA, PSattention);

       gameByte(0x01);
       gameByte(0x44);
       gameByte(0x00);
       gameByte(0x01);
       gameByte(0x03);
       gameByte(0x00);
       gameByte(0x00);
       gameByte(0x00);
       gameByte(0x00);

       sbi(PORTA, PScommand);
       delay_us(1);
       sbi(PORTA, PSattention);

       delay_ms(1);

       // exit config mode
       sbi(PORTA, PScommand);
       sbi(PORTA, PSclock);
       cbi(PORTA, PSattention);

       gameByte(0x01);
       gameByte(0x43);
       gameByte(0x00);
       gameByte(0x00);
       gameByte(0x5A);
       gameByte(0x5A);
       gameByte(0x5A);
       gameByte(0x5A);
       gameByte(0x5A);

       sbi(PORTA, PScommand);
       delay_us(1);
       sbi(PORTA, PSattention);

       delay_ms(1);

       // poll controller and check in analouge mode.
       sbi(PORTA, PScommand);
       sbi(PORTA, PSclock);
       cbi(PORTA, PSattention);

       gameByte(0x01);
       chk_ana = gameByte(0x42);            // the 2nd byte to be returned from the controller should = 0x73 for "red" analouge controller.
       gameByte(0x00);
       gameByte(0x00);
       gameByte(0x00);
       gameByte(0x00);
       gameByte(0x00);
       gameByte(0x00);
       gameByte(0x00);

       sbi(PORTA, PScommand);
       delay_us(1);
       sbi(PORTA, PSattention);
       delay_ms(1);

       rprintf(" Pass number %d.  Controller returned 0x%x (expected 0x0073)", cnt++, chk_ana);
   }

   rprintf(" PS2 controller initialised.");

   delay_ms(100);

   short int temp, data0, data1, data2, data3, data4, data5;
  // main program loop:
  // ADD YOUR CODE TO THIS LOOP!
  // data from PS2 controller will be stored in data0, data1, data2, etc...
   while (1){

        sbi(PORTA, PScommand);                          // start communication with PSx controller
        sbi(PORTA, PSclock);
        cbi(PORTA, PSattention);

        gameByte(0x01);                                 // bite 0. header.
        temp = gameByte(0x42);                          // bite 1. header. (should possibly put test on this byte to detect unplugging of controller.)
        gameByte(0x00);                                 // bite 2. header.

        data0 = gameByte(0x00);                         // bite 3. first data bite.
        data1 = gameByte(0x00);                         // bite 4.
        data2 = gameByte(0x00);                         // bite 5.
        data3 = gameByte(0x00);                         // bite 6.
        data4 = gameByte(0x00);                         // bite 7.
        data5 = gameByte(0x00);                         // bite 8.

        sbi(PORTA, PScommand);                          // close communication with PSx controller
        delay_us(1);
        sbi(PORTA, PSattention);                        // all done.



        // display data from PS2 controller
        rprintf(" %x   %x   %x   %x   %x   %x", data0, data1, data2, data3, data4, data5);


        delay_ms(10);

        }


    return 0;
}

 

Future development.

So like i said, the firmware still needs some work on the timing before it works with fake (ie. non Sony) PS2 controllers.

If anyone gets it working with other controllers ley me know at mrdunk(at)gmail.com.

 

 

AttachmentSize
dscn0054.jpg819.79 KB
dscn0061.jpg820.56 KB
Axon.c8.69 KB
( categories: )

What kind of

What kind of peripherals/hacking is needed to make this wireless? maybe on a 2.4GHz level?

wireless.

well... you could either get a wireless controller or look into bluesmirf which i think operates on 2.4ghz...