Classic gameport joysticks such as the Logitech wingman are excellent controllers to use with small microprocessors since the output is either a varying resistance or a switch. However a single joystick may have as many as 10 outputs which requires substantial wiring. In the case of the robosub project it is desired to use a pair of joysticks (in this case 14 IO in total). Sending 14 signals down a 100 foot tether to the submarine adds significant cabling to the tether. Instead the 14 IO are converted into a TTL serial signal which is then sent down the cable at 2400 baud. 2400 baud is selected as lower speed means more robust signaling. If it turns out that this is not sufficiently robust at long cable lengths, we can use a Max232 line driver on each end.
Below is the code for both ends of the project:
/*
Read PC Joystick
A5 Joy1X A4 Joy1Y A3 Joy1X1 (Hat etc) A2 Joy1Y1 (Throttle etc) A1 Joy2X1 A0 Joy2Y1
D2 Joy1Butn1 D3 Joy1Butn2 D4 joy1Butn3 D5 joy1Butn4
D6 Joy2Butn1 D7 Joy2Butn2 D8 Joy2Butn3 D9 Joy2Butn4</code>
Note on Box: Green - Green&White +5 Orange RX Orange&White TX
Functions:
read_joysticks: Read the current state of the joysticks
read_data: Read joystick data from another arduino using this code
write_data: Write joystick data to the serial port
debug_vals: Output the valiables in human readable form
Sample Python Testcode at end
*/
// These constants won't change. They're used to give names
// to the pins used:
const int Joy1X = A5;
const int Joy1Y = A4 ;
const int Joy1X1 = A3;// (Hat etc)
const int Joy1Y1 = A2; // (Throttle etc)
const int Joy2X = A1;
const int Joy2Y = A0;
const int Joy1Butn1 = 2;
const int Joy1Butn2 =3;
const int Joy1Butn3 = 4;
const int Joy1Butn4 = 5;
const int Joy2Butn1 = 6;
const int Joy2Butn2 = 7;
const int Joy2Butn3 = 8;
const int Joy2Butn4 = 9;
//Define a set of variables to store the values.
int Joy1X_Val,Joy1Y_Val,Joy1X1_Val,Joy1Y1_Val,Joy2X_Val,Joy2Y_Val;
int Joy1Butn1_Val,Joy1Butn2_Val,Joy1Butn3_Val,Joy1Butn4_Val,Joy2Butn1_Val, Joy2Butn2_Val,Joy2Butn3_Val,Joy2Butn4_Val;
void setup() {
// initialize serial communications at 9600 bps:
Serial.begin(2400);
pinMode(Joy1Butn1, INPUT);
pinMode(Joy1Butn2, INPUT);
pinMode(Joy1Butn3, INPUT);
pinMode(Joy1Butn4, INPUT);
pinMode(Joy2Butn1, INPUT);
pinMode(Joy2Butn2, INPUT);
pinMode(Joy2Butn3, INPUT);
pinMode(Joy2Butn4, INPUT);
Serial.println('Initialized');
}
void loop() {
//Standard usage for reading joysticks
read_joysticks();
write_data();
//Standard usage for getting data from the joystick module
//read_data(); //this makes the data available in the global
//joystick variables declared above
delay(60); // wait 60 milliseconds before the next loop
}
void read_joysticks()
{
Joy1X_Val = map(analogRead(Joy1X), 0, 1023, 0, 255);
Joy1Butn1_Val = digitalRead(Joy1Butn1);
Joy1Y_Val = map(analogRead(Joy1Y), 0, 1023, 0, 255);
Joy1Butn2_Val = digitalRead(Joy1Butn2);
Joy1X1_Val = map(analogRead(Joy1X1), 0, 1023, 0, 255);
Joy1Butn3_Val = digitalRead(Joy1Butn3);
Joy1Y1_Val = map(analogRead(Joy1Y1), 0, 1023, 0, 255);
Joy1Butn4_Val = digitalRead(Joy1Butn4);
Joy2X_Val = map(analogRead(Joy2X), 0, 1023, 0, 255);
Joy2Butn1_Val = digitalRead(Joy2Butn1);
Joy2Y_Val = map(analogRead(Joy2Y), 0, 1023, 0, 255);
Joy2Butn2_Val = digitalRead(Joy2Butn2);
Joy2Butn3_Val = digitalRead(Joy2Butn3);
Joy2Butn4_Val = digitalRead(Joy2Butn4);
}
void read_data()
{
if (Serial.available() > 0) // Don't read unless
// there you know there is data
{
while(Serial.read() != '&')//Check for the Start Character
{
}
// read the Values in from the serial port
Joy1X_Val = Serial.read();
Joy1Y_Val = Serial.read();
Joy1X1_Val = Serial.read();
Joy1Y1_Val = Serial.read();
Joy1Butn1_Val = Serial.read();
Joy1Butn2_Val = Serial.read();
Joy1Butn3_Val = Serial.read();
Joy1Butn4_Val = Serial.read();
Joy2X_Val = Serial.read();
Joy2Y_Val = Serial.read();
Joy2Butn1_Val = Serial.read();
Joy2Butn2_Val = Serial.read();
Joy2Butn3_Val = Serial.read();
Joy2Butn4_Val = Serial.read();
}
}
void write_data()
{
Serial.print('&');
Serial.write(Joy1X_Val);
Serial.write(Joy1Y_Val);
Serial.write(Joy1X1_Val);
Serial.write(Joy1Y1_Val);
Serial.write(Joy1Butn1_Val);
Serial.write(Joy1Butn2_Val);
Serial.write(Joy1Butn3_Val);
Serial.write(Joy1Butn4_Val);
Serial.write(Joy2X_Val);
Serial.write(Joy2Y_Val);
Serial.write(Joy2Butn1_Val);
Serial.write(Joy2Butn2_Val);
Serial.write(Joy2Butn3_Val);
Serial.write(Joy2Butn4_Val);
Serial.println();
}
void debug_vals()
{
Serial.print('['); //This is the start character in the message
Serial.print(Joy1X_Val,HEX);
Serial.print(Joy1Y_Val,HEX);
Serial.print(Joy1X1_Val,HEX);
Serial.print(Joy1Y1_Val,HEX);
Serial.print(Joy1Butn1_Val,BIN);
Serial.print(Joy1Butn2_Val,BIN);
Serial.print(Joy1Butn2_Val,BIN);
Serial.print(Joy1Butn2_Val,BIN);
Serial.print(Joy2X_Val,HEX);
Serial.print(Joy2Y_Val,HEX);
Serial.print(Joy2Butn1_Val,BIN);
Serial.print(Joy2Butn2_Val,BIN);
Serial.print(Joy2Butn2_Val,BIN);
Serial.print(Joy2Butn2_Val,BIN);
Serial.println(']');//Terminating Character
}
/* Python code to read in Data
import serial #The pyserial library must be installed
#Format
#&,Joy1X,Joy1Y,Joy1X1,Joy1Y1,Joy1Btn1,Joy1Btn2,Joy1Brn3,Joy1Btn4,Joy2X,Joy2Y,Joy2Btn1,Joy2Btn2,Joy2Btn3,Joy2Btn4
ser = serial.Serial(13,2400) #By default the device uses port 14 (python #s from 0)
print ser.portstr #Print the valid port
j=0
while (j < 100): #100 for testing
char = ser.read() #Read in a character
if char == '&': #If we are at the start of a new string
commandlist = [] #initialize the list
for i in range(0,14):
char = ser.read()
commandlist.append(ord(char)) #Append the ascii value to the list
i += 1
print commandlist #Print the list after it is built
j+=1
ser.close()
*/