Keyboards

Arduino USB HID Keyboard – MitchTech

Posted by michael on Jun 24, 2012 in Arduino, Tutorials, Ubuntu | 113 comments

Turn your Arduino UNO into a USB HID keyboard, and make buttons that do whatever you want. Make it a useful tool, with new buttons for Cut/Copy/Paste or Volume+/Volume-/Mute, or annoy your friends and colleagues by setting the keyboard to perform random keypress after random delays!

The USB HID keyboard conforms to the standard USB specification, so is functional on all modern operating systems.  All this is made possible by the use of the Arduino Device Firmware Update (DFU) function.

Arduino Device Firmware Update (DFU)

The Atmega8U2 chip on the Arduino UNO can be programmed directly using the special USB protocol called Device Firmware Update (DFU). This is completely independant of the ‘normal’ method of flashing sketches to the board using the Arduino IDE.

This process is normally used to update the firmware to a more recent version, as explained in the offical Arduino guide, Updating the Atmega8U2 on an Uno or Mega2560 using DFU. Note: If your board is NOT an Arduino UNO SMD you’ll need to solder a 10k resistor (Brown-black-orange) at the back of your board as shown on the Arduino site.

However, in addition to the ability to flash standard USB Serial firmwares, we can also flash alternative firmwares as well. This allows the device to be recognized as many other device types, including keyboard, mouse, joystick, midi device, etc. This is made possible in part to the wonderful open source LUFA (Lightweight USB Framework for AVRs)  USB stack, and keyboard HID firmware from Darran.

In this demonstration, we will flash generic USB HID keyboard firmware. The USB HID protocol provides manufactures the generic specifications to interact with nearly every operating system in existence. For more info, check out the USB HID Spec sheet.

Before you start, install the required packages. On Ubuntu and Debain systems, in a terminal run:

sudo apt-get install dfu-programmer dfu-util

For Windows and Mac instructions to install the dfu-programmer tool, consult the official Arduino DFU documentation.

Then download these two firmware files:

Arduino-usbserial.hex
Arduino-keyboard-0.3.hex

The first step is to make sure you are able to flash the standard arduino firmware. This will confirm that the programmer and the environment are both functional. NOTE: There is no chance of ‘bricking’ the device using this method. The Arduino bootloader firmware can always be updated using the DFU protocol!

sudo dfu-programmer at90usb82 erase sudo dfu-programmer at90usb82 flash –debug 1 Arduino-usbserial.hex sudo dfu-programmer at90usb82 reset

Plug cycle the Arduino, then open the Arduino IDE and ensure that you can still upload a sketch. Assuming everything flashes normally, we can move forward with flashing the HID keyboard firmware.

sudo dfu-programmer at90usb82 erase sudo dfu-programmer at90usb82 flash –debug 1 Arduino-keyboard-0.3.hex sudo dfu-programmer at90usb82 reset

NOTE: The Arduino can only be flashed with skectches through the Adruino IDE if the Arduino-usbserial.hex bootloader is active. So, to develop a USB HID device, the process becomes:

Flash Arduino-usbserial.hex bootloader with dfu-programmer (erase/flash/reset)
Plug cycle the Arduino
Flash firmware sketch using Arduino IDE
Plug cycle the Arduino
Flash Arduino-keyboard-0.3.hex bootloader with dfu-programmer (erase/flash/reset)
Test and repeat

Now that you understand how the process works, you can try out some of these keyboard samples. The easiest example is the random keypress with random delays, since it doesn’t require any components connected to the Arduino.

Random Key/Random Delay

/* Arduino USB HID Keyboard Demo * Random Key/Random Delay */ uint8_t buf[8] = { 0 }; /* Keyboard report buffer */ void setup() { Serial.begin(9600); randomSeed(analogRead(0)); delay(200); } void loop() { int randomChar = random(4, 130); long randomDelay = random(1000, 10000); delay(randomDelay); buf[2] = randomChar; // Random character Serial.write(buf, 8); // Send keypress releaseKey(); } void releaseKey() { buf[0] = 0; buf[2] = 0; Serial.write(buf, 8); // Release key }

The following two examples both use three buttons connected to the Arduino. The code can easily be changed to make the buttons perform other actions, by consulting the mapping tables in the USB HID documentation.  Here is a diagram of the circuit, (created with Fritzing):

 

Volume+/Volume-/Mute

/* Arduino USB Keyboard HID demo * Volume+/Volume-/Mute keys */ uint8_t buf[8] = { 0 }; /* Keyboard report buffer */ #define PIN_VOLUME_UP 5 #define PIN_VOLUME_DOWN 6 #define PIN_MUTE 7 int state = 1; void setup() { Serial.begin(9600); pinMode(PIN_VOLUME_UP, INPUT); pinMode(PIN_VOLUME_DOWN, INPUT); pinMode(PIN_MUTE, INPUT); // enable internal pull-ups digitalWrite(PIN_VOLUME_UP, 1); digitalWrite(PIN_VOLUME_DOWN, 1); digitalWrite(PIN_MUTE, 1); delay(200); } void loop() { state = digitalRead(PIN_VOLUME_UP); if (state != 1) { buf[2] = 128; // Volume up key Serial.write(buf, 8); // Send keypress releaseKey(); } state = digitalRead(PIN_VOLUME_DOWN); if (state != 1) { buf[2] = 129; // Volume down key Serial.write(buf, 8); // Send keypress releaseKey(); } state = digitalRead(PIN_MUTE); if (state != 1) { buf[2] = 127; // Mute key Serial.write(buf, 8); // Send keypress releaseKey(); } } void releaseKey() { buf[0] = 0; buf[2] = 0; Serial.write(buf, 8); // Release key }

Cut/Copy/Paste

/* Arduino USB Keyboard HID demo * Cut/Copy/Paste Keys */ #define KEY_LEFT_CTRL 0x01 #define KEY_LEFT_SHIFT 0x02 #define KEY_RIGHT_CTRL 0x10 #define KEY_RIGHT_SHIFT 0x20 uint8_t buf[8] = { 0 }; /* Keyboard report buffer */ #define PIN_COPY 5 #define PIN_CUT 6 #define PIN_PASTE 7 int state = 1; void setup() { Serial.begin(9600); pinMode(PIN_COPY, INPUT); pinMode(PIN_CUT, INPUT); pinMode(PIN_PASTE, INPUT); // Enable internal pull-ups digitalWrite(PIN_COPY, 1); digitalWrite(PIN_CUT, 1); digitalWrite(PIN_PASTE, 1); delay(200); } void loop() { state = digitalRead(PIN_CUT); if (state != 1) { buf[0] = KEY_LEFT_CTRL; // Ctrl buf[2] = 27; // Letter X // buf[2] = 123; // Cut key: Less portable Serial.write(buf, 8); // Ssend keypress releaseKey(); } state = digitalRead(PIN_COPY); if (state != 1) { buf[0] = KEY_LEFT_CTRL; // Ctrl buf[2] = 6; // Letter C // buf[2] = 124; // Copy key: Less portable Serial.write(buf, 8); // Send keypress releaseKey(); } state = digitalRead(PIN_PASTE); if (state != 1) { buf[0] = KEY_LEFT_CTRL; // Ctrl buf[2] = 25; // Letter V // buf[2] = 125; // Paste key: Less portable Serial.write(buf, 8); // Send keypress releaseKey(); } } void releaseKey() { buf[0] = 0; buf[2] = 0; Serial.write(buf, 8); // Release key delay(500); }

 

Source

You may also like...

Leave a Reply

Your email address will not be published. Required fields are marked *