MAME ARCADE STICK with 16 keyboard keys using Arduino Leonardo

Hello

I am a complete beginner with no programming and Arduino skills. But in the last few days I tried to read a lot of stuff available regarding it to start my journey with it.

As this is my first project, I plans to make a simple USB keyboard/Mame arcade stick which I am going to use for other PC games like Devil May Cry3 as well. So I figured, I need 4 directional keys, 8 action buttons, 2 keys for start & coin, Escape and Enter key ( just like in computer keyboard). So in total,16 keys.

As I found out that Arduino Leonardo can be emulated as USB keyboard and it provides you with 20 digital I/O keys. I did a extensive search on various libraries regarding it, and found somewhat similar code for it as well (which I modified as per my own need).

I already brought Arduino Leonardo chip and arcade control stick and buttons to move forward with my project.

Kindly check if it will be possible for me to use the analog keys as digital by emulating it as USB keyboard for my arcade controller and it should act as 0 delay keyboard encoder.

#**include** <Keyboard.h>

// MAMEish. An array of pin-key pairs.
struct { int pin; int key; } pinsToKeys[] = {
{ 2, KEY_LEFT_ARROW },
{ 3, KEY_UP_ARROW },
{ 4, KEY_RIGHT_ARROW },
{ 5, KEY_DOWN_ARROW },
{ 6, 's' }, // Fire 1
{ 7, 'd' }, // Fire 2
{ 8, 'f' }, // Fire 3
{ 9, 'x' }, // Fire 4
{ 10, 'c' }, // Fire 5
{ 11, 'v' }, // Fire 6
{ 12, 'g' }, // Button 7
{ 13, 'b' } // Button 8

{ A0, '1' } // select

{ A1, '5' } // Coin

{ A2, KEY_ESC } // Back

{ A3, KEY_RETURN } // Confirm Actions/Activate
};

void setup() {
// Set all used pins to handle input from
// arcade buttons.
for (auto const &pinToKey : pinsToKeys) {
pinMode(pinToKey.pin, INPUT_PULLUP);
}

// Initialize keyboard.
Keyboard.begin();
}

void loop() {
// For each pin-key pair, check the state
// of the pin and set the associated key
// state to match.
for (auto const &pinToKey : pinsToKeys) {
if (digitalRead(pinToKey.pin) == LOW) {
Keyboard.press(pinToKey.key);
} else {

Keyboard.release(pinkey.key);
      }

   }

}

@naveensanju, please edit your post, select all code and click the </> button; next save your post. As a result, we will not see pinsToKeys[] but pinsToKeys[]; it will also make it easier to read and copy.

Please spend some time reading How to get the best out of this forum.

Analog inputs can be used as digital inputs.

Thanks for replying. I corrected the code as per your directions :slight_smile:

1 Like

There is a useful function in the IDE; tools -> autoformat. It will indent your code properly. I've also fixed some errors like missing commas.

#include <Keyboard.h>

// MAMEish. An array of pin-key pairs.
struct PINSTOKEY
{
  int pin;
  int key;
};

PINSTOKEY pinsToKeys[] =
{
  { 2, KEY_LEFT_ARROW },
  { 3, KEY_UP_ARROW },
  { 4, KEY_RIGHT_ARROW },
  { 5, KEY_DOWN_ARROW },
  { 6, 's' }, // Fire 1
  { 7, 'd' }, // Fire 2
  { 8, 'f' }, // Fire 3
  { 9, 'x' }, // Fire 4
  { 10, 'c' }, // Fire 5
  { 11, 'v' }, // Fire 6
  { 12, 'g' }, // Button 7
  { 13, 'b' }, // Button 8
  { A0, '1' }, // select
  { A1, '5' }, // Coin
  { A2, KEY_ESC }, // Back
  { A3, KEY_RETURN }, // Confirm Actions/Activate
};

void setup()
{
  // Set all used pins to handle input from
  // arcade buttons.
  for (auto const &pinToKey : pinsToKeys)
  {
    pinMode(pinToKey.pin, INPUT_PULLUP);
  }

  // Initialize keyboard.
  Keyboard.begin();
}

void loop()
{
  // For each pin-key pair, check the state
  // of the pin and set the associated key
  // state to match.
  for (auto const &pinToKey : pinsToKeys)
  {
    if (digitalRead(pinToKey.pin) == LOW)
    {
      Keyboard.press(pinToKey.key);
    }
    else
    {
      Keyboard.release(pinToKey.key);
    }
  }
}

Be aware that loop() executes very fast so if you press a button with your current code, it will send a number of keypresses to the PC when you press a button, not a single keypress. If you don't want that, you will have to detect when a button becomes pressed, not when it is pressed as you currently do.

On a Leonardo, you can safely use pins 0 and 1 as well; they are not used for serial communication with the PC.

It might be advisable to add a safety mechanism so you can stop your Leonardo from sending keypresses due to coding mistakes; a keypress is remembered by the PC till you release it and you have to jump through all kinds of hoops to get your PC in a normal state. You would not be the first one who manages to get the PC in a state where e.g. the <ctrl>is pressed and not released and pressing e.g. 'A' on the normal keyboard after that will always result in <ctrl>A until you reboot the PC.

Just allocate a pin (e.g. A5); if that pin is e.g. LOW, you abort e.g. loop() immediately so nothing will be sent.

Below as demo

#include <Keyboard.h>

const byte safetyPin = A5;
...
...
void setup()
{
  pinMode(safetyPin, INPUT_PULLUP);
  ...
  ...
}
void loop()
{
  if (digitalRead(safetyPin) == LOW)
  {
    return;
  }
  ...
  ...
}

The ... represents your existing code.

Wiring A5 (in above in above example) to GND will prevent the Leonardo from sending any keypresses in loop(); for normal use, disconnect the wire between A5 and GND.

This topic was automatically closed 120 days after the last reply. New replies are no longer allowed.