Turning an Arduino nano into a joystick

Hi all, this is an old post, but as I went through it when I was looking a solution for a similar issue, here is what I do:

  • I'm using linux, but I'm sure you will find the equivalent for other systems.

On arduino:

  • for each pin where a button is attached to, i use pinmode(xxx,input_pull)
    On linux
  • i read the ttyUSB
  • and i use the tool xdotool

So, yes, the buttons will act as a key of a keyboard, rather than exactly a joystick, but that should be ok for old consoles emulation.

arduino:

int Pin[12]={2,3,4,5,6,7,8,9,10,11,12,13}
int Stat[12]={0,0,0,0,0,0,0,0,0,0,0,0,0}
int Maxi = 12

void Setup() {
  Serial.begin(115200);
  while (!Serial) {
    ;
  }

  for (int i = 0; i < Maxi ; i = i + 1) {
    pinMode(i, INPUT_PULLUP);             // defines all pins used as Pullups
  }
}

void loop() {
  for (int i = 0; i < Maxi ; i = i + 1) {
    Stat[i] = digitalRead(Pin[i]);           //Stat is 0 when the button is pressed, 1 else
    Serial.print(Stat[i]);
  }
  Serial.println("");                             //ends the line

this will send to serial something like that:

111111111      <-- no button is pressed
111111111
111111111
111011111      <-- button attached to D5 is pressed
111011111
111011111
111011111
111011111
110011111      <-- button attached to D4 is also pressed
110011111
110011111
110011111      <-- buttton attached to D4 is released
111011111
111011111
111011111
111011111
111111111      <-- buttton attached to D5 is released

On the linux side, I create a bash script :

#!/bin/bash
stty -F /dev/ttyUSB0 115200 cs8 -cstopb -parenb -icanon min 1 time 1

button_A=1    # State of the button A (1 = released, 0 = pressed)
button_B=1 
#  ...          <-------- to be filled with the other buttons, and with the keyboard touch you want to use


key_A=a
key_B=b
#  ...          <-------- to be filled with the other buttons, and with the keyboard touch you want to use
key_start=e
key_up=UP
#  ...          <-------- to be filled with the other buttons, and with the keyboard touch you want to use

while true ; do
  read LINE < /dev/ttyUSB0
  if  [ $(#LINE) = 13 ]     # takes only the lines with the correct number of chars (avoids incorrec readins)
  then
     button_A=$(echo $LINE | cut -c2)   # -c2 indicates the position of the button value in the line sent by the arduino, in my case the button A is on the second position.
     if [[ $buttton_A -ne $button_A_before ]]
     then
         button_A_before = $button_A
         if [ $button_A = 0 ]
         then
             xdotool keydown $key_A       #presses the key corresponding to the A button
         fi
         if [ $button_A = 1 ]
         then
             xdotool keyup $key_A           #presses the key corresponding to the A button
         fi
     fi

#### repeat for the other buttons

done

Next steps:

  • save the script, make it executable (chmod +x ./joystick.sh), run it (./joystick.sh)
  • define the key on your emulator

Notes:
The xdotool may have to be installed (sudo apt install xdotool)
This code allows having several buttons pressed at the same time
The bash script can be improved by using arrays and for loops instead of copies of lines for each button
The only trouble I had was that when I unplugged the USB, and plugged it again, I received whith the TTY one line per second. I changed the baudrate on each side and it worked fine again.