Hello,
I have very successfully controlled my robot with an official PS2 controller, but when I connect a wireless controller, it doesn’t work. My setup is as follows:
Microcontroller: OX2 by pololu (with ATmega644)
Wired controller: Official Sony PS2 controller
Wireless controller: Official PS2 controller (licensed by Sony to Katana) and Logitec PS2 controller
I can’t figure out why the wired controller would work by the wireless one will not. Any help would be greatly appreciated!
Relevant diagram section
//**********************************************************
//Define pins
//PD0 and PD1 are reserved for USART
#define PS2_DATA PA0 //data
#define PS2_CMD PA1 //command
#define PS2_ATT PA2 //attention
#define PS2_CLK PA3 //clock
//Define constants for PS2 communication
#define PS2_START_CMD 0x01
#define PS2_REQUEST_DATA 0x42
#define PS2_CONFIG_MODE 0x43
#define PS2_CONFIG_MODE2 0x01
#define PS2_CONFIG_ANALOG 0x44
#define PS2_CONFIG_EXIT 0x00
#define PS2_SET_ANALOG 0x01
#define PS2_LOCK_ANALOG 0x03
#define PS2_DIGITAL_MODE 0x41
#define PS2_ANALOG_MODE 0x73
#define PS2_NO_CMD 0x00
//Define the locations of the different buttons in the data bytes
//Data byte 1 (PS2CMD1)
#define PS2_SELECT 0
#define PS2_L3 1
#define PS2_R3 2
#define PS2_START 3
#define PS2_UP 4
#define PS2_RIGHT 5
#define PS2_DOWN 6
#define PS2_LEFT 7
//Data byte 2 (PS2CMD2)
#define PS2_L2 0
#define PS2_R2 1
#define PS2_L1 2
#define PS2_R1 3
#define PS2_TRIANGLE 4
#define PS2_CIRCLE 5
#define PS2_X 6
#define PS2_SQUARE 7
//function prototypes
void PS2Init();
void PS2Get(void);
static unsigned char PS2ReadSend(unsigned char command);
//variables
unsigned char PS2TEMP = 0x00;
unsigned char PS2ID = 0xFF;
unsigned char PS2CMD1 = 0x00;
unsigned char PS2CMD2 = 0x00;
int RightHorizontal = 0x00;
int RightVertical = 0x00;
int LeftHorizontal = 0x00;
int LeftVertical = 0x00;
//Function definitions
//*********************************************************************
//BEGIN PS2Init()
//Purpose: Initializes the pins for PS2 communication and sets the
//controller into analog mode and locks it
//Input: NONE
//Output: NONE
//*********************************************************************
void PS2Init(void)
{
DDRA |= (1<<PS2_CLK)|(1<<PS2_ATT)|(1<<PS2_CMD);
//set pins as outputs
PORTA |= (1<<PS2_CLK)|(1<<PS2_ATT)|(1<<PS2_DATA);
//start clock, attention high, pull up resistor on DATA
while(PS2ID == 0xFF) //loop until controller present
{
PORTA &= ~(1<<PS2_ATT); //pull attention low
PS2TEMP = PS2ReadSend(PS2_START_CMD);
PS2ID = PS2ReadSend(PS2_NO_CMD); //check for controller ID
PORTA |= (1<<PS2_CLK); //clock high
PORTA |= (1<<PS2_ATT); //attention high
}
//go into command mode
PORTA &= ~(1<<PS2_ATT); //pull attention low
PS2TEMP = PS2ReadSend(PS2_START_CMD);
PS2TEMP = PS2ReadSend(PS2_CONFIG_MODE);
PS2TEMP = PS2ReadSend(PS2_NO_CMD);
PS2TEMP = PS2ReadSend(PS2_CONFIG_MODE2);
PS2TEMP = PS2ReadSend(PS2_NO_CMD);
PORTA |= (1<<PS2_CLK); //clock high
PORTA |= (1<<PS2_ATT); //attention high
//set controller to analog mode and lock
PORTA &= ~(1<<PS2_ATT); //pull attention low
PS2TEMP = PS2ReadSend(PS2_START_CMD);
PS2TEMP = PS2ReadSend(PS2_CONFIG_ANALOG);
PS2TEMP = PS2ReadSend(PS2_NO_CMD);
PS2TEMP = PS2ReadSend(PS2_SET_ANALOG);
PS2TEMP = PS2ReadSend(PS2_LOCK_ANALOG);
PS2TEMP = PS2ReadSend(PS2_NO_CMD);
PS2TEMP = PS2ReadSend(PS2_NO_CMD);
PS2TEMP = PS2ReadSend(PS2_NO_CMD);
PS2TEMP = PS2ReadSend(PS2_NO_CMD);
PORTA |= (1<<PS2_CLK); //clock high
PORTA |= (1<<PS2_ATT); //attention high
//exit configuration mode
PORTA &= ~(1<<PS2_ATT); //pull attention low
PS2TEMP = PS2ReadSend(PS2_START_CMD);
PS2TEMP = PS2ReadSend(PS2_CONFIG_MODE);
PS2TEMP = PS2ReadSend(PS2_NO_CMD);
PS2TEMP = PS2ReadSend(PS2_NO_CMD);
PS2TEMP = PS2ReadSend(0x5A);
PS2TEMP = PS2ReadSend(0x5A);
PS2TEMP = PS2ReadSend(0x5A);
PS2TEMP = PS2ReadSend(0x5A);
PS2TEMP = PS2ReadSend(0x5A);
PORTA |= (1<<PS2_CLK); //clock high
PORTA |= (1<<PS2_ATT); //attention high
} // END PS2Init()
//*********************************************************************
//BEGIN PS2Get()
//Purpose: Gets the PS2 controller configuration. Returns (as a global
//variable) the joystick positions as a value from -255 to +255
//Input: NONE
//Output: NONE
//*********************************************************************
void PS2Get(void)
{
PORTA &= ~(1<<PS2_ATT); //pull attention low
PS2TEMP = PS2ReadSend(PS2_START_CMD);
PS2ID = PS2ReadSend(PS2_REQUEST_DATA);
PS2TEMP = PS2ReadSend(PS2_NO_CMD);
PS2CMD1 = ~PS2ReadSend(PS2_NO_CMD); //invert output so high
//means button pressed
PS2CMD2 = ~PS2ReadSend(PS2_NO_CMD); //invert output so high
//means button pressed
RightHorizontal = PS2ReadSend(PS2_NO_CMD);
RightVertical = PS2ReadSend(PS2_NO_CMD);
LeftHorizontal = PS2ReadSend(PS2_NO_CMD);
LeftVertical = PS2ReadSend(PS2_NO_CMD);
PORTA |= (1<<PS2_CLK); //clock high
PORTA |= (1<<PS2_ATT); //attention high
} //END PS2Get()
//*********************************************************************
//BEGIN PS2ReadSend()
//Purpose: The bitwise send command and read data function. This
//function is only to be called by the functions PS2Init() and PS2Get()
//and should never be called directly from the DRA code
//Input: PS2 commands
//Output: PS2 data
//*********************************************************************
unsigned char PS2ReadSend(unsigned char command)
//clock must be high before calling
{
unsigned char PS2Data = 0x00;
for(int i=0;i<8;i++)
{
PORTA &= ~(1<<PS2_CLK); //set clock low
if(bit_is_set(command, i)) //is PS2 command bit i set?
PORTA |= (1<<PS2_CMD); //if yes set PS2_CMD bit
else
PORTA &= ~(1<<PS2_CMD); //if no clear PS2_CMD bit
_delay_us(60); //wait for PS2 controller to set data bit
PORTA |= (1<<PS2_CLK); //set clock high. Controller sets
//and reads on clock change
if(bit_is_set(PINA, PS2_DATA)) //is PS2_DATA bit set?
PS2Data |= (1<<i); //if yes set PS2Data bit i
else
PS2Data &= ~(1<<i); //if no clear PS2Data bit i
_delay_us(60); //wait for PS2 controller to
}
_delay_us(300); //wait for PS2 controller to acknowledge
return PS2Data;
} // END PS2ReadSend()
/**********************************************************