Turning an Arduino nano into a joystick

Hello there

We have made a joystick prototype. It is using an arduinon nano, a 2-axis analog stick and 2 buttons.

So far i'm using it with a basic serial protocol, into a vjoy feeder. (http://vjoystick.sourceforge.net/)

It's working fine but I'd like something simpler. I'm quite new to arduino, but i've seen the work of connor here to turn a leonardo into a joystick by modifiying the HID descriptor. I understand that with this i would not need vjoy, much more plug and play.

Is it possible to do so with a nano? what are the steps involved? I've merged his tweaks of usbapi.h and hid.cpp into hardware/arduino/core, but when i try to upload the sketch it seems to not see my changes (i get 'JoyState_t' does not name a type error message). What am i missing there?

thank you for any support or clue you might provide.

Hello people

I’m quite stuck on the subject, and i’d really appreciate some support…


hello, look that post http://www.instructables.com/id/Arduino-LeonardoMicro-as-Game-ControllerJoystick/?ALLSTEPS , this can help you!

The Arduinos (such as Leonardo and Micro) that use the Atmega 32U4 chip have a completely different approach to implementing a USB connection compared to those using the Atmega 328 or Atmega 2560.

With the 32U4 chip the ability to pretend to be a mouse or keyboard is much easier to implement.

Solutions to your problem that are related to the 32U4 chip will not work on a Nano.


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.


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() {
  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.println("");                             //ends the line

this will send to serial something like that:

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

On the linux side, I create a bash script :

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)
#  ...          <-------- to be filled with the other buttons, and with the keyboard touch you want to use

#  ...          <-------- to be filled with the other buttons, and with the keyboard touch you want to use
#  ...          <-------- 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)
     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 ]]
         button_A_before = $button_A
         if [ $button_A = 0 ]
             xdotool keydown $key_A       #presses the key corresponding to the A button
         if [ $button_A = 1 ]
             xdotool keyup $key_A           #presses the key corresponding to the A button

#### repeat for the other buttons


Next steps:

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

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.

V-USB is a software-only implementation of a low-speed USB device for Atmel’s AVR® microcontrollers, making it possible to build USB hardware with almost any AVR® microcontroller, not requiring any additional chip.

and you configure the Nano to be USB-HID joystick with mouse and keyboard included if desired for panning and buttons. HID requires no changes to the PC.

If you use a Teensy 2.0 (and likely Arduino Micro) you can have 12 axes; 3 stick, 1 pedals and 8 throttles/trimmers. And they don't need V-USB to run HID, it's easier and faster on AVR-USB boards.

Use Linear Hall sensors and bar magnets instead of pots if you can. The sensor has 1 axis you place over the turn center of the magnet. When the magnet is aligned with the sensor axis you get the highest reading (choose a resistor that makes that analog read about 1000) and if not aligned you get the cosine of the angle between sensor and magnet that a simple lookup table can give the angle in microseconds -- Arduinos usually have a lot of room in flash for tables, means not having to run slow cpu-hogging floating point calcs.