I had a little trouble figuring out how to make the Arduino act as a keyboard so I decided to share what I've learned by posting an Arduino as HID device tutorial below. Check out the demo and tutorial below.
Demonstration:
Intro:
When I began to research using the Arduino Uno as a keyboard, I was surprised to learn that the chip that handles the USB connection for the Arduino Uno is actually a re-programmable Atmega16U2 or 8U2 (depending on Arduino Uno version) setup as a virtual USB serial device. The Arduino resets whenever a serial connection is initiated. During each reset, the Arduino bootloader checks to see if a new program is being transmitted to it via serial. It then proceeds to the setup function and finally the loop function of the uploaded code. The 16u2 or 8u2 used for USB on the Uno can be programmed to act as several different HIDs that receives commands from the main chip via serial instead of just relaying the serial connection over USB.
Reprogramming Atmega16u2 or 8u2:
Thankfully, the hard work of programming the USB connected chip to act as a HID has been accomplished by others. All you need to do is download the appropriate hex files from this site and flash it to the USB chip using a program from Atmel called FLIP. The only trick is that it needs to be in DFU mode. Just short the two pins identified in the image to enter DFU mode. The Arduino USB connection should re-enumerate as a different device as soon as you short the pins highlighted on the left.
One small word of warning: The downside of turning the Arduino into a human interface device is that the Arduino cannot be programmed using the Arduino IDE unless the USB connected Atmega is programmed to be a serial relay again. This page has more details about DFU mode and a link to the hex file that returns the Arduino to its regular state. The steps for using FLIP are displayed below:
After entering DFU mode (see above), select the USB connection.
Select the HEX file that you want to load. This should be Arduino-keyboard-0.3.hex or Arduino-usbserial-atmega16u2-Uno-Rev3.hex for example. These HEX files are pre-compiled instructions for the microcontroller that runs the USB connection. Thanks to the Arduino community for making this so easy by providing these files!
Once you hit run, these icons should turn green if everything worked. Once this is complete, disconnect and reconnect the Arduino to leave DFU mode and enter normal or HID operation.
That's all there is to it. If you have any question or you have any tips or corrections, please comment.
Arduino Code:
Here's the code I utilized in the demo. Remember, to program the Arduino with the IDE before using FLIP to make the Arduino show up as keyboard.
Thanks to the Arduino community for all the great info I found that made this project so easy! I would like to specifically thank darran from hunt.net.nz for sharing his Arduino as HID hex files used in this project. Please post any comments or questions below.
Using Parallax RFID Tag Reader with Arduino:
The first thing I wanted to do was read in the tag codes via serial. The Arduino site has some great examples on how to use the Parallax RFID reader to do just that.
Arduino as Keyboard / HID:
Intro:
When I began to research using the Arduino Uno as a keyboard, I was surprised to learn that the chip that handles the USB connection for the Arduino Uno is actually a re-programmable Atmega16U2 or 8U2 (depending on Arduino Uno version) setup as a virtual USB serial device. The Arduino resets whenever a serial connection is initiated. During each reset, the Arduino bootloader checks to see if a new program is being transmitted to it via serial. It then proceeds to the setup function and finally the loop function of the uploaded code. The 16u2 or 8u2 used for USB on the Uno can be programmed to act as several different HIDs that receives commands from the main chip via serial instead of just relaying the serial connection over USB.
Reprogramming Atmega16u2 or 8u2:
Thankfully, the hard work of programming the USB connected chip to act as a HID has been accomplished by others. All you need to do is download the appropriate hex files from this site and flash it to the USB chip using a program from Atmel called FLIP. The only trick is that it needs to be in DFU mode. Just short the two pins identified in the image to enter DFU mode. The Arduino USB connection should re-enumerate as a different device as soon as you short the pins highlighted on the left.
One small word of warning: The downside of turning the Arduino into a human interface device is that the Arduino cannot be programmed using the Arduino IDE unless the USB connected Atmega is programmed to be a serial relay again. This page has more details about DFU mode and a link to the hex file that returns the Arduino to its regular state. The steps for using FLIP are displayed below:
After entering DFU mode (see above), select the USB connection.
Select the HEX file that you want to load. This should be Arduino-keyboard-0.3.hex or Arduino-usbserial-atmega16u2-Uno-Rev3.hex for example. These HEX files are pre-compiled instructions for the microcontroller that runs the USB connection. Thanks to the Arduino community for making this so easy by providing these files!
Once you hit run, these icons should turn green if everything worked. Once this is complete, disconnect and reconnect the Arduino to leave DFU mode and enter normal or HID operation.
That's all there is to it. If you have any question or you have any tips or corrections, please comment.
Arduino Code:
Here's the code I utilized in the demo. Remember, to program the Arduino with the IDE before using FLIP to make the Arduino show up as keyboard.
// Reads RFID Tag from Parallax RFID reader using software serial // sends TAG code via serial to ATMEGA16u2 programmed to act as // a USB HID to send the TAG as keyboard presses #include <SoftwareSerial.h> SoftwareSerial mySerial(6, 7); //software serial for rfid reader uint8_t buf[8] = { 0 }; /* Keyboard report buffer */ int read = 0; int val = 0; char code[10]; int bytesread = 0; const int buttonPin = 3; //Activation button long lastDebounceTime = 0; // the last time the output pin was toggled long debounceDelay = 100; // the debounce time; increase if the output flickers // These aren't really necessary but the rest are available // Use this file as a guide for other keystrokes // http://www.usb.org/developers/devclass_docs/Hut1_11.pdf #define KEY_LEFT_CTRL 0x01 #define KEY_LEFT_SHIFT 0x02 #define KEY_RIGHT_CTRL 0x10 #define KEY_RIGHT_SHIFT 0x20 void setup() { Serial.begin(9600); //connection between chips delay(200); mySerial.begin(2400); // set the data rate for the SoftwareSerial port pinMode(2,OUTPUT); // Set digital pin 2 as OUTPUT to connect it to the RFID /ENABLE pin digitalWrite(2, HIGH); // Turn off reader pinMode(buttonPin, INPUT); // Set the input pin for the activation button } // Function to send char[] to computer as keyboard presses // This section is based on http://hunt.net.nz/users/darran/weblog/b3029/Arduino_UNO_Keyboard_HID_version_03.html // Modified to handle numerals void type(char *str) { char *chp = str; delay(100); while (*chp) { if ((*chp >= 'a') && (*chp <= 'z')) { buf[2] = *chp - 'a' + 4; //Converts from char to usb code from HUT1_11.pdf } else if ((*chp >= 'A') && (*chp <= 'Z')) { buf[0] = KEY_LEFT_SHIFT; /* Caps */ buf[2] = *chp - 'A' + 4; //Converts from char to usb code from HUT1_11.pdf } else if ((*chp >= '0') && (*chp <= '9')) { buf[2] = *chp - '0' + 30; //Converts from char to usb code from HUT1_11.pdf } else { switch (*chp) { case ' ': buf[2] = 0x2c; // Space break; default: /* Character not handled. To do: add rest of chars from HUT1_11.pdf */ //buf[2] = 0x37; // Period break; } } Serial.write(buf, 8); // Send keypress buf[0] = 0; buf[2] = 0; Serial.write(buf, 8); // Release key chp++; } } void loop() { // Turns the RFID reader on int reading = digitalRead(buttonPin); // check button status if (((millis() - lastDebounceTime) > debounceDelay ) && (reading == HIGH) && (read==0)) { digitalWrite(2, LOW); // Activate the RFID reader lastDebounceTime = millis(); //Serial.println("Reader on"); read = 1; } // Reads the code if the button has been pressed // Most of this chunk is from http://arduino.cc/playground/Learning/PRFID if((mySerial.available() > 0) && (read==1)) { // if data available from reader if((val = mySerial.read()) == 10) { // check for header bytesread = 0; // reset bytesread while(bytesread<10) { // read 10 digit code if( mySerial.available() > 0) { val = mySerial.read(); if((val == 10)||(val == 13)) { // if header or stop bytes before the 10 digit reading break; // stop reading } code[bytesread] = val; // add the digit bytesread++; // ready to read next digit } } if(bytesread == 10) { // if 10 digit read is complete type(code); // send code via simulated HID } bytesread = 0; digitalWrite(2, HIGH); // deactivate the RFID reader until the button is pressend again read = 0; } } }
Thanks to the Arduino community for all the great info I found that made this project so easy! I would like to specifically thank darran from hunt.net.nz for sharing his Arduino as HID hex files used in this project. Please post any comments or questions below.
Hi, I have something that might interest you: http://www.frank-zhao.com/cache/usnoobie_rfid_keyboard.php
ReplyDeleteThanks for sharing excellent information. Your web-site is very cool.
ReplyDeleteRFID reader is undoubtedly a very interesting and useful technology. Well-written post!
ReplyDeleteGreat site my friend
ReplyDeleteVery nice and helpful information has been given in this article. I like the way you explain the things. Keep posting. Thanks..
ReplyDeleteBest RFID Solutions Provider Company
Interesting and amazing how your post is! It Is Useful and helpful for me That I like it very much, and I am looking forward to Hearing from your next.. rfid tags
ReplyDeleteCan i do this with Arduino UNO R3 Mega328P? Please send me how? robsonandrade@hotmail.com
ReplyDelete