19 October 2014

Joystick shields for Arduino

I was playing around lately with some standard I/O boards and came across the joystick shields. There are at least 2 versions of joystick shields on the market. There is one from sparkfun (see link below) and another labeled with funduino that is available in many stores and as well on eBay.

Both share a kind of Nintendo layout using an analog joystick on the left, 4 buttons on the right and 2 buttons in between. The JoyStick Shield V1.a is the one I like to write bout here but I expect that the sources I share with you can help out on other layouts too.

JoyStickShield

The Funduino version has more functionality by providing  switch for the reference voltage of the analog joystick and a lot of connectors especially for the NRF24L01 transceiver. However samples for the shield are hard to find and most stores don’t provide a schema. So here is my documentation that may help you out of this and some sketches to show the functionality.

The JoyStick IO definitions I use are for the Funduino JoyStick Shield V1.A but they can easily be adapted to the sparkfun and other similar joystick shields.

Raw Signal testing

The JoyStick_RawTest.ino sketch that you can find in the library shows how to initialize all the input ports of the Arduino corresponding to the buttons and the joystick of the shield.

Here is the list of the Arduino ports used by the shield buttons and joystick:

function io port
Button A digital pin 2
Button B digital pin 3
Button C digital pin 4
Button D digital pin 5
Button E digital pin 6
Button F digital pin 7
X - Axis analog pin A0
Y – Axis analog pin A1
Joystick push, Button K digital pin 8

In the loop function the real raw signal levels of the IO are printed out to the Serial port so you can inspect the current values. After compiling and uploading the sketch you should open the serial monitor with the 57600 baud settings and watch all the information coming from the shield.
You can see the difference for the 3V3 / 5V switch in the possible values of the analog input signals.

You should use this sketch just to be sure all the IO definitions are fine.

Signal testing

However, using the raw signals is a kind of pain. 2 simple methods can help you to make this more easy. The JoyStick_Test.ino sketch that you can find in the download files shows how to use the input on a more logical level and in respect of the not so exact analog joystick signals.

Buttons

The levels of the buttons are on the level 1 when not pressed. The conversion is implemented in the function joyButton(...) and returns a boolean value.

boolean joyButton(byte pin) {
  int signal = digitalRead(pin);
  return (signal == 0);
} // joyButton

JoyStick position

The levels of the X and Y joystick normally are not very correct. If you leave the stick untouched in the middle position the actual value from the analog port will not be exactly half the reference voltage and it may jump between some values. It is also very hard to get the stick to a specific position and hold it in place. Therefore I use a function that converts to the analog input value to a range of -4 to 4 where 0 is the level in normal position. The conversion is implemented in the function joyStick(...) and returns a signed int. The 3v3 / 5v switch should be in the 5v position.

int joyStick(byte pin) {
  // read the analog value
  int signal = analogRead(pin);
  // convert with mathematics:
  signal = ((signal+64) / 128) - 4;
  return (signal);
} // joyStick

After compiling and uploading the sketch you should open the serial monitor with the 57600 baud settings and watch all the information coming from the shield.

If you like to use these functions just copy them over to your sketch.

...

Sketch JoyStick_RawTest.ino

/// \file JoyStick_rawtest.ino
/// \brief A simple sketch showing the binary input values fro the joystick board.
///
/// \author Matthias Hertel, http://www.mathertel.de
/// \copyright Copyright (c) 2014 by Matthias Hertel.\n
/// This work is licensed under a BSD style license.\n
/// See http://www.mathertel.de/License.aspx
///
/// \details
/// This sketch shows how to initialize all the input ports of the Arduino
/// corresponding to the buttons and the joystick of the shield.
/// The real raw singal levels of the IO are printed out to the Serial port
/// so you can inspect the current values.
/// you can see the difference for the 3V3 / 5V switch in the possible values
/// of the analog input signals.
/// The JoyStick IO definitions  here are for the Funduino JoyStick Shield V1.A.
/// It can easily be adapted to the sparkfun JoyStick Shield.
///
/// More documentation and source code is available at http://www.mathertel.de/Arduino
///
/// History:
/// --------
/// * 18.10.2014 creation.

/// Port definitions for the buttons on the shield with the printed labels
#define BUTTON_A  2 
#define BUTTON_B  3
#define BUTTON_C  4
#define BUTTON_D  5
#define BUTTON_E  8
#define BUTTON_F  7

/// Port definitions for the JoyStick functions
#define ANALOG_PUSH 8
#define ANALOG_X A0 
#define ANALOG_Y A1 


void setup() {
  Serial.begin(57600);

  // Setup button inputs with internal pull up high resistor
  pinMode(BUTTON_A, INPUT_PULLUP);
  pinMode(BUTTON_B, INPUT_PULLUP);
  pinMode(BUTTON_C, INPUT_PULLUP);
  pinMode(BUTTON_D, INPUT_PULLUP);
  
  // Setup the option buttons
  pinMode(BUTTON_E, INPUT_PULLUP);
  pinMode(BUTTON_F, INPUT_PULLUP);
  
  // Setup joystick button
  pinMode(ANALOG_PUSH, INPUT_PULLUP);
  // The analog inputs need no setup.
}

void loop() {
  Serial.print(" A:"); Serial.print(digitalRead(BUTTON_A));
  Serial.print(" B:"); Serial.print(digitalRead(BUTTON_B));
  Serial.print(" C:"); Serial.print(digitalRead(BUTTON_C));
  Serial.print(" D:"); Serial.print(digitalRead(BUTTON_D));

  Serial.print(" E:"); Serial.print(digitalRead(BUTTON_E));
  Serial.print(" F:"); Serial.print(digitalRead(BUTTON_F));
  
  Serial.print(" -- X:"); Serial.print(analogRead(ANALOG_X));
  Serial.print(" y:"); Serial.print(analogRead(ANALOG_Y));
  Serial.print(" K:"); Serial.print(digitalRead(ANALOG_PUSH));

  Serial.println();
  delay(250);
}

 

Sketch JoyStick_Test.ino

///
/// \file JoyStick_Test.ino
/// \brief A simple sketch showing the binary input values from the joystick board.
///
/// \author Matthias Hertel, http://www.mathertel.de
/// \copyright Copyright (c) 2014 by Matthias Hertel.\n
/// This work is licensed under a BSD style license.\n
/// See http://www.mathertel.de/License.aspx
///
/// \details
/// This sketch shows how to initialize all the input ports of the Arduino
/// corresponding to the buttons and the joystick of the shield.
/// Here the io signal are converted to be interpreted easily:
/// * The levels of the buttons are on the level 1 when not pressed.
/// The conversion is implemented in the function joyButton(...) and returns a boolean value.
/// * The levels of the X and Y joystick normally are not very correct.
/// They are converted to the range -4 to 4 where 0 is the level in normal position.
/// The conversion is implemented in the function joyStick(...) and returns a signed int.
/// The 3v3 / 5v switch should be in the 5v position.
///
/// The JoyStick IO definitions  here are for the Funduino JoyStick Shield V1.A.
/// It can easily be adapted to the sparkfun JoyStick Shield.
///
/// More documentation and source code is available at http://www.mathertel.de/Arduino
///
/// History:
/// --------
/// * 18.10.2014 creation.

/// Port definitions for the buttons on the shield with the printed labels
#define BUTTON_A  2 
#define BUTTON_B  3
#define BUTTON_C  4
#define BUTTON_D  5
#define BUTTON_E  8
#define BUTTON_F  7

/// Buttons with the names of the classic Nintendo layout
#define BUTTON_SELECT BUTTON_F
#define BUTTON_START BUTTON_E

/// Port definitions for the JoyStick functions
#define ANALOG_PUSH 8
#define ANALOG_X A0 
#define ANALOG_Y A1 

boolean joyButton(byte pin) {
  int signal = digitalRead(pin);
  return (signal == 0);
} // joyButton


int joyStick(byte pin) {
  // 000....128....256....384....512....640....768....896....1024
  // -4     -3     -2     -1      0      1      2      3       4
  int signal = analogRead(pin);
  /// convert with mathematics
  signal = ((signal+64) / 128) - 4;
  return (signal);
} // joyStick


void setup() {
  Serial.begin(57600);

  // Setup button inputs with internal pull up high resistor
  pinMode(BUTTON_A, INPUT_PULLUP);
  pinMode(BUTTON_B, INPUT_PULLUP);
  pinMode(BUTTON_C, INPUT_PULLUP);
  pinMode(BUTTON_D, INPUT_PULLUP);
  
  // Setup the option buttons
  pinMode(BUTTON_E, INPUT_PULLUP);
  pinMode(BUTTON_F, INPUT_PULLUP);
  
  // Setup joystick button
  pinMode(ANALOG_PUSH, INPUT_PULLUP);
  // The analog inputs need no setup.
}

void loop() {
  Serial.print(" A:"); Serial.print(joyButton(BUTTON_A));
  Serial.print(" B:"); Serial.print(joyButton(BUTTON_B));
  Serial.print(" C:"); Serial.print(joyButton(BUTTON_C));
  Serial.print(" D:"); Serial.print(joyButton(BUTTON_D));

  Serial.print(" E:"); Serial.print(joyButton(BUTTON_E));
  Serial.print(" F:"); Serial.print(joyButton(BUTTON_F));
  
  Serial.print(" -- X:"); Serial.print(joyStick(ANALOG_X));
  Serial.print(" y:"); Serial.print(joyStick(ANALOG_Y));
  Serial.print(" K:"); Serial.print(joyButton(ANALOG_PUSH));

  Serial.println();
  delay(250);
}

 

Additional Links

http://arduino.cc/en/Main/ArduinoBoardEsplora

http://arduino.cc/en/Reference/EsploraReadJoystickSwitch