Monday, January 2, 2017

Creating a WASD joystick with an Arduino Esplora

Introduction

The classic WASD game keys are very popular. But if this key layout is nice on QWERTY keyboard, it is not so logical on an AZERTY keyboard.


With such layout you cannot make great score at any game.
The classic solution is to configure the keyboard as a US QWERTY keyboard for the duration of the game. But that's not a very satisfactory solution. What we need is a joystick that behaves like the WASD keys.

The Arduino Esplora board

The Arduino Esplora board is an Arduino Leonardo board that implement a joystick.
This is exactly what we need.

 The Leonardo (and the Esplora) board can behave like an HID device. This means that they can be programmed to behave as an USB mouse or as an USB  keyboard by the computer.

Now all we need is to program it so that the board joystick generates the WSAD key press.

The program

Enrico Gueli has written a program called "EsploraKart" (www.arduino.cc/en/Tutorial/EsploraKart) that does exactly what we want except that he has used the arrow keys instead of the WSAD keys.
Now lets modify his program to get the WSAD keys mapping:

/*
 esploraWASD
 This is a sketch is a modification of "EsploraKart" written by Enrico Gueli
 The joystick will send the WASD keys and
 the switches will send "space"
*/
#include <Esplora.h>
#include <Keyboard.h>
boolean buttonStates[8];
const byte buttons[] = {
  JOYSTICK_DOWN,
  JOYSTICK_LEFT,
  JOYSTICK_UP,
  JOYSTICK_RIGHT,
 
  SWITCH_RIGHT,
  SWITCH_LEFT,
  SWITCH_UP,
  SWITCH_DOWN
};
const char keystrokes[] = {
  's',
  'a',
  'w',
  'd',
  ' ',
  ' ',
  ' ',
  ' '

};
void setup() {
  Keyboard.begin();
}
void loop() {
  for (byte thisButton = 0; thisButton < 8; thisButton++) {
    boolean lastState = buttonStates[thisButton];
    boolean newState = Esplora.readButton(buttons[thisButton]);
    if (lastState != newState) { // Something changed!
      if (newState == PRESSED) {
        Keyboard.press(keystrokes[thisButton]);
      }
      else if (newState == RELEASED) {
        Keyboard.release(keystrokes[thisButton]);
      }
    }
    buttonStates[thisButton] = newState;
  }
  delay(50);
}

I have removed the comments and marked in red the modified lines

 Return of the AZERTY problem

The above program will work great if you have a QWERTY (or a German QWERTZ) keyboard, but strangely, it does not work with a computer configured with an AZERTY keyboard.

On a AZERTY computer the Esplora board outputs are  ZQSD instead of WASD.
If you look at the position of the ZQSD keys on an AZERTY keyboard you will notice that they are at the same location as the WASD keys on a QWERTY keyboard.

This is a limitation of the Arduino Keyboard library: this library allows to simulate a keyboard with a Leonardo or an Esplora board but the simulated keyboard is expecting that the computer uses a US QWERTY keyboard layout.

This origin of this restriction comes from the HID protocol: It specifies a key location on the keyboard and it is the computer responsibility to map this key location to a key symbol (or a special key).

I should have tried to adapt the Arduino Keyboard library to support multiple keyboard layouts. But I was too lazy ( this guy did something like that www.zem.fr). I simply have mapped the AZERTY keys in my program. This makes the program only usable on an AZERTY PC.

const char keystrokes[] = {
  's',//s
  'q',//a
  'z',//w
  'd',//d
  ' ',
  ' ',
  ' ',
  ' '
};

With this mapping the Esplora board is behaving like a WASD joystick. This is what I needed.