Tags

    Arduino UNO Big Joystick HID firmware

    I've extended the joystick firmware to present a much larger joystick to the host PC. The new firmware has:
    • 8 analog axis supporting values from -32768 to 32767.
    • 40 buttons
    This should be handy for building large control systems like the flight controls for a flight simulator, Firefly console, Viper console, or other large control system.

    Background

    A little background for anyone new to creating USB devices with the Arduino UNO or MEGA2560.

    The USB interface on the UNO and MEGA2560 boards is implemented in a small AVR. For R1 and R2 boards that AVR is an Atmega8U2, and for R3 boards it is an Atmega16U2. These chips are programmed with firmware that presents a USB Serial interface to the host PC, and they connect to the Arduino's main Atmega MCU via its TTL Serial port (digital pins 0 and 1).

    The 8U2 and 16U2 can be reprogrammed using DFU (Device Firmware Upgrade mode). This means that the USB Serial firmware can be replaced with other USB firmware to turn the Arduino all sorts of USB devices, like a mouse, a keyboard, a joystick, or a MIDI device.

    More info on DFU mode:

    Big Joystick Firmware


    Serial Report Format

    Byte Type Description
    0,1 int16_t Analog Axis 0 (X) value. -32768 to 32787
    2,3 int16_t Analog Axis 1 (Y) value. -32768 to 32787
    4,5 int16_t Analog Axis 2 value. -32768 to 32787
    6,7 int16_t Analog Axis 3 value. -32768 to 32787
    8,9 int16_t Analog Axis 4 value. -32768 to 32787
    10,11 int16_t Analog Axis 5 value. -32768 to 32787
    12,13 int16_t Analog Axis 6 value. -32768 to 32787
    14,15 int16_t Analog Axis 7 value. -32768 to 32787
    16 uint8_t Buttons 0-7. Bit 0 = button 0, bit 7 = button 7
    17 uint8_t Buttons 8-15. Bit 0 = button 8, bit 7 = button 15
    18 uint8_t Buttons 16-23. Bit 0 = button 16, bit 7 = button 23
    19 uint8_t Buttons 24-31. Bit 0 = button 24, bit 7 = button 31
    20 uint8_t Buttons 32-39. Bit 0 = button 32, bit 7 = button 40

    This table describes the format of the 21 byte report that the Arduino sends to the 8U2/16U2. This allows the Arduino to emulate a large joystick, sending axis positions and the value of 40 buttons to the Host PC.

    HID Descriptor


    This is the HID descriptor for the joystick. You can learn more about them from the USB HID Usage Tables.
     
     
     
    0x05, 0x01, /* Usage Page (Generic Desktop) */
    0x09, 0x04, /* Usage (Joystick) */

    0xa1, 0x01, /* Collection (Application) */
    0x09, 0x01, /* Usage (Pointer) */

    /* 8 axes, signed 16 bit resolution, range -32768 to 32767 (16 bytes) */
    0xa1, 0x00, /* Collection (Physical) */
    0x05, 0x01, /* Usage Page (Generic Desktop) */
    0x09, 0x30, /* Usage (X) */
    0x09, 0x31, /* Usage (Y) */
    0x09, 0x32, /* Usage (Analog1) */
    0x09, 0x33, /* Usage (Analog2) */
    0x09, 0x34, /* Usage (Analog3) */
    0x09, 0x35, /* Usage (Analog4) */
    0x09, 0x36, /* Usage (Analog5) */
    0x09, 0x37, /* Usage (Analog6) */
    0x16, 0x00, 0x80, /* Logical Minimum (-32768) */
    0x26, 0xff, 0x7f, /* Logical Maximum (32767) */
    0x75, 16, /* Report Size (16) */
    0x95, 8, /* Report Count (8) */
    0x81, 0x82, /* Input (Data, Variable, Absolute, Volatile) */
    0xc0, /* End Collection */

    /* 40 buttons, value 0=off, 1=on (5 bytes) */
    0x05, 0x09, /* Usage Page (Button) */
    0x19, 1, /* Usage Minimum (Button 1) */
    0x29, 40, /* Usage Maximum (Button 40) */
    0x15, 0x00, /* Logical Minimum (0) */
    0x25, 0x01, /* Logical Maximum (1) */
    0x75, 1, /* Report Size (1) */
    0x95, 40, /* Report Count (40) */
    0x81, 0x02, /* Input (Data, Variable, Absolute) */
    0xc0 /* End Collection */

    Example Sketch


    Here's a sketch demonstrating how to send joystick data to the host.

        /* Arduino USB Joystick HID demo */
    /* Author: Darran Hunt
    * Released into the public domain.
    */
    #define NUM_BUTTONS 40
    #define NUM_AXES 8 // 8 axes, X, Y, Z, etc
        typedef struct joyReport_t {
    int16_t axis[NUM_AXES];
    uint8_t button[(NUM_BUTTONS+7)/8]; // 8 buttons per byte
    } joyReport_t;
    joyReport_t joyReport;
    void setup()
    {
    Serial.begin(115200);
    delay(200);
    for (uint8_t ind=0; ind<8; ind++) {
    joyReport.axis[ind] = ind*1000;
    }
    for (uint8_t ind=0; ind<sizeof(joyReport.button); ind++) {
    joyReport.button[ind] = 0;
    }
    }
    // Send an HID report to the USB interface
    void sendJoyReport(struct joyReport_t *report)
    {
    Serial.write((uint8_t *)report, sizeof(joyReport_t));
    }
    // turn a button on
    void setButton(joyReport_t *joy, uint8_t button)
    {
    uint8_t index = button/8;
    uint8_t bit = button - 8*index;
    joy->button[index] |= 1 << bit;
    }
    // turn a button off
    void clearButton(joyReport_t *joy, uint8_t button)
    {
    uint8_t index = button/8;
    uint8_t bit = button - 8*index;
    joy->button[index] &= ~(1 << bit);
    }
    uint8_t button=0; // current button
    bool press = true; // turn buttons on?
        /* Turn each button on in sequence 1 - 40, then off 1 - 40
    * add values to each axis each loop
    */
    void loop()
    {
    // Turn on a different button each time
    if (press) {
    setButton(&joyReport, button);
    } else {
    clearButton(&joyReport, button);
    }
    /* Move all of the axes */ for (uint8_t ind=0; ind<8; ind++) { joyReport.axis[ind] += 10 * (ind+1); } sendJoyReport(&joyReport); button++; if (button >= 40) { button = 0; press = !press; } delay(100); }

    Upload the sketch to the Arduino first, then flash Arduino-big-joystick.hex to the 8U2/16U2. Unplug the Arduino and plug it back in, and will look like a joystick to the host and the host will receive the joystick updates from the sketch.

    If you want to upload another sketch, flash Arduino-usbserial.hex to the 8U2/16U2 first, unplug the Arduino and plug it back in. You can now upload the sketch.

    Downloads


    Demo sketch, joystick firmware, usbserial firmware.

    Download file "big_joystick_demo.ino"
    Download file "Arduino-big-joystick.hex"
    Download file "Arduino-usbserial.hex"

    Here's a python test application for checking that your Arduino joystick is behaving correctly. It requires pygame and ocempgui.

    Download file "joy.py"

    Source code is available on Github. See my earlier blog posts for directions on how to build the firmware.

    Loading the firmware


    For the Atmega8u2 (UNO R1, R2, MEGA2560 R1, R2):
    • Put the UNO into DFU mode.
    • dfu-prgrammer at90usb82 erase
    • dfu-programmer at90usb82 flash --debug 1 Arduino-big-joystick.hex
    • dfu-programmer at90usb82 reset
    • Unplug the UNO's USB cable for a few seconds and plug it back in
    For the ATMEGA16U2 (UNO R3, MEGA2560 R3)
    • Put the UNO into DFU mode.
    • dfu-prgrammer atmega16u2 erase
    • dfu-programmer atmega16u2 flash --debug 1 Arduino-big-joystick.hex
    • dfu-programmer atmega16u2 reset
    • Unplug the UNO's USB cable for a few seconds and plug it back in
    Use the same steps to to load Arduino-usbserial.hex when you want to restore the normal functionality to your UNO (e.g. to load a new sketch).

    Note: You will need version 0.5.5 of dfu-programmer to program the ATMEGA16U2. Get the latest version here.

    Comments

    &lt;a|g&gt; (unauthenticated)
    Jan 31, 2013

    Darran,

    Is the source available for this? I could not find it on the Github link that you posted.

    Thanks

    darran
    Jan 31, 2013

    Here's a browse link to the big joystick source: https://github.com/harlequin-tech/arduino-usb/tree/master/firmwares/arduino-big-joystick.

    Alex (unauthenticated)
    Feb 26, 2013

    Hi Darran,

    Thanks for such useful project! What need to be modified in order to add another 40 buttons and have 80 in total?

    Thanks!

    Dom (unauthenticated)
    Feb 27, 2013

    Hi Darren

    I've made a custom keyboard interface and wanting to add two joystick interfaces now. How possible (and easy) is it to make multple devices run from one Arduino 2560?

    Alex (unauthenticated)
    Feb 27, 2013

    Hey Dom, you may want to check this: https://code.google.com/p/unojoy/downloads/list

    Dom (unauthenticated)
    Feb 28, 2013

    I've seen the double joystick but haven't figured out which part of the code handles the usb device part. Admittedly I don't have a full handle on the USB HID bootstrap. So fare I've found nobody who has created code that allows more than one type of device running from an Arduino UNO. I'm thinking the 4kb limit may have something to do with it but it would be awesome to have a hex file which included a keyboard, joysticks and midi (and mouse I guess) all controlled through one Arduino Mega through one usb port. I have a feeling the 16mhz is also a limiting factor here.

    darran
    Mar 3, 2013

    Hi Alex,

    you can increase the number of buttons by modifying the descriptor called JoystickReport in Descriptors.c to add more buttons, and modifying the USB_JoystickReport_Data_t structure in Arduino-joystick.h to make room for the additional buttons.

    darran
    Mar 3, 2013

    Hi Dom,

    if you have a newer Arduino 2560 with the 16u2 then you can fit in additional devices in the descriptor and add code to send data for them. With the older 8u2 its unlikely it will have the code space to support them.

    Andy (unauthenticated)
    Mar 8, 2013

    Hi Darran, thanks for your hard work! I am using your firmware on Sparkfun's 32U4 breakout board (not an Arduino). After some minor modifications to the makefile (changed MCU) I got my board to enumerate in Windows and show up as a game controller. I am using the Big Joystick demo and my question is, how can I write to the joystick axes? I have several potentiometers hooked up to various ADC ports and I would like each of them to control a joystick axis.

    Thank you!

    Ender117 (unauthenticated)
    Mar 24, 2013

    Hello Darran,

    Thank you for all of these great resources. I have flashed the firmware successfully, but I am confused about how to assign pins to the potentiometers and buttons that I have. I don't see any pin assignments in your Arduino BigJoystick sketch. Should I be writing those myself? If you have time, could you point me in the right direction on how to do that? Thank you so much.

    Gyom (unauthenticated)
    Mar 25, 2013

    Hi Darran, great work!

    I have a question tho. If you use the Arduino as a joystick, can you still send back data to it via a serial connection? I mean, would you still be able to make the Arduino light up led and other device from commands sent from the PC at the sametime it "emulate" a joystick in Windows?

    Thanks!

    darran
    Apr 21, 2013

    Hi Gyom,

    the 8u2/16u2 firmware replaces the serial function with the new function. This mean when you flash the joystick or keyboard firmware, the Arduino appears to be a joystick or keyboard and not a serial port.

    i-make-robots (unauthenticated)
    Apr 22, 2013

    Thank you for this excellent How To. I've just build a 6DOF joystick for Kerbal Space Program and Minecraft. Maybe even Descent? I really hope with this I can get it to work. I'll let you know!

    Ender117 (unauthenticated)
    Apr 24, 2013

    Hello again Darran. Can you provide some indication on how to assign pins using your code?

    Dan (unauthenticated)
    Apr 25, 2013

    Hi, Darran. Great tutorial. Thank you for writing it and doing all that hard work on your own. I'm trying to follow your example to flash my MEGA 2560 from OSX Lion. All I get is "dfu-programmer: no device present." Any idea what I'm doing wrong?

    darran
    May 23, 2013

    Dan, try the latest version of dfu-programmer (http://dfu-programmer.sourceforge.net). It might also be that your mega is not in DFU mode, this page may help http://arduino.cc/en/Hacking/DFUProgramming8U2 (its the same two pins on the 2560).

    rabish (unauthenticated)
    Jun 9, 2013

    Hi Darran, and everyone. I get the same problem as Dan ("dfu-programmer: no device present.") with a arduino Uno R3, using dfu-programmer-win-0.6.0.
    I connected briefly the ground and reset pins as described in the above link (but without the 10Kohm resistor soldered on the board, because it's a R3 one) to turn it in DFU mode. The "L" LED, as turned "off" then "on", so the manipulation seems to be efficient.
    Did I missed something? Is the 0.6.0 programmer the last version?
    Dan, did you solve your own issue?

    rabish (unauthenticated)
    Jun 10, 2013

    Hi everyone,
    I just solved my problem using Windows 7 drivers from https://code.google.com/p/unojoy/downloads/list
    so it seems like my previous drivers didn't work well...
    Enjoy, and thanks anyway to those who searched.

    hillar (unauthenticated)
    Jul 18, 2013

    Hi Darran,

    is it possible to use an arduino MICRO for this?

    Fred (unauthenticated)
    Jul 22, 2013

    Hi Darran,

    I'm a combat simulation fan and DIY adept. I have an arduino uno and I'm making a combat stick. That possibility sounds fantastic for the young maker I am.
    Would it be possible to add a wiring scheme in order to use these 8 axis + 40 buttons ? That would allow a quick use of your sketch without digging how to wire bits :o).

    Regards.

    matii43 (unauthenticated)
    Jul 27, 2013

    yahoo point com
    hi what chip i need and what board if need 64 button only joystick, no analog axis and other.
    32-64 button /chip and all adding to usb port to computer,need.
    all come toggle switch. on-off.
    and can i adding same chip/board A+B rotary encoder too ?
    how make program ,step by step,i no newer have programmed anything,
    OR can anybody made to me thats chip some piece ?
    1, chip were have maximum button what chip can adding 32-64 ?
    2, chip were have only maximum rotary encoders what can adding to chip.
    3, chip were have maximum analog were can adding to chip. but thats no important longtime.
    i pay if can made to me,i no understand programmind anything.
    mail to me, name+yahoo.

    Nitin (unauthenticated)
    Aug 24, 2013

    Hi Darren,

    Is there any particular reason that you continue to use 100807 version of LUFA? I see that it's over 2 years old and latest version 130303 is available.

    I did attempt to port your previous project (and thirtybuttons one) to use this latest version. I was successful in compilation but I could never get resultant firmware to run on Arduino UNO.

    Gates (unauthenticated)
    Aug 27, 2013

    Hi Darran,
    How did u generate the hex file? did u refer it from HID descriptor? and how is it possible?

    Gates (unauthenticated)
    Aug 27, 2013

    Im in Windows 7

    Gates (unauthenticated)
    Aug 31, 2013

    And how is it possible to hav 8 analog inputs from uno?
    and 40 button from uno?

    wolrah (unauthenticated)
    Sep 1, 2013

    Fred,

    This is not a complete ready-to-wire package, if you'll note the main loop in the code (the lines near the end starting with "void loop()") just cycles through the buttons turning them all on and off while moving the axes around. It's a demo, for which the user is expected to fill in the blanks with however they prefer to get the input.

    On the plus side the author has done pretty much all the hard work here. You can take example analog/digital I/O code from any "starting Arduino" type guide, toss it in the loop, and call the setButton/clearButton/joyReport functions as appropriate and get something that works in a few minutes.

    Gazz (unauthenticated)
    Sep 7, 2013

    I wonder if the uno can still run other code whilst it is acting as a hid joystick?

    My project is a bus ticket machine, i want the 36 keys on it to send joystick button inputs over usb (using a matrix for the keys) and at the same time i want to run an LCD, so when certain keys are pressed, as well as sending the joystick button input over usb, it also displays text on the LCD,

    Anyone know if this will work?

    darran
    Sep 19, 2013

    Gates, have a look at the earlier posts on the blog for a guide on how to build the hex file: http://hunt.net.nz/users/darran. I'm not sure how you would build it under windows, but you could install virtualbox and then Ubuntu linux (or your favourite flavour linux distro) in a VM, then use the linux tools to build the hex file.

    > And how is it possible to hav 8 analog inputs from uno?
    > and 40 button from uno?

    Pretty much anyway you want. Check the hardware interface guide on the arduino.cc site. You could use the 6 analog input pins and an I2C expander to provide two more analog inputs, or you use a chip like the MCP3008 (http://www.adafruit.com/products/856) to get 8 analog inputs via the SPI bus. For the digital inputs, you can construct a matrix (or grid) using 13 inputs (e.g. 5 x 8). If you're low on input pins, use an expander like the I2C MCP23008 (http://www.adafruit.com/products/593) to add another 8 inputs.

    darran
    Sep 19, 2013

    Gazz, yes you can run other code. You can just use the normal 4-bit Arduino LCD library to drive a text LCD, or an SPI library to drive an TFT graphic LCD, or any of the other displays that the Arduino can handle.

    Stevos758 (unauthenticated)
    Sep 28, 2013

    I just got my firs arduino today. I figured out how to get the hex file loaded and stuff but I am lost with programming. I just need an example of using a hall effect sensor for 1 axis right now. Can anyone help?

    Ewertsp (unauthenticated)
    Oct 1, 2013

    check this out: http://www.jpfiles.com/hardware/uni_stick.pdf
    I'm into this arduino as hid thing too. I already have a good joystick but I need some rudder pedals and maybe a quadrant + button box. This pdf will teach you how to use hall sensors. The rest is simple code.

    Stevos758 (unauthenticated)
    Oct 4, 2013

    I have that part down. I just don't know anything about coding yet! : )

    marcepan (unauthenticated)
    Oct 13, 2013

    It is possible to start this program on arduino due? If yes, please reply. My email marcepan@hackerspace.pl

    Bill (unauthenticated)
    Nov 3, 2013

    Hi Daran,

    Seems you did a really nice work here! But I can't figure out how to control an axis. Could you give me an example of scketch?
    Thanks a lot for your time.

    Shawn (unauthenticated)
    Nov 14, 2013

    Hi Daran
    I tried to expand the button number from 40 to 48 but failed, according to your instructions I changed Descriptors.c JoystickReport[] like this :

    73 0x05, 0x09, /* Usage Page (Button) */
    74 0x19, 1, /* Usage Minimum (Button 1) */
    75 0x29, 48, /* Usage Maximum (Button 48) */
    76 0x15, 0x00, /* Logical Minimum (0) */
    77 0x25, 0x01, /* Logical Maximum (1) */
    78 0x75, 1, /* Report Size (1) */
    79 0x95, 48, /* Report Count (48) */
    80 0x81, 0x02, /* Input (Data, Variable, Absolute) */
    81 0xc0 /* End Collection */

    as you can see the UsageMaximum and Report count has changed to 48,

    Then I changed Arduino-big-joystick.c joyReport declaration like this, just appended a zero at the end:
    92 USB_JoystickReport_Data_t joyReport = { {0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0} };

    I also changed your test sketch to make the board send 48 buttons data to the serial port, I uploaded the sketch and tested the serial output by using HTerm, below is a sample output captured:
    78 05 D8 0E 38 18 98 21 F8 2A 58 34 B8 3D 18 47 FF FF FF FF FF 0F
    the first 16 bytes are the 8 axis, the last 6 bytes are the buttons status.

    I'm using Arduino Mega2560 R3, so I set the ARDUINO_MODEL_PID to 0x0010 in makefile then make the firmware
    and uploaded it by using dfu-programmer, unplug / replug, windows installed the arduino joystick driver.

    But the button and axis doesn't work, in Windows Game controller settings window the button indicator doesn't change, the axis bar doesn't move.
    And I assume the TX indicator light on Mega2560 should always flash indicates there are data send out to USB Host, but it only flashes for the first few seconds after I plug it in, after that it remains unlighted.

    If I revert everything to 40 buttons it works without any problem, please could you shed me some light on this? I have no idea which part I missed.

    Thank you so much.

    Shawn (unauthenticated)
    Nov 14, 2013

    Uh, I think I missed Arduino-joystick.h, USB_JoystickReport_Data_t,
    it should be changed to
    uint8_t button[6];

    Now I encountered a new issue, the button on/off activity is totally out of order.

    Shawn (unauthenticated)
    Nov 15, 2013

    I'm not sure if this is a bug in the firmware but I'm pretty sure when I changed the button count to 48 the button's on/off are actually controlled by the the 6 bytes from 3 axis?! This is weird. I can see the button status changes very clearly by using XPlane button:Adv control panel.

    darran
    Nov 21, 2013

    Hey Shawn, nice one. I'm surprised that Windows will support more than 30 buttons. Could you try testing the joystick using pygame?

    Jason (unauthenticated)
    Nov 23, 2013

    Hi Darran,

    I am totally new to this field, hardware or coding, but how do you make it happen in UNO supporting 16 bits resolution axis? As I know, only Arduino Due has the 12 bits ADS input, other boards are all 10 bits.

    Shawn (unauthenticated)
    Nov 24, 2013

    Hi Darran,
    I think I have figured out the reason that the button status changes randomly after change button number from 40 to 48, it's because the ringbuffer size need to be changed accodringly.

    We have 16 bytes for axis and 6 byte for the 48 buttons, so, there are 22 bytes for the report data,

    /** Size of each ring buffer, in data elements - must be between 1 and 255. */
    47 #define BUFFER_SIZE 110 // 110 = 22 * 5
    48
    49 /** Maximum number of data elements to buffer before forcing a flush.
    50 * Must be less than BUFFER_SIZE
    51 */
    52 #define BUFFER_NEARLY_FULL 88
    //88 = 22 * 4

    Apart from this, I think the endpoint buffer size should be updated accordingly in Descriptor.h

    /** Size in bytes of the Joystick HID reporting IN endpoint. */
    68 #define JOYSTICK_EPSIZE 22

    Windows can support buttons more then 32, but the game controller setting page can only show the first 32 buttons,
    to test more button status, I just use the game, XPlane 10 or others.

    Shawn (unauthenticated)
    Nov 24, 2013

    Hi Jason, It seems that the code just send out the 16 bit numbers for each axis to the USB host ( computer ), but the AD resolution is actually 10 bit. So it's still in 10 bit resolution.

    Shawn (unauthenticated)
    Nov 24, 2013

    Hi Darran, Another question, I tried to use latest LUFA, it compiles success but just won't work. Is there any reason you stick on LUFA 100807? Thanks

    Shawn (unauthenticated)
    Nov 25, 2013

    Tested LUFA version 100807 101122,110528,111009, all works,
    can't make it compile in 120219,
    120730, 130303, 130901 doesn't work.

    Jason (unauthenticated)
    Nov 27, 2013

    Hi all,

    I tried the code in the uno, the demo works well, all buttons lighted and axis moved. When I tried to modified the sketch as below, the 3 axis were not response to the input:

    /* Move all of the axes */
    joyReport.axis[0] = analogRead(A0);
    joyReport.axis[1] = analogRead(A1);
    joyReport.axis[2] = analogRead(A2);

    Anyone can help? how to make the axis and button actually work? Better give some example code.
    Many thanks!

    Jason

    PizzaBoy (unauthenticated)
    Nov 29, 2013

    I am having the same issue as Jason!

    Also I thought the uno read 10bits of precision but had to be sent via 8bits?

    Shawn (unauthenticated)
    Nov 29, 2013

    Hi Jason,
    the HID report specified that the analog range is [-32768, 32767], but analogRead(x) return value's range is [ 0,1023]
    so you need to use map() like this:
    joyReport.axis[0] = map( analogRead(A0), 0, 1023, -32768, 32767 );

    Jason (unauthenticated)
    Dec 1, 2013

    Hi Shawn,

    Thank your answer, I figured it out myself today and resolved the jitter problem by average. It's working now in my rudder pedal.

    Wapsi (unauthenticated)
    Dec 4, 2013

    How can i extend from 8 to 14 axis ? Can someone make a tutorial ? to extend axis or buttons with avr-studio ?
    ;-)
    What files have i to change and how values must new calculated in the source code ?

    Ignacio (unauthenticated)
    Dec 7, 2013

    You could send a photo of the electronic circuit. thanks

    darran
    Dec 13, 2013

    Hi Shawn,

    I used LUFA 100807 because that was the only version of LUFA that was supported at the time. Good to see that some of the newer versions are working.

    Glauco Ramalho (unauthenticated)
    Dec 31, 2013

    Hi Darran!

    Great job, this is exactly what I need. But I'm having a problem here and I can't figure out what is wrong... I downloaded the HEX file, submitted it to my Arduino Mega 2560R3 using your instructions, unplugged and plugged in again and windows recognized it as an Android Joystick... but the buttons simple don't works in games nor in windows controller settings. They are all connected to Analog ports 0-12 and I'm using Windows 7... there are any port mapping I should do in the source code to put it to work?

    Very thanks and have a good new year!

    smartroad (unauthenticated)
    Jan 1, 2014

    I was wondering if it is possible to use this on a Micro (or Leonardo)? Both have USB baked in and the Micro means that I could stash the circuit out of the way in a case easier.

    Glauco Ramalho (unauthenticated)
    Jan 1, 2014

    Nevermind, I'm doing everything wrong here. I'm just figuring out on how to add pushbuttons on Arduino. Anyway, at least after *REALLY* following the instructions my buttons stopped pushing like crazy.

    Now I will have to wait the end of the hollydays to continue my project due to a $.10c resistor! Hehehe!

    Again, very thanks for your hard work!

    Jasper (unauthenticated)
    Jan 28, 2014

    Hi,

    I can't figure out how to program the joystick. I have tried this, it didn't do anything. What do I have to add to make it work?

    #define NUM_BUTTONS 40
    #define NUM_AXES 8

    typedef struct joyReport_t {
    int16_t axis[NUM_AXES];
    uint8_t button[(NUM_BUTTONS+7)/8];
    } joyReport_t;

    joyReport_t joyReport;

    long sensorValue = 0;
    long sensor = 10;

    void setup() {

    Serial.begin(115200);
    delay(200);
    }

    void loop() {

    sensorValue = analogRead(A0);
    sensor = map(sensorValue, 0, 1023, -32768, 32767);
    joyReport.axis[3] = sensor;
    delay(1);
    }

    nick (unauthenticated)
    Feb 13, 2014

    Hi Darran, I'm wanting to make a HID dj controller with a minimum of 24 analogue pots, would it be possible with LUFA and what device class should I thinking about using?

    Gazz (unauthenticated)
    Feb 24, 2014

    I'm useless at this LUFA stuff,
    i managed to put an uno into dfu mode, flash it to works as a joystick, and it works with the test sketch provided... buttons 1-40 turn on in turn, then off in turn, and the axis move up and down, great,

    But i really don't need the axis, just 40 buttons,
    not sure what bits i need to remove and change in the HID descriptor thing to make this happen, i believe i need to make sure that after removing the axis parts, the data packet length matches up with some padding.... but as you can tell, i have no idea what i am doing.

    Can you show me which bits i need to change and how so i can flash my uno to show up as just a 40 button joystick? please.... with cherries on top :)
    or even cheat and point me to a finished hex file with the axis removed and all renumerated or what ever needs doing to it.

    nick, again (unauthenticated)
    Feb 24, 2014

    Hi again Darran, I've been toying with the Unojoy code and have it transmitting a 64 Byte HID report, (48 pots & 128 buttons) I am now wanting to try the same with your code, could you include the .cproj and the like in your source? As I am now somewhat familiar editing and building with AVR studio but makefiles and using VM I have no clue about.

    darran
    Mar 5, 2014

    Hey Nick, I don't have a .cproj file. I assume that's for Windows? I built the firmware using the makefile that is included. It builds on Linux and OS X.

    Carlos (unauthenticated)
    Mar 6, 2014

    Hi darran.

    Congratulations for this great project. I am interested in contact with you my mail about a big project. Mine is carcaes1 AT hotmail.com Cheers.

    Riclamer (unauthenticated)
    Mar 11, 2014

    Hi dears, good tutorial. I updated the demo to my arduino, and all the 8 axes moves. Now i'm interest to read the 8 axes from the ANALOG port of Arduino. I can't find a Sketch with this code. Somebody have this code or a link ? Big Hugs

    Riclamer (unauthenticated)
    Mar 11, 2014

    I Write a code to use with POT in ANALOG PIN, and BUTTON in DIGITAL PIN of Arduino. With this code, is possible to use with Joystik Microsoft SideWinder and others. To use with pot, need to use ground, analog pin, 5v of arduino respective, linke this pic -> http://arduino.cc/en/uploads/Tutorial/joy_sch_480.jpg

    // CODE Arduno Scketch
    /* Arduino USB Joystick HID /
    /* Author: Darran Hunt
    * Edited by RICLAMER 11/03/2014 V 1.0
    *This code, don't use matrix like keyboard to button. Just will use the ports of Arduino.
    *5 pot (axis) and 13 button DIgital (switch to ground) to Arduino UNO,
    *and 15 pot (axis) and 54 button Digital (switch to ground) to Arduino Mega.
    ** Comment all lines "Serial.println" after your tests to increase the performace.
    */

    #define NUM_BUTTONS 13
    #define NUM_AXES 5 // 5 axes, X, Y, Z, etc (UNO)

    typedef struct joyReport_t {
    int16_t axis[NUM_AXES];
    uint8_t button[(NUM_BUTTONS)];
    } joyReport_t;

    joyReport_t joyReport;

    void setup(void);
    void loop(void);
    void setButton(joyReport_t *joy, uint8_t button);
    void clearButton(joyReport_t *joy, uint8_t button);
    void sendJoyReport(joyReport_t *report);

    void setup()
    {

    for( int portId = 01; portId < NUM_BUTTONS; portId ++ )
    {
    pinMode( portId, INPUT_PULLUP);
    }

    Serial.begin(115200);
    delay(200);

    /*================Axis and Button state initialization=======================*/
    for (uint8_t ind=0; ind < NUM_AXES; ind++) {
    joyReport.axis[ind] = 0;
    }

    for (uint8_t ind=0; ind<sizeof(joyReport.button); ind++) {
    joyReport.button[ind] = 0;
    }
    }

    // Send an HID report to the USB interface
    void sendJoyReport(struct joyReport_t *report)
    {
    Serial.write((uint8_t *)report, sizeof(joyReport_t));

    // dump human readable output for debugging
    for (uint8_t ind=0; ind<NUM_AXES; ind++) {
    Serial.print("axis[");
    Serial.print(ind);
    Serial.print("]= ");
    Serial.print(report->axis[ind]);
    Serial.print(" ");
    }
    Serial.println();
    for (uint8_t ind=0; ind<NUM_BUTTONS; ind++) {
    Serial.print("button[");
    Serial.print(ind);
    Serial.print("]= ");
    Serial.print(report->button[ind], HEX);
    Serial.print(" ");
    }
    Serial.println();

    }

    // turn a button on
    void setButton(joyReport_t *joy, uint8_t button)
    {
    uint8_t index = button;
    uint8_t bit = button ;
    //Inform Botton power ON
    Serial.println("POWER BOTTON_");
    Serial.println(button);

    joy->button[index] |= 1 << bit;
    }

    // turn a button off
    void clearButton(joyReport_t *joy, uint8_t button)
    {
    uint8_t index = button;
    uint8_t bit = button ;
    //Inform Botton power OFF
    Serial.println("OFF BOTTON_");
    Serial.println(button);

    joy->button[index] &= ~(1 << bit);
    }

    uint8_t button=0; // current button

    // Read and Set values of button and axis
    void loop()
    { //read the digital port are switch with groun
    if (digitalRead(button)== LOW) {
    setButton(&joyReport, button);
    } else {
    clearButton(&joyReport, button);
    }
    //read the pot in analog port.
    for (uint8_t ind=0; ind< NUM_AXES; ind++) {
    joyReport.axis[ind] = map(analogRead(54+ind), 0, 1023, -32768,32767 );
    }

    sendJoyReport(&joyReport);

    button++;
    if (button >= NUM_BUTTONS ) {
    button = 0;
    }
    delay(100);
    }

    Riclamer (unauthenticated)
    Mar 25, 2014

    Sorry for the last CODE. It's don't run correctly.
    Now i'm sharing the new code to use with POT in ANALOG port, and button Switch in Digital Port.
    I Used Arduino UNO. But is compatible with MEGA, In future i will share a new CODE just to MEGA.
    If you have some problem to test and use this code, please questme. Big Hugs
    Remember, is necessary update firmware with Arduino-big-joystick.hex. I Used Flip to run in Windows.
    ____________________
    /* Arduino USB Joystick HID demo */

    /* Author: Darran Hunt
    * Released into the public domain.
    * Update by RICLAMER in 25/03/2014 to use Analog ports and digital ports
    * This code is to be used with Arduino UNO (6 axis and 13 Button )
    * This code is compatible with Arduino Mega.
    */

    /* INSTALLATION
    Just install POT in each analog port. Using the _GND _Analog _5V Arduino.
    Like this image: http://arduino.cc/en/uploads/Tutorial/joy_sch_480.jpg
    To setup the buttons, just install you prefered button switch under GND and Port Digital 02~13.
    Use Flip to erease and burn this firmware DFU: https://github.com/harlequin-tech/arduino-usb/blob/master/firmwares/Arduino-big-joystick.hex
    I used Arduino R3 with Atmega 16U2.
    */

    #undef DEBUG

    #define NUM_BUTTONS 40 // you don't need to change this value
    #define NUM_AXES 8 // 6 axes to UNO, and 8 to MEGA. If you are using UNO, don't need to change this value.

    typedef struct joyReport_t {
    int16_t axis[NUM_AXES];
    uint8_t button[(NUM_BUTTONS+7)/8]; // 8 buttons per byte
    } joyReport_t;

    joyReport_t joyReport;

    uint8_t btn[12];
    int fulloff = 0;
    void setup(void);
    void loop(void);
    void setButton(joyReport_t *joy, uint8_t button);
    void clearButton(joyReport_t *joy, uint8_t button);
    void sendJoyReport(joyReport_t *report);

    void setup()
    {
    //set pin to input Button
    for( int portId = 02; portId < 13; portId ++ )
    {
    pinMode( portId, INPUT_PULLUP);
    }
    Serial.begin(115200);
    delay(200);

    for (uint8_t ind=0; ind<8; ind++) {
    joyReport.axis[ind] = ind*1000;
    }
    for (uint8_t ind=0; ind<sizeof(joyReport.button); ind++) {
    joyReport.button[ind] = 0;
    }
    }

    // Send an HID report to the USB interface
    void sendJoyReport(struct joyReport_t *report)
    {
    #ifndef DEBUG
    Serial.write((uint8_t *)report, sizeof(joyReport_t));
    #else
    // dump human readable output for debugging
    for (uint8_t ind=0; ind<NUM_AXES; ind++) {
    Serial.print("axis[");
    Serial.print(ind);
    Serial.print("]= ");
    Serial.print(report->axis[ind]);
    Serial.print(" ");
    }
    Serial.println();
    for (uint8_t ind=0; ind<NUM_BUTTONS/8; ind++) {
    Serial.print("button[");
    Serial.print(ind);
    Serial.print("]= ");
    Serial.print(report->button[ind], HEX);
    Serial.print(" ");
    }
    Serial.println();
    #endif
    }

    // turn a button on
    void setButton(joyReport_t *joy, uint8_t button)
    {
    uint8_t index = button/8;
    uint8_t bit = button - 8*index;

    joy->button[index] |= 1 << bit;
    }

    // turn a button off
    void clearButton(joyReport_t *joy, uint8_t button)
    {
    uint8_t index = button/8;
    uint8_t bit = button - 8*index;

    joy->button[index] &= ~(1 << bit);
    }

    /*
    * Read Digital port for Button
    * Read Analog port for axis
    */
    void loop()
    {
    // Create Matriz with value off switch button
    for(int bt = 1; bt < 13; bt ++)
    {
    btn[bt]= digitalRead(bt+1);
    }
    // Power ON button if it is press. buton 17 at 28
    for(int on=01; on < 13; on++)
    {
    if (btn[on] == LOW)
    {
    setButton(&joyReport, on+16);
    // Serial.println("botao ON");
    // Serial.println(on+16);
    }else{
    fulloff = fulloff++;
    } //Power off all Button, if all button are not press
    if(fulloff == 13)
    {
    for(uint8_t cont=0; cont<40; cont++)
    {
    clearButton(&joyReport, cont);
    }
    // Serial.println("Every buttons is off");
    }
    }

    /* Move all of the Analogic axis */
    /* Arduino UNO have only 6 port. Will be necessary set to 0; the not used port */
    /* In this example, i will use just 3 axis. X, Y, Z */
    /* if you will use all 6 analog ports, set axis < 3, to axis < 5 */
    for (uint8_t axis = 0; axis < 3; axis++) {
    joyReport.axis[axis] = map(analogRead(axis), 0, 1023, -32768,32767 );
    }
    //Set to 0; the not used analog port.
    //if you will use all 6 analog ports, exclude the lines, axis[3] at axis [5] */
    joyReport.axis[3] = 0;
    joyReport.axis[4] = 0;
    joyReport.axis[5] = 0;
    joyReport.axis[6] = 0;
    joyReport.axis[7] = 0;
    joyReport.axis[8] = 0;

    //Send Data to HID
    sendJoyReport(&joyReport);

    delay(100);
    fulloff = 0;
    }

    IceMakeR (unauthenticated)
    Mar 30, 2014

    Cans you tell me what to change to use pulse buttons for the joystick? your code sets only buttons on but never goes off!

    Carlos (unauthenticated)
    Apr 1, 2014

    Is possible doing this hid usb with arduino due?

    RICLAMER (unauthenticated)
    Apr 15, 2014

    Hi IceMakeR, I will test the Buttons, and if detect some problem, i post new CODE. OK ? Big Hugs

    p2 (unauthenticated)
    Apr 16, 2014

    Dear Riclamer,

    Thanks for your code.
    I am using Arduino Mega 2560 and I've uploaded the last code provided by you on Mar 25. I am able to connect 3 POTs or Joysticks to pins A0,A1 and A3 ... but it seems other analog pins don't work! also for push button I can use only digital pin 2 ~ 13 !
    Would you please modify the code by adding some rotary encoders and help us to use all the pins on the Arduino Mega boards?

    Thanks.

    RICLAMER (unauthenticated)
    Apr 17, 2014

    Hi p2, it's correct. My code are set to 3 axis. If you want more axis, you need so set this line: for (uint8_t axis = 0; axis < 3; axis++) . It's possible to use at 8 axis. Edit to: for (uint8_t axis = 0; axis < 7; axis++).
    Also need to coment all not used axis. Edit with simbol "//":
    //joyReport.axis[3] = 0;
    //joyReport.axis[4] = 0;
    //joyReport.axis[5] = 0;
    //joyReport.axis[6] = 0;
    //joyReport.axis[7] = 0;
    //joyReport.axis[8] = 0;

    About the buttons, i'm testing and will post a new code.

    Big Hugs

    p2 (unauthenticated)
    Apr 17, 2014

    Dear Riclamer,

    Thanks for your help.
    This is what I understood:
    To let an Analog pin read the input, we have to add "//" at the beginning of the code or we can remove it.
    This is what I have now:

    for (uint8_t axis = 0; axis < 5; axis++) {
    joyReport.axis[axis] = map(analogRead(axis), 0, 1023, -32768,32767 );
    }
    //Set to 0; the not used analog port.
    //if you will use all 6 analog ports, exclude the lines, axis[3] at axis [5] */
    //joyReport.axis[0] = 0;
    //joyReport.axis[1] = 0;
    //joyReport.axis[2] = 0;
    //joyReport.axis[3] = 0;
    joyReport.axis[4] = 0;
    joyReport.axis[5] = 0;
    joyReport.axis[6] = 0;
    joyReport.axis[7] = 0;
    joyReport.axis[8] = 0;

    Now analog pins A0, A1, A2 and A3 are reading 4 Axis and ther are working fine.
    But my question is, since I am using Arduino Mega 2560 and I have 16 Analog pins, is there any method to active other analog or digital pins?
    how about Roraty Encoder?
    That would be nice, If you could add the Rotary Encoder function into your code.
    I have seen someone provided a code including Rotary Encoder like this:

    /*
    Mega2560 R3, digitalPin 22~ 37 used as row0 ~ row 15,
    digital pin 38~53 used as column 0 ~ 15,
    it's a 16 * 16 matrix,

    row 0, 1, 2 ,3 will be used to support 32 rotary encoder
    row 4, 5 will be used to support 16 On - off - On toggle switches,
    note: this application will make the On-off-on toggle switch generate a button push signal when toggle from On to off,
    but this is not implemented yet
    for normal on- on toggle switch or if you don't need this feature then just plug the switch to push button area
    row 6~15 will be used to support push button or normal on-on toggle switch
    */

    #define NUM_BUTTONS 256
    #define NUM_AXES 8 // 8 axes, X, Y, Z, etc

    typedef struct joyReport_t {
    int16_t axis[NUM_AXES];
    uint8_t button[(NUM_BUTTONS+7)/8]; // 8 buttons per byte
    };

    joyReport_t joyReport;

    /*
    RotaryEncoder
    BA BA BA BA
    CW >>> 00 01 11 10 <<< CCW
    */

    /*
    this value sets the threshold for the CW/CCW drift in milliseconds
    any direction drift within this time limit will be ignored, the previous direction will be used.
    */
    byte CWCCWDriftTimeLimit = 60;

    //totally 32 rotary encoders,
    const byte ENCODER_COUNT = 32;

    //store the rotary encoder's AB pin value in last scan
    byte prevEncoderValue[ENCODER_COUNT];

    //store the rotary encoder's last effective CW/ CCW state
    int prevEncoderDirection[ENCODER_COUNT];

    //indicate the current stage of thie encoder
    // for every pulse, left shift stage 2 bits and append the new 2 bits at the lower end,
    // and compare the value with B00011110 and B00101101, then it's CW or CCW,
    // if it's CW or CCW, reset stage to 0
    byte EncoderState[ENCODER_COUNT];

    const byte CWPattern1 = B00011110, CWPattern2 = B01111000, CWPattern3 = B11100001, CWPattern4 = B10000111;
    const byte CCWPattern1 = B00101101, CCWPattern2 = B10110100, CCWPattern3 = B11010010, CCWPattern4 = B01001110;

    //store the rotary encoder's last pulse time, this will be used to remove the drift effect
    unsigned long prevEncoderMillis[ENCODER_COUNT];

    //unsigned long loopTime;

    void setup()
    {
    for( int portId = 22; portId < 38; portId ++ )
    {
    pinMode( portId, OUTPUT );
    }
    for( int portId = 38; portId < 54; portId ++ )
    {
    pinMode( portId, INPUT_PULLUP);
    }
    PORTD = B10000000;
    PORTG = B00000111;
    PORTL = B11111111;
    PORTB = B00001111;

    Serial.begin(115200);
    delay(200);

    /*================axis and key state initialization=======================*/
    for (uint8_t ind=0; ind < NUM_AXES; ind++) {
    joyReport.axis[ind] = 0;
    }

    for (uint8_t ind=0; ind<sizeof(joyReport.button); ind++) {
    joyReport.button[ind] = 0;
    }

    for ( int i = 0; i < ENCODER_COUNT; i++)
    {
    prevEncoderMillis[i] = millis();
    }
    /*---------------------------------------*/

    }

    // Send an HID report to the USB interface
    void sendJoyReport(struct joyReport_t *report)
    {
    //check if time has elapsed enough time since last report sent.
    long static prevMillis;
    if ( millis() - prevMillis >= 10 )
    {
    Serial.write((uint8_t *)report, sizeof(joyReport_t));

    //clear the pulse buttons state
    for( int i = 0; i < 8; i ++ )
    {
    joyReport.button[i] = 0;
    }
    prevMillis = millis();
    }
    }

    void loop()
    {
    //Serial.println( millis() - loopTime );
    //loopTime = millis();

    //scan rotary encoder

    PORTC = 0xFF;
    for ( int rowid = 0; rowid < 4; rowid ++ )
    {
    //turn on the current row
    PORTA = ~( B00000001 << rowid);

    //we must have such a delay so the digital pin output can go LOW steadily,
    //without this delay, the row PIN will not 100% at LOW during yet,
    //so check the first column pin's value will return incorrect result.
    delayMicroseconds(3);

    byte colResult[16];

    //pin 38, PD7
    colResult[0] = (PIND & B10000000 )== 0 ? 1 : 0;
    //pin 39, PG2
    colResult[1] = (PING & B00000100 )== 0 ? 1 : 0;
    //pin 40, PG1
    colResult[2] = (PING & B00000010 )== 0 ? 1 : 0;
    //pin 41, PG0
    colResult[3] = (PING & B00000001 )== 0 ? 1 : 0;

    //pin 42, PL7
    colResult[4] = (PINL & B10000000 )== 0 ? 1 : 0;
    //pin 43, PL6
    colResult[5] = (PINL & B01000000 )== 0 ? 1 : 0;
    //pin 44, PL5
    colResult[6] = (PINL & B00100000 )== 0 ? 1 : 0;
    //pin 45, PL4
    colResult[7] = (PINL & B00010000 )== 0 ? 1 : 0;

    //pin 46, PL3
    colResult[8] = (PINL & B00001000 )== 0 ? 1 : 0;
    //pin 47, PL2
    colResult[9] = (PINL & B00000100 )== 0 ? 1 : 0;
    //pin 48, PL1
    colResult[10] =( PINL & B00000010)== 0 ? 1 : 0;
    //pin 49, PL0
    colResult[11] =( PINL & B00000001)== 0 ? 1 : 0;

    //pin 50, PB3
    colResult[12] =( PINB & B00001000)== 0 ? 1 : 0;
    //pin 51, PB2
    colResult[13] =( PINB & B00000100)== 0 ? 1 : 0;
    //pin 52, PB1
    colResult[14] =( PINB & B00000010)== 0 ? 1 : 0;
    //pin 53, PB0
    colResult[15] =( PINB & B00000001)== 0 ? 1 : 0;

    for ( int colid = 0; colid < 16; colid += 2 )
    {
    byte encoderValue = colResult[colid] << 1 | colResult[colid + 1];
    //byte encoderValue = digitalRead(colid+38) << 1 | digitalRead(colid + 39);
    byte encoderId = rowid * 8 + colid / 2;
    //int encoderState = encoderTable[ prevEncoderValue[ encoderId ] << 2 | encoderValue ];

    if ( encoderValue != prevEncoderValue[encoderId] )
    {
    //we have a "pulse" from rotary encoder
    int direction = 0;
    EncoderState[encoderId] = EncoderState[encoderId] << 2 | encoderValue;

    if (EncoderState[encoderId] == CWPattern1 || EncoderState[encoderId] == CWPattern3 )
    {
    //this is a full CW pattern,
    direction = 1;
    //EncoderState[encoderId] = 0;
    }
    else if (EncoderState[encoderId] == CCWPattern1 || EncoderState[encoderId] == CCWPattern3 )
    {
    //this is a full CCW pattern,
    direction = -1;
    // EncoderState[encoderId] = 0;
    }
    prevEncoderValue[encoderId ] = encoderValue;

    unsigned long timeDiff = millis() - prevEncoderMillis[encoderId];
    if ( timeDiff < CWCCWDriftTimeLimit && direction != 0 )
    {
    // we get a CW/CCW in less then a very short time, let's check if the current direction is identical with the previous direction
    if ( prevEncoderDirection[encoderId] != direction && prevEncoderDirection[encoderId] != 0 )
    {
    //the current direction is different with the previous one, let's use the previous direction instead
    direction = prevEncoderDirection[encoderId];
    }
    }

    if ( direction == 1 )
    {
    //set bit to 10
    joyReport.button[ rowid * 2 + colid / 8 ] |= 0x1 << ( colid % 8 + 1);
    joyReport.button[ rowid * 2 + colid / 8 ] &= ~(0x1 << ( colid % 8 ));
    prevEncoderMillis[ encoderId ] = millis();
    prevEncoderDirection[ encoderId ] = direction;
    }
    else if ( direction == -1 )
    {
    //set bit to 01
    joyReport.button[ rowid * 2 + colid / 8 ] &= ~(0x1 << ( colid % 8 + 1));
    joyReport.button[ rowid * 2 + colid / 8 ] |= 0x1 << ( colid % 8 );
    prevEncoderMillis[ encoderId ] = millis();
    prevEncoderDirection[ encoderId ] = direction;
    }
    }

    }
    }

    //turn off all rows first
    for ( int rowid = 4; rowid < 16; rowid ++ )
    {
    //turn on the current row
    if (rowid < 8)
    {
    PORTA = ~(0x1 << rowid);
    }
    else
    {
    PORTA = 0xFF;
    PORTC = ~(0x1 << (15 - rowid) );
    }
    //we must have such a delay so the digital pin output can go LOW steadily,
    //without this delay, the row PIN will not 100% at LOW during yet,
    //so check the first column pin's value will return incorrect result.
    delayMicroseconds(3);

    byte colResult[16];
    //pin 38, PD7
    colResult[0] = (PIND & B10000000)== 0 ? 1 : 0;
    //pin 39, PG2
    colResult[1] = (PING & B00000100)== 0 ? 1 : 0;
    //pin 40, PG1
    colResult[2] = (PING & B00000010)== 0 ? 1 : 0;
    //pin 41, PG0
    colResult[3] = (PING & B00000001)== 0 ? 1 : 0;

    //pin 42, PL7
    colResult[4] = (PINL & B10000000)== 0 ? 1 : 0;
    //pin 43, PL6
    colResult[5] = (PINL & B01000000)== 0 ? 1 : 0;
    //pin 44, PL5
    colResult[6] = (PINL & B00100000)== 0 ? 1 : 0;
    //pin 45, PL4
    colResult[7] = (PINL & B00010000)== 0 ? 1 : 0;

    //pin 46, PL3
    colResult[8] = (PINL & B00001000)== 0 ? 1 : 0;
    //pin 47, PL2
    colResult[9] = (PINL & B00000100)== 0 ? 1 : 0;
    //pin 48, PL1
    colResult[10] =(PINL & B00000010) == 0 ? 1 : 0;
    //pin 49, PL0
    colResult[11] =(PINL & B00000001) == 0 ? 1 : 0;

    //pin 50, PB3
    colResult[12] =(PINB & B00001000) == 0 ? 1 : 0;
    //pin 51, PB2
    colResult[13] =(PINB & B00000100) == 0 ? 1 : 0;
    //pin 52, PB1
    colResult[14] =(PINB & B00000010) == 0 ? 1 : 0;
    //pin 53, PB0
    colResult[15] =(PINB & B00000001) == 0 ? 1 : 0;

    for ( int colid = 0; colid < 16; colid ++ )
    {
    if ( colResult[ colid ] == 1 )
    //if ( digitalRead( colid + 38 ) == LOW )
    {
    joyReport.button[ rowid * 2 + colid / 8 ] |= (0x1 << ( colid % 8 ));
    }
    else
    {
    joyReport.button[ rowid * 2 + colid / 8 ] &= ~(0x1 << ( colid % 8 ));
    }
    }
    }

    for (uint8_t ind=0; ind< NUM_AXES; ind++) {
    //joyReport.axis[ind] = map(analogRead(54+ind), 0, 1023, -32768,32767 );
    }
    sendJoyReport(&joyReport);
    }

    RICLAMER (unauthenticated)
    Apr 18, 2014

    Hi P2. With firmware arduino_big_joystik.hex, you can use up to 8 axis. Analog Pins 0~7.
    About use encoders, i'm not sure if it's possible to use with big_joystik firmware. I believe this code you post, need another firmware.
    About buttons you can use all digital pins of Arduino Mega. 53 Buttons with my code. I will post in some days new version of code.
    Big Hugs

    RICLAMER (unauthenticated)
    Apr 18, 2014

    Hi ... Today i tested an the buttons are OK !! I created a store to share the code with everybody. Some quest can by post here. https://github.com/RICLAMER/Arduino_Big_Joystik

    p2 (unauthenticated)
    Apr 19, 2014

    Dear Riclamer, Thanks for your efforts. It should be nice, I will check it and let you know.
    Thanks

    p2 (unauthenticated)
    Apr 20, 2014

    Dear Riclamer,

    As I said before, on Mega only pin number 2~13 work as button! and other pins remained unused!
    by the way I could not find any difference between the new code and the previous one.

    Thanks.

    Riclamer (unauthenticated)
    Apr 24, 2014

    Hi p2, the code are made to work with 13 buttons because the limitation of Uno. Now i'm writing a code to use in all digital pin of MEGA

    Big Hugs

    carlos (unauthenticated)
    Apr 25, 2014

    Hi again, is possible upload a firmware .hex like joystick/serial together?

    carlos (unauthenticated)
    May 2, 2014

    One question guys, If i set delay(5) or delay(10), the joystick controller turns crazy.
    What is the minimum delay that is possible to use?

    Nitin (unauthenticated)
    May 11, 2014

    Hi Darran,

    Great job. Have you done any experimentation with force feedback (receiving data from the host to the USB devlice)? USB spec seems to allow that. Do you know if windows generic USB HID driver has support for it?

    Thanks

    NicoHood (unauthenticated)
    May 12, 2014

    Hi,
    i just noticed how easy it is to use dfu and programm your own hid devices. Very nice work darran!

    I tried to compile the files myself and i had some problems. It only works with the lufa version from darrans github page. Okay i dont really care about that but i am wondering how you can update it?

    I tried to rename my arduino but its still not working. I wanted to modify the usbserial firmware and rename the arduino. Even if i change the makefile from uno to mega it always displays a uno with the arduino website. I tried to clean and recompile but its always a uno. what am i doing wrong? For the big joystick example i could easyly rename the joystick!?

    Nitin: I thought of that too but ive no idea how to write the descriptor and how to read data from it. If you found a solution please post it :)

    Dee Jay (unauthenticated)
    Jun 25, 2014

    Hi Riclamer, first of all, big fan of your code, and it totaly works.
    I do however have one problem.
    i can see you say you have tested the buttons and it is okay. i still also have the problem that when i make a connection from GND to one of the digital pins and unplug the connection again the button remains on until the audrino is unplugged and plugged back in.

    am i doing something wrong or do i have to change a part of the code.

    Thanks
    - Dee Jay.

    Giulio (unauthenticated)
    Aug 2, 2014

    Hi guys,

    This post is just amazing.
    At first, somebody could clarify about the root post from Darran how can I set up the physical connection ?
    Just wondering about 40 buttons on Uno.

    Thanks in advance for your help.

    Giulio

    NicoHood (unauthenticated)
    Aug 9, 2014

    I created a project that fully replaces the Arduino Bootloader. You are able to upload sketches and use it as HID. See Project HID on Github: https://github.com/NicoHood/HID

    Jacob (unauthenticated)
    Aug 29, 2014

    Darran, thanks for all the hard work you put in to this!

    Anyone,
    I'm also having button problems. Since I'm horrible at programming all my attempts to solve this have failed. Getting a bit frustrating.
    Problem: Like "Dee Jay" I have sticky buttons. BUT only when I hold one down and attempt to push another one or two at the same time. They all stay active until I release the first one.
    How do I go about fixing this??

    Regards