Arduino Uno as a USB HID Interface

I was recently involved with a simple project that involved emulating the functionality of some basic keyboard commands. I decided to try out the Arduino Uno board for the task since I’ve read posts where people used the Arduino for keyboard, mouse, and MIDI device emulation. Unfortunately, many of those posts are very old and aren’t quite right any more. Here are some links to the sites I used to piece together the information in the rest of this post.

These instructions should work for the Arduino Uno R2 and R3. I’m running Ubuntu Linux 12.04. If you are using Windoze or Mac OSX, you can download precompiled versions of whatever programs you need from the previously mentioned links.

1.) Place the Arduino Uno’s ATMega16U2 chip into reset.
This is done by shorting the RESET pin to the GROUND pin on the ATMega16U2’s ICSP header. These are the two pins that are closest to the USB header, as shown in the following image and the video. In some previous posts, it was stated that you have to solder a resistor between two pads on the back of the Arduino, but this isn’t true for the R2 and R3 Arduino Uno version.

The Arduino should be plugged into the computer’s USB port (so that the ATMega16U2 is powered on), then the pins should be shorted for a second or two, and then you need to disconnect the short, so that it can be programmed from the computer.

ATMega16U2's Reset pin shorted to ground.

ATMega16U2’s Reset pin shorted to ground.

2.) Install prerequisites
If you are using Ubuntu Linux, you first need some prerequisites:

$ sudo apt-get install dfu-programmer dfu-util libusb-dev

Download the Atmel USB DFU Programmer (get the tar.gz file) from Source force:
Untar the downloaded file and build it:
$ tar xvf dfu-programmer-0.6.2.tar.gz
$ cd dfu-programmer-0.6.2
$ ./bootstrap
$ ./configure
$ make
$ sudo make install

With this newer version of the dfu-programmer, you don’t have to worry about patching it for the ATMega16U2, it has already been applied to the newer source code.

3.) Program the ATMega16U2 chip with dfu-programmer
$ sudo dfu-programmer atmega16u2 erase
$ sudo dfu-programmer atmega16u2 flash --debug 1 Arduino-usbserial-uno.hex
$ sudo dfu-programmer atmega16u2 reset

Notice, the main difference in these commands from those mentioned in the previously referenced posts was that I used “atmega16u2” instead of “at90usb82.” To simplify this process, I created a simple bash script that calls these three commands in order and takes a path to the hex file as an argument. You can download this script as well as the usb-serial and usb-keyboard hex files from my github project at:

You would call the program script by cd’ing to the scripts directory and executing the script with a single argument that consists of the path to the hex file to be programed. For example:
$ cd /path/to/scripts/
$ sudo ./ Arduino-usbserial-uno.hex

If the commands return the error string, “no device present,” that means you either didn’t reset the ATMega16U2 correctly, or you are using an old version of dfu-programmer (install it using step 2 above).

4.) Work flow
Now that you can program the ATMega16U2 chip, you can get to work on that USB HID interface. Your work flow will consist of:

  1. Program the ATMega16U2 with Arduino-usbserial-uno.hex. (reset ATMega16U2, then, sudo ./ Arduino-usbserial-uno.hex).
  2. Plug cycle the Arduino.
  3. Program the Arduino’s main Atmel chip with the standard Arduino IDE.
  4. Plug cycle the Arduino.
  5. Program the ATMega16U2 with Arduino-keyboard-0.3.hex. (reset ATMega16U2, then, sudo ./ Arduino-keyboard-0.3.hex).
  6. Test, then go to step 1.

5.) Simple Arduino HID USB Program
The following sketch will simply send the USB keyboard scan code for “R” from the Arduino (acting as an HID USB device) to the computer every five seconds.

/* Arduino USB HID Keyboard Demo
* Random Key/Random Delay
uint8_t buf[8] = {
0 }; /* Keyboard report buffer */

void setup()

void loop()

buf[0] = 0;
buf[2] = 0x15; // letter R
Serial.write(buf, 8);

void releaseKey()
buf[0] = 0;
buf[2] = 0;
Serial.write(buf, 8); // Release key

If you want to add the ability to send key strokes that make use of the CTRL or ALT keys, you modify the character at buf[0]. For example, to send the keystroke, CTRL+R, you would set buf[0] to 0x01 and buf[2] to 0x15. You can find out more about the USB HID scan codes in the following table:

Here is a quick video of me testing the CTRL+R functionality with an attached push button.