An addition of Human Input Device Class support to USB Host Shield library 2.0, announced several days ago allows using powerful and inexpensive input devices with USB interface in Arduino projects. Sample sketches demonstrating sending and receiving data to one of the most useful HID device types – boot keyboard/mouse, has been released along with the library. The beauty of boot protocol lies in the simplicity of device report – a data packet containing information about button presses and mouse movements. However, samples were designed to demonstrate all features of the class and because of that, they are somewhat heavy. In real-life applications, it is often not necessary to implement each and every virtual function – only what is needed. In today’s article I will show practical application of HID boot device building a simple gadget.
Originally, HID boot protocol was meant to be used with keyboards and mice. When USB became popular, other keyboard-emulating devices, such as barcode scanners and magnetic card readers have been migrated from PS/2 standard to USB while keeping their keyboard-emulating property. As a result, many modern “not-so-human” input devices behave exactly like a keyboard including boot protocol support. A gadget that I demonstrate today is portable autonomous barcode scanner built using Arduino board, USB Host shield, handheld USB barcode scanner and LCD display (see title picture). The operation is simple – when handheld scanner button is pressed, it scans the barcode and sends it to Arduino symbol by symbol. Arduino then outputs these symbols on LCD display. LCD is erased before outputting each new barcode by tracking time between arrival of two consecutive symbols. To keep the code simple, I intentionally did not implement any data processing, however, since Arduino sketch for the gadget compiles in just a little over 14K, there is plenty of memory space left for expansion.
Let’s talk a little bit about necessary parts. First of all, we’ll need Arduino board and USB Host Shield. I use standard 16×2 HD44780-compatible LCD display, connected similarly to one in Arduino LiquidCrystal tutorial. Since USB Host shield uses pins 11 and 12 to interface to Arduino, I had to move corrsponding LCD signals to pins 6 and 7; the rest of the connections shall be made exactly like in the tutorial. Lastly, we need compatible handheld barcode scanner. The best place to search for one is eBay; look for phrases “no driver required” and “USB HID device” in product description.
To make sure a device is indeed a boot keyboard, take a look at device descriptors using USB_Desc example from USB Host library – a sample output is given below. Class, Subclass, Protocol in interface descriptor (lines 29-31) should be 03, 01, 01. If Subclass is zero, boot protocol is not supported. Non-boot scanner is still useful but accessing it is going to be slightly more complicated. I will cover HID report protocol in one of the next articles.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 | Device descriptor: Descriptor Length: 12 Descriptor type: 01 USB version: 0100 Device class: 00 Device Subclass: 00 Device Protocol: 00 Max.packet size: 08 Vendor ID: 04B4 Product ID: 0100 Revision ID: 0100 Mfg.string index: 01 Prod.string index: 02 Serial number index: 00 Number of conf.: 01 Configuration descriptor: Total length: 0022 Num.intf: 01 Conf.value: 01 Conf.string: 04 Attr.: A0 Max.pwr: 64 Interface descriptor: Intf.number: 00 Alt.: 00 Endpoints: 01 Intf. Class: 03 Intf. Subclass: 01 Intf. Protocol: 01 Intf.string: 05 Unknown descriptor: Length: 09 Type: 21 Contents: 00011001223F000705 Endpoint descriptor: Endpoint address: 81 Attr.: 03 Max.pkt size: 0008 Polling interval: 0A |
Below is the sketch which needs to be compiled and loaded into Arduino. I wrote it by copying the keyboard example, taking out all unnecessary code and adding LCD support. The sketch can be copied from this page and pasted to Arduino IDE window. An explanation of key pieces is given after the listing.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 | /* Portable barcode scanner. Uses USB HID barcode scanner, Arduino Board, USB Host Shield and HD44780-compatible LCD display The circuit: * LCD RS pin to digital pin 7 * LCD Enable pin to digital pin 6 * LCD D4 pin to digital pin 5 * LCD D5 pin to digital pin 4 * LCD D6 pin to digital pin 3 * LCD D7 pin to digital pin 2 * LCD R/W pin to ground * 10K resistor: * ends to +5V and ground * wiper to LCD VO pin (pin 3) */ #include <LiquidCrystal.h> #include <avr/pgmspace.h> #include <avrpins.h> #include <max3421e.h> #include <usbhost.h> #include <usb_ch9.h> #include <Usb.h> #include <usbhub.h> #include <avr/pgmspace.h> #include <address.h> #include <hidboot.h> #include <printhex.h> #include <message.h> #include <hexdump.h> #include <parsetools.h> #define DISPLAY_WIDTH 16 // initialize the LCD library with the numbers of the interface pins LiquidCrystal lcd(7, 6, 5, 4, 3, 2); USB Usb; //USBHub Hub(&Usb); HIDBoot<HID_PROTOCOL_KEYBOARD> Keyboard(&Usb); class KbdRptParser : public KeyboardReportParser { protected: virtual void OnKeyDown (uint8_t mod, uint8_t key); virtual void OnKeyPressed(uint8_t key); }; void KbdRptParser::OnKeyDown(uint8_t mod, uint8_t key) { uint8_t c = OemToAscii(mod, key); if (c) OnKeyPressed(c); } /* what to do when symbol arrives */ void KbdRptParser::OnKeyPressed(uint8_t key) { static uint32_t next_time = 0; //watchdog static uint8_t current_cursor = 0; //tracks current cursor position if( millis() > next_time ) { lcd.clear(); current_cursor = 0; delay( 5 ); //LCD-specific lcd.setCursor( 0,0 ); }//if( millis() > next_time ... next_time = millis() + 200; //reset watchdog if( current_cursor++ == ( DISPLAY_WIDTH + 1 )) { //switch to second line if cursor outside the screen lcd.setCursor( 0,1 ); } Serial.println( key ); lcd.print( key ); }; KbdRptParser Prs; void setup() { Serial.begin( 115200 ); Serial.println("Start"); if (Usb.Init() == -1) { Serial.println("OSC did not start."); } delay( 200 ); Keyboard.SetReportParser(0, (HIDReportParser*)&Prs); // set up the LCD's number of columns and rows: lcd.begin(DISPLAY_WIDTH, 2); lcd.clear(); lcd.noAutoscroll(); lcd.print("Ready"); delay( 200 ); } void loop() { Usb.Task(); } |
- Lines 5-15. This comment contains information about necessary LCD connections
- Lines 46-52.
KeyboardReportParser
declaration. Compare with keyboard example. Here, we only needOnKeyDown()
andOnKeyPressed()
methods. - Lines 54-60.
OnKeyDown()
callback definition. When a keyboard key is pressed, it receives scan code of this key plus modifiers (Ctrl, Alt, Shift). Since our LCD takes ASCII codes the callback performs scan code to ASCII conversion and then callsOnKeyPressed()
- Line 63.
OnKeyPressed()
definition - Lines 68-73.Clears the display before outputting first symbol of new barcode, i.e., if pause between symbols is larger than 200ms. Note delay in line 71 – my display is old and slow and unless I wait a little, it won’t print the first symbol of the sequence. Newer displays should work fine without it
- Lines 81-82. The output. A symbol is sent to serial terminal and LCD
The rest of the sketch contains standard initialization of USB Host
and Liquidcrystal
libraries, as well as periodic calling of Usb.Task()
, from which keyboard callbacks are called.
Lastly, a bonus material for those who managed to keep reading the article to this place. Since the sketch assumes HID boot device, it can be used with many different devices. For example, it is possible to produce an output using ordinary keyboard (due to watchdod, in order to get more than one symbol on the LCD display, you’d have to type pretty fast). Also, the same setup makes pretty good RFID reader – many inexpensive USB readers in 125KHz class are implemented as HID boot keyboards. Picture on the left shows one such device connected to Arduino. It also shows a way of providing power via Arduino USB port using portable USB charger. RFID cloning, anyone?
dear sir ,i will hope to buy this barcoder reader. it ca use to this project.pls reply me.
http://www.ebay.com/itm/New-USB-Black-XYL-820-Laser-Barcode-Scanner-Bar-Code-Reader-Decoder-POS-/150709100096?pt=LH_DefaultDomain_0&hash=item2316f65e40
I need a little help.First your code is work pretty well for me.My promblem is how I use a data from barcode reader to a get data from database.I connected a a usb shield and ethernet shield together. It’s not show a data after i scan barcode .How can i modify to make it work.
/*
Portable barcode scanner. Uses USB HID barcode scanner, Arduino Board, USB Host Shield and HD44780-compatible LCD display
The circuit:
* LCD RS pin to digital pin 7
* LCD Enable pin to digital pin 6
* LCD D4 pin to digital pin 5
* LCD D5 pin to digital pin 4
* LCD D6 pin to digital pin 3
* LCD D7 pin to digital pin 2
* LCD R/W pin to ground
* 10K resistor:
* ends to +5V and ground
* wiper to LCD VO pin (pin 3)
*Usb shield SS change to pin 4 // CHANGED Usb.h
*/
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define DISPLAY_WIDTH 16
// initialize the LCD library with the numbers of the interface pins
LiquidCrystal lcd(8, 7, 5, 6, 3, 2);
byte mac[] = { 0x3E, 0xBA, 0x7F, 0x9F, 0x44, 0xED };
byte ip[] = { 10,0,0,4 };
byte gateway[] = {10,0,0,254};
byte subnet[] ={255,255,255,0};
byte server[] = {10,0,0,100};
Client client(server, 80);
USB Usb;
//USBHub Hub(&Usb);
HIDBoot Keyboard(&Usb);
class KbdRptParser : public KeyboardReportParser
{
protected:
virtual void OnKeyDown (uint8_t mod, uint8_t key);
virtual void OnKeyPressed(uint8_t key);
};
void KbdRptParser::OnKeyDown(uint8_t mod, uint8_t key)
{
uint8_t c = OemToAscii(mod, key);
if (c)
OnKeyPressed(c);
}
/* what to do when symbol arrives */
void KbdRptParser::OnKeyPressed(uint8_t key)
{
static uint32_t next_time = 0; //watchdog
static uint8_t current_cursor = 0; //tracks current cursor position
if( millis() > next_time ) {
lcd.clear();
current_cursor = 0;
delay( 5 ); //LCD-specific
lcd.setCursor( 0,0 );
}//if( millis() > next_time …
next_time = millis() + 200; //reset watchdog
if( current_cursor++ == ( DISPLAY_WIDTH + 1 )) { //switch to second line if cursor outside the screen
lcd.setCursor( 0,1 );
}
Serial.println( key );
lcd.print( key );
};
KbdRptParser Prs;
void setup()
{
if (Usb.Init() == -1) {
Serial.println(“OSC did not start.”);
}
delay( 200 );
Ethernet.begin(mac, ip, gateway, subnet); // connect to network
Serial.begin( 9600 );
Serial.println(“Start”);
if (client.connect())
{
lcd.print(“connected”);
Serial.println(“connected”);
// Make a HTTP request:
client.println(“GET /test/connect_test.php?key=”);
client.println();
}
else
{
lcd.print(“connection fail”);
Serial.println(“connection fail”);
}
delay( 200 );
Keyboard.SetReportParser(0, (HIDReportParser*)&Prs);
// set up the LCD’s number of columns and rows:
lcd.begin(20, 4);
lcd.clear();
lcd.noAutoscroll();
lcd.print(“Ready”);
}
void loop()
{
if (client.available()) {
while (client.connected()){
Usb.Task();
}
char c = client.read();
Serial.print(c);
}
}
if (!client.connected()) {
Serial.println();
Serial.println(“disconnecting.”);
Serial.println(“==================================”);
Serial.println(“”);
client.stop();
for(;;);
}
}
Tommy,I am trying to do the same thing as you. Did you ever get this solved?
Tommy, Brandon,
Hi, I’m completely new to Arduino and I already have a project for work that seems to be the same as yours, I know I need the Arduino board and 3 shields, Ethernet shield, LCD shield, USB host shield, but I’m still uncertain about what Arduino board to buy.
Any advice is greatly appreciated
Thanks
Hello Brandon,
we are trying to do the same as you wrote: Arduino + Ethernet shield + USB Host shield, the problem is when trying to use Ethernet after USB communication. Did you solve the problem already?
I’ve made all the connection and I’m about to verify and upload your code using Arduino 1.0, but I’m getting an error saying “USB does not name a type”. How can I solve this?
could you tell me please how did you solve it ? i already have the same problem
Hi there. I solved my previous problem myself, but here comes a new one. I’m using a quickscan QS6500 as a scanner and I’m unable to scan any barcode. I dont knw if it is a interfacing problem. Can anyone help me please?
Great project…!
Sir, i want to know how to connect 4 pcs USB barcode reader using USB Hub with this project, wich programming code we have to change
Thank you for your advance
I answered this question not too long ago, Look in the comments to this post -> https://www.circuitsathome.com/mcu/hid-support-for-usb-host-shield-library-2-0-released
I’ve made all the connection and I’m about to verify and upload your code using Arduino 1.0, but I’m getting an error saying “USB does not name a type”. How can I solve this?
I am using a Arduino UNO, the USB host shield from circuits@home and a TFT LCD from adafruit. The code provided works fine and the barcode gets outputted on the serial monitor of arduino but it doesnt output on the TFT LCD after making the changes in the code related to display on LCD. The problem is that the LCD requires pins 11 and 12 of arduino which is being used by the USB host shield. Is there a way I can remap these pins 11 and 12 to some other pin. What changes do I make in the code or in any other libraries provided?
Please reply at the earliest. Will greatly appreciate it.
do you have a link to a display you’re using?
http://www.adafruit.com/products/376
Its a TFT LCD we found on adafruit.
You can’t use pins 11,12 as they are used by SPI and can’t be relocated. You either need one of the big Arduinos where pins 11,12 are not tied to SPI or modify Adafruit LCD library to use other pins.
can you give us a basic idea of how pins are remapped? That way I can try to remap in the TFT LCD
I have a problem with a circuit for barcode reader, and my problem is that the reader does not light if not connected to the USB if I try to connect to VCC does not turn … using the arduino is removed that problem?
Hi there,
I’m struggling to get the full barcode value when using this sketch. I’ve commented out the LCD information as I do not have one, but I want to output the information to the serial monitor.
My barcode reader seems to fail at the setup stage – the SetIdle fails with a failure value of 5. If I comment out the SetIdle check then the barcode reader completes the setup.
Unfortunately when a successful barcode is read the keypressed class is not called for every character in the barcode (am I right to assume it does?) I’ve added a counter to the keypressed event and it’s called a maximum of 3 times. Do you think that the SetIdle failure may have something to do with it? My background is VB, so I’m trying to work my way through C++ but am pretty well stuck.
I’m using an Arduino Uno with a Sparkfun USB Host shield. I’ve made the jumper reset fix suggested by other users on this site and have managed to get a USB keyboard to output key data correctly. However if I use a USB mouse it doesn’t output the coordinate information regularly, but every now and again.
I’ve powered the Arduino from the Vin pin, and the barcode fails to power up if I leave it to USB power only, so I don’t think it is power related.
Any help you are able to provide will be much appreciated.
Sparkfun shield is not compatible with my code. The differences are fundamental – you can make it pass initialization but it will break later.
Thanks for the update Oleg. Do you have any details of a UK distributor for your USB host shield?
The closest one to you is lipoly.de in Germany.
Hi Oleg,
I’m getting the following output from the USB Desc example program
Start
01
—
Device descriptor:
Descriptor Length: 12
Descriptor type: 01
USB version: 0110
Device class: 00
Device Subclass: 00
Device Protocol: 00
Max.packet size: 10
Vendor ID: 0C2E
Product ID: 0200
Revision ID: 5232
Mfg.string index: 01
Prod.string index: 02
Serial number index: 00
Number of conf.: 01
Configuration descriptor:
Total length: 0022
Num.intf: 01
Conf.value: 01
Conf.string: 04
Attr.: 80
Max.pwr: E1
Interface descriptor:
Intf.number: 00
Alt.: 00
Endpoints: 01
Intf. Class: 03
Intf. Subclass: 01
Intf. Protocol: 01
Intf.string: 00
Unknown descriptor:
Length: 09
Type: 21
Contents: 11010001223F000705
Endpoint descriptor:
Endpoint address: 81
Attr.: 03
Max.pkt size: 0010
Polling interval: 0A
Addr:1(0.0.1)
I’m trying to read from a barcode scanner(Metrologic MS1690 106) which runs fine on a computer but when using the barcode example program it doesnt call the onkeydown function ever when reading a valid barcode. I know the host shield actually receives the scanned code because my barcode scanner has a transmit LED that turns off once the code has been transmitted.
The second time however when i scan a valid code the host shield seems to not read in the data anymore.
This is my output when i run the barcode example (I took out all the LCD since i don’t need it).
Start
BM Init
Addr:1
SetProto:5
From this point on usb.task() keeps looping but onkeydown does never get called nor is anything getting printed to the serial monitor afterwards.
Thanks!
SetProto: 5 means it stalls when usb host tries to set device to boot protocol. This is strange since interface descriptor shows boot protocol is supported. Try to read this device as a normal report protocol HID device -> https://github.com/felis/USB_Host_Shield_2.0/tree/master/examples/HID/USBHID_desc
Here you go!
Thanks,
Start
HU Init
Addr:1
NC:1
Cnf:1
HU configured
0000: 05 01 09 06 A1 01 05 07 19 E0 29 E7 15 00 25 01
0010: 75 01 95 08 81 02 95 01 75 08 81 01 95 05 75 01
0020: 05 08 19 01 29 05 91 02 95 01 75 03 91 01 95 06
0030: 75 08 15 00 25 65 05 07 19 00 29 65 81 00 C0
Usage Page Gen Desktop Ctrls(01)
Usage Keypad
Collection Application
Usage Page Kbrd/Keypad(07)
Usage Min(E0)
Usage Max(E7)
Logical Min(00)
Logical Max(01)
Report Size(01)
Report Count(08)
Input(00000010)
Report Count(01)
Report Size(08)
Input(00000001)
Report Count(05)
Report Size(01)
Usage Page LEDs(08)
Usage Min(01)
Usage Max(05)
Output(00000010)
Report Count(01)
Report Size(03)
Output(00000001)
Report Count(06)
Report Size(08)
Logical Min(00)
Logical Max(65)
Usage Page Kbrd/Keypad(07)
Usage Min(00)
Usage Max(65)
Input(00000000)
End Collection
Have you tried to scan? After outputting report descriptor the sketch should print HID report generated by device.
Buf: 0200000000000000
GetReportDescr-2: 04
Buf: 0200270000000000
GetReportDescr-2: 04
Buf: 0200000000000000
GetReportDescr-2: 04
Buf: 02001F0000000000
GetReportDescr-2: 04
Buf: 0200000000000000
GetReportDescr-2: 04
Buf: 02001E0000000000
GetReportDescr-2: 04
Buf: 0200000000000000
GetReportDescr-2: 04
Buf: 02001F0000000000
GetReportDescr-2: 04
Buf: 0200000000000000
GetReportDescr-2: 04
Buf: 0200270000000000
GetReportDescr-2: 04
Buf: 0200000000000000
GetReportDescr-2: 04
Buf: 0200270000000000
GetReportDescr-2: 04
Buf: 0200000000000000
GetReportDescr-2: 04
Buf: 02001E0000000000
GetReportDescr-2: 04
Buf: 0200000000000000
GetReportDescr-2: 04
Buf: 0200240000000000
GetReportDescr-2: 04
Buf: 0200000000000000
GetReportDescr-2: 04
Buf: 02001E0000000000
GetReportDescr-2: 04
Buf: 0200000000000000
GetReportDescr-2: 04
Buf: 0200270000000000
GetReportDescr-2: 04
Buf: 0200000000000000
GetReportDescr-2: 04
Buf: 0200200000000000
GetReportDescr-2: 04
Buf: 0200000000000000
GetReportDescr-2: 04
Buf: 02001E0000000000
GetReportDescr-2: 04
Buf: 0200000000000000
GetReportDescr-2: 04
Buf: 0000000000000000
GetReportDescr-2: 04
Buf: 0000280000000000
GetReportDescr-2: 04
Buf: 0000000000000000
Keypad(00)(00)(00)(00)(00)(00)(00)(00)
(00)
(00)(00)(00)(00)(00)(00)
This is your report. Just read it like explained here -> https://www.circuitsathome.com/mcu/usb/visualizing-hid-device-reports-and-report-descriptors and couple of joystick-related articles. Yours should be easier than a joystick since it is just a keyboard and all controls are the same. You can read this buffer directly as explained here -> https://www.circuitsathome.com/mcu/how-to-drive-usb-keyboard-from-arduino
Is there also a file in the library that explains the error codes?
It depends on the error. There are many sources of errors and codes are also different. Stall (05) can be found in MAX3421E programmer’s guide -> http://www.hdl.co.jp/ftpdata/utl-001/AN3785.pdf
Alright thank you, i will look over it.
Hi,
Out of curiosity i took out the following code where it got stuck and it seems to run just fine now.
/*
rcode = SetProtocol(bIfaceNum, HID_BOOT_PROTOCOL);
if (rcode)
goto FailSetProtocol;
*/
I’ve just been reading into it so I’m not sure how trivial that part of the boot protocol is. It goes to STALL in the handshake procedure indicating an impossible transfer. However after that it seems to acknowledge after receiving data. I know it is a dirty fix but I’m still looking into it.
Thanks for pointing me in the right direction!
regards,
Start
HU Init
Addr:1
NC:1
Cnf:1
HU configured
Barcode: 021200171031
Barcode: 1PMAX3421EEHJ+
Barcode: 226660
Barcode: 420432169712
Barcode: 1Z44YV55YW12961215
Thanks man!! HIDUniversal approach works great
Where I can buy all the parts. I work close to Mcallen TX.
Thanks Mannn!!!
Thanks for the great info. I had a compile error with this (below). I renamed the declaration on line 44 and the reference on line 98 to “MyKeyboard” instead of “Keyboard” and it complied.
barcode2:43: error: conflicting declaration ‘HIDBoot Keyboard’
/Applications/Arduino.app/Contents/Resources/Java/hardware/arduino/cores/arduino/USBAPI.h:135: error: ‘Keyboard’ has a previous declaration as ‘Keyboard_ Keyboard’
barcode2.cpp: In function ‘void setup()’:
barcode2:98: error: ‘class Keyboard_’ has no member named ‘SetReportParser’
Just realized the board may make a difference. I had my IDE set up for a Leonardo (which has some libraries for acting as a USB keyboard). Switching to Uno also fixed this (as opposed to my above renaming).
Hi Oleg,
I am currently using the HID universal to have read out a couple barcode scanners. It all works great but i’ve been noticing some glitches lately. Especially in combination with the WiFi shield from sparkfun. I do not have a watchdog timer running in my sketch but is it possible there has been one set up in the usb code itself? Is this wdt just to fix a USB timeout? What is the maximum time allowed between two calls of Usb.task()? I know this is not that hard to figure out if I go over the code but I want to make sure that this is the right thing to look into. Lastly is there any example available that involves the interrupt available on the maxim chip?
void setup() {
// Configure SPI
SPI.begin();
// Configure UART
Serial.begin(115200);
Serial.println(“Board Init”);
// Initalize GPIO pin modes
pinModes();
// Initial IO write to check all LEDs
UI_Init();
// Configure ADCs (AD7195)
Init_ADCs();
// Configure Wifi
Init_Wifi();
// Configure USB
Init_USB();
}
in my loop I call usb.task() and some other WiFi stuff. The wifi routines sometimes take about 2-3 seconds to finish so I’m wondering if this causes the board to restart.
Thanks!!
Wouter
There is no watchdog timer in USB code. If a Wi-Fi Shield is the one originally designed by Asynclabs then it conflicts with USB Host shield – you need to re-assign some pins, see hardware manual, section 5 -> http://www.circuitsathome.com/usb-host-shield-hardware-manual
Hi Oleg
I have a question about the connecting usb barcode scanner to Arduino ADK ATmega2560.
I try use your source code upload to Arduino ADK ATmega2560 by use USB_Host_Shield_2.0 , I found that it show ” OSC did not start. ” So, I understand and suspect that it have a problem on the board or the libraries not compatible.
– Do you have a USB host shield libraries compatible with Arduino ADK ATmega2560 board ?
– If no have USB host shield libraries compatible ,please advise the modification or edit the your USB host shield libraries.
Please advise…
You simply have to uncomment this line: https://github.com/felis/USB_Host_Shield_2.0/blob/master/avrpins.h#L25 for the library to work with the ADK.
Thank you for your advise…
Hi Lauszus
I have follow your advice, and try uuload file to ADK bopard again.
I found that the ADK board still show ” OSC did not start “.
Do you have another edit for USB_Host_Shield libraries or not ?
What ADK board are you using? The one from the Arduino team: http://arduino.cc/en/Main/ArduinoBoardADK or another one?
It works fine with the official board.
I use arduino adk mega2560 board.
Please advise…
Are you using the original board or something else? I need to see the schematic if it’s not the original one, to help you out.
No, I use board from local supplier in thailand.
Please see schematic as this link in final page.
http://www.etteam.com/prod2011/arduino/manET-MEGA2560.pdf
Thank you.
You have to change this line: https://github.com/felis/USB_Host_Shield_2.0/blob/master/avrpins.h#L475 to:
#define P53 Ph7
It looks like you can easily modify the board, by unsoldering a 0ohm resistor and move it to the other pad (see the last page of the pdf). It’s pretty hard for me to tell where is located as there is no board files. But try using a multimeter to figure out where it’s located. But the above fix should work just as good.
Thank you very much for your advic.
I will try and update status to you.
You can also change this line: https://github.com/felis/USB_Host_Shield_2.0/blob/master/Usb.h#L59 to:
if you prefer that instead.
Hi, im using usb shield plus usb barcode reader. Thus I need to control a stepper and have some signals from other sensors… however… every single time I declare outputs pinMode(StepperPin1, OUTPUT); // initialize the StepperPin as an output
pinMode(StepperPin2, OUTPUT); // initialize the StepperPin as an output
pinMode(StepperPin3, OUTPUT); // initialize the StepperPin as an output
pinMode(StepperPin4, OUTPUT); // initialize the StepperPin as an output
the program stops when calling the function Usb.Task… I remove the declaration n everything works fine… im using an arduino Mega and Ive set the all the other ports that are not in use by the shield (i mean ports 22 till 53)
I don’t know more what to do… this is driving me crazy!
tks in advance!
Actually, the problem is not by initializing OUTPUTS, i have problems by initializing INPUTS… why that?
Oleg can you give me an idea why I cant compile on an Leonardo I understand its the keyboard emulation but cant see why got it working on a mega 256 but cant on the Leonardo.
Thanks….
No idea. I also don’t have Leonardo therefore can’t test, sorry.
ok sorted myself will post the code up
hi all
an update to the barcode scanner for the loenardo to mimic the scanner, taken out all the code not needed. It has one issue at the moment it drops the leading char of the barcode after the first scan. will fix it soon. Original code by Oleg and by Benjamin Maus.
Rgds Mark
#include
#include
#include
USB Usb;
HIDBoot Keyboardscan(&Usb);
int bc_byte;
byte scanCodes[10] = {0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39}; // you might need to change these if you scanner is set up for a different ean code system
char characters[10] = {‘0’, ‘1’, ‘2’, ‘3’, ‘4’, ‘5’, ‘6’, ‘7’, ‘8’, ‘9’};
int SCAN_ENTER = 0x13; //line feed char
int SCAN_BREAK = 0x6a; // char sent by barcode scanner to indicate a an end of scan
int breakActive = 0;
int clockValue = 0;
byte dataValue;
int quantityCodes = 10;
char buffer[64] = {}; // This saves the characters (for now only numbers)
int bufferPos = 0;
int bufferLength = 64;
class KbdRptParser : public KeyboardReportParser{
protected:
virtual void OnKeyDown (uint8_t mod, uint8_t key);
virtual void OnKeyUp (uint8_t mod, uint8_t key);
virtual void OnKeyPressed(uint8_t key);};
void KbdRptParser::OnKeyDown(uint8_t mod, uint8_t key){
uint8_t c = OemToAscii(mod, key);
if (c) OnKeyPressed(c);
//bc_byte=key;
}
void KbdRptParser::OnKeyUp(uint8_t mod, uint8_t key){
uint8_t c = OemToAscii(mod, key);
//do nothing
}
void KbdRptParser::OnKeyPressed(uint8_t key){
bc_byte=key, HEX;
dataValue = bc_byte;
// If there is a break code, skip the next byte
if (dataValue == SCAN_BREAK) {
breakActive = 1;
}
// Translate the scan codes to numbers
// If there is a match, store it to the buffer
for (int i = 0; i < quantityCodes; i++) {
byte temp = scanCodes[i];
if(temp == dataValue){
if(!breakActive == 1){
buffer[bufferPos] = characters[i];
bufferPos++;
}
}
}
//Serial.print('*'); // Output an asterix for every byte
// Print the buffer if SCAN_ENTER is pressed.
if(dataValue == SCAN_ENTER){
Serial.print("\nbuffer: ");
// Read the buffer
int i=0;
if (buffer[i] != 0) {
while(buffer[i] != 0) {
Serial.print(buffer[i]);
Keyboard.print(buffer[i]);
buffer[i] = 0;
i++;
}
}
Serial.println();
Keyboard.println();
bufferPos = 0;
}
// Reset the SCAN_BREAK state if the byte was a normal one
if(dataValue != SCAN_BREAK){
breakActive = 0;
}
dataValue = 0;
};
KbdRptParser Prs;
void setup()
{
Serial.begin(9600);
Serial.println("Start");
if (Usb.Init() == -1) {
Serial.println("OSC did not start.");
}
Keyboard.begin();
delay( 200 );
Keyboardscan.SetReportParser(0, (HIDReportParser*)&Prs);
}
void loop() {
Usb.Task();
}
includes that don’t show are….
Usb.h
HIDBoot.h
Wire.h
OK done taken out most of the code by Benjamin Maus and cut the main loop down to look for the barcode signal breaks. All works fine.
enjoy Mark…….
#include Usb.h
#include HIDBoot.h //remember here you need the <
#include Wire.h
USB Usb;
HIDBoot Keyboardscan(&Usb);
int bc_byte;
String barcode;
byte dataValue;
int SCAN_ENTER = 0x13; //line feed char
int SCAN_BREAK = 0x6a; // char sent by barcode scanner to indicate a an end of scan
class KbdRptParser : public KeyboardReportParser{
protected:
virtual void OnKeyDown (uint8_t mod, uint8_t key);
virtual void OnKeyUp (uint8_t mod, uint8_t key);
virtual void OnKeyPressed(uint8_t key);};
void KbdRptParser::OnKeyDown(uint8_t mod, uint8_t key){
uint8_t c = OemToAscii(mod, key);
if (c) OnKeyPressed(c);
//bc_byte=key;
}
void KbdRptParser::OnKeyUp(uint8_t mod, uint8_t key){
uint8_t c = OemToAscii(mod, key);
//do nothing
}
void KbdRptParser::OnKeyPressed(uint8_t key){
bc_byte=key, HEX;
dataValue = bc_byte;
if (dataValue != SCAN_BREAK) barcode+=char(key);
// If there is a break code, skip the next byte
if (dataValue == SCAN_BREAK) {
Serial.println(“Barcode: “+barcode);
Keyboard.println(barcode+”\n”);
barcode=””;
}
};
KbdRptParser Prs;
void setup()
{
Serial.begin(9600);
Serial.println(“Start”);
if (Usb.Init() == -1) {
Serial.println(“OSC did not start.”);
}
Keyboard.begin();
delay( 200 );
Keyboardscan.SetReportParser(0, (HIDReportParser*)&Prs);
}
void loop() {
Usb.Task();
}
I tried the original code posted on this page and commented out the LCD portion. When I scanned barcodes it gave me a series of 2 digit numbers that did not seem related to the barcode scanned. So I then tried Marks code and commented our anything that said Keyboard since I am using the UNO cause the compiler said it was only for the Leonardo. The code compiles fine but when I try scanning something I the barcode scanner flashes red and beeps twice. Any suggestions?
Thanks,
Brandon
When I try to compile the code, I get these errors:
sketch_nov28a:42: error: ‘USB’ does not name a type
sketch_nov28a:44: error: expected constructor, destructor, or type conversion before ‘<' token
sketch_nov28a:47: error: expected class-name before '{' token
sketch_nov28a.ino: In member function 'virtual void KbdRptParser::OnKeyDown(uint8_t, uint8_t)':
sketch_nov28a:56: error: 'OemToAscii' was not declared in this scope
sketch_nov28a.ino: In function 'void setup()':
sketch_nov28a:92: error: 'Usb' was not declared in this scope
sketch_nov28a:98: error: 'Keyboard' was not declared in this scope
sketch_nov28a:98: error: 'HIDReportParser' was not declared in this scope
sketch_nov28a:98: error: expected primary-expression before ')' token
sketch_nov28a.ino: In function 'void loop()':
sketch_nov28a:109: error: 'Usb' was not declared in this scope
Do you know what is wrong?
USB library code is missing, i.e., compiler can’t find it.
Does that come with the Arduino software? Or do I have to download it and put it in a specific folder?
Thanks
how can soft trigger a usb scanner?
i am able to use your example featured here with Symbol LS2208, but i would like to be able to use my arduino to initiate the capture rather than me pressing the hard button on the scanner.
is it i have to use Usb.setconf to send the command? how do i get started in learning this communication?
You can’t, at least on a standard one. A barcode scanner is just a keyboard without keys.
the scanner can be sent to many different mode. for the LS2208, it can go to IBM USB mode.
would you know if those other modes can be soft triggered? so far i tried it can’t though
I’m not familiar with this scanner, sorry.
Back again with a new question. So when I run the program on my Arduino Uno R3 SMD, and try to scan a standard UPC of 0 11491 96730 7, I get this as my output:
Start
BM Init
Addr:1
BM configured
48
49
49
52
57
49
57
54
55
51
48
55
19
(On the LCD screen, the numbers are inserted without line breaks or spaces)
I ran the USB desc example, and the Class, Subclass, and Protocol all came back correct. I know how to do basic C programming, but I haven’t done anything with classes, and I don’t recognize some of the other code. Can anyone help debug what is going on. As a side note, the barcode scanner works flawlessly when connected directly to the computer.
USB_desc
Start
01
—
Device descriptor:
Descriptor Length: 12
Descriptor type: 01
USB version: 0200
Device class: 00
Device Subclass: 00
Device Protocol: 00
Max.packet size: 40
Vendor ID: 05E0
Product ID: 1200
Revision ID: 0100
Mfg.string index: 01
Prod.string index: 02
Serial number index: 03
Number of conf.: 01
Configuration descriptor:
Total length: 0022
Num.intf: 01
Conf.value: 01
Conf.string: 08
Attr.: A0
Max.pwr: FA
Interface descriptor:
Intf.number: 00
Alt.: 00
Endpoints: 01
Intf. Class: 03
Intf. Subclass: 01
Intf. Protocol: 01
Intf.string: 00
Unknown descriptor:
Length: 09
Type: 21
Contents: 10010001224D000705
Endpoint descriptor:
Endpoint address: 81
Attr.: 03
Max.pkt size: 0040
Polling interval: 08
Addr:1(0.0.1)
I don’t see a problem – everything works as it should. UPC codes don’t contain spaces, they are printed on a label for convenience.
Well, like I said… The barcode I’m trying to scan is 011491967307, but the output on the serial monitor (and lcd) is:
48
49
49
52
57
49
57
54
55
51
48
55
19
Those are your digits in the wrong representation. You need to print them as ASCII.
I’m searching online for how to do this, but I don’t know enough about Arduino programming as of now. How do you convert the ASCII decimal to the character when printing?
Okay, I found out how to print the characters to the LCD screen. Basically, I took everywhere that said “lcd.print” and replaced it with “lcd.write.”
I also then changed “Serial.println” to “Serial.write” and it now prints the correct characters to the LCD screen AND serial monitor.
Hi oleg,
I am trying to get my ACR122 usb NFC reader to talk to my arduino Uno. I have been trying for a week but still cannot.
Can advise or share some codes on how to do it?
Thanks in advance.
What is your hardware and what have you already tried?
why am i getting this error?
what should i do?
sketch_jan28a:42: error: ‘USB’ does not name a type
sketch_jan28a:44: error: expected constructor, destructor, or type conversion before ‘<' token
sketch_jan28a:47: error: expected class-name before '{' token
sketch_jan28a.ino: In member function 'virtual void KbdRptParser::OnKeyDown(uint8_t, uint8_t)':
sketch_jan28a:56: error: 'OemToAscii' was not declared in this scope
sketch_jan28a.ino: In function 'void setup()':
sketch_jan28a:92: error: 'Usb' was not declared in this scope
sketch_jan28a:98: error: 'Keyboard' was not declared in this scope
sketch_jan28a:98: error: 'HIDReportParser' was not declared in this scope
sketch_jan28a:98: error: expected primary-expression before ')' token
sketch_jan28a.ino: In function 'void loop()':
sketch_jan28a:109: error: 'Usb' was not declared in this scope
The USB library is not seen by the compiler.
In file included from adk_barcode.pde:6:
C:\Users\ISIPja\Desktop\Arduino\Software\arduino-1.0.2\libraries\USBHostShield/usbhost.h: In constructor ‘MAX3421e::MAX3421e()’:
C:\Users\ISIPja\Desktop\Arduino\Software\arduino-1.0.2\libraries\USBHostShield/usbhost.h:87: error: ‘spi’ has not been declared
In file included from adk_barcode.pde:8:
C:\Users\ISIPja\Desktop\Arduino\Software\arduino-1.0.2\libraries\USBHostShield/Usb.h: At global scope:
C:\Users\ISIPja\Desktop\Arduino\Software\arduino-1.0.2\libraries\USBHostShield/Usb.h:61: error: ‘P10’ was not declared in this scope
C:\Users\ISIPja\Desktop\Arduino\Software\arduino-1.0.2\libraries\USBHostShield/Usb.h:61: error: ‘P9’ was not declared in this scope
C:\Users\ISIPja\Desktop\Arduino\Software\arduino-1.0.2\libraries\USBHostShield/Usb.h:61: error: template argument 1 is invalid
C:\Users\ISIPja\Desktop\Arduino\Software\arduino-1.0.2\libraries\USBHostShield/Usb.h:61: error: template argument 2 is invalid
C:\Users\ISIPja\Desktop\Arduino\Software\arduino-1.0.2\libraries\USBHostShield/Usb.h:61: error: invalid type in declaration before ‘;’ token
C:\Users\ISIPja\Desktop\Arduino\Software\arduino-1.0.2\libraries\USBHostShield/Usb.h:182: error: expected class-name before ‘{‘ token
another error
what should i do? i already imported the usb host shield library but still the error exist.
See my old reply on how to add the USB Host Library: https://www.circuitsathome.com/mcu/rc-car-controlled-by-wii-remote-on-arduino/comment-page-1#comment-13787
can you guide me. i am interfacing barcode scanner with atmega 1281 by using usb host shield. i want to display the scanned barcode to the lcd display.
It’s hard to say. Make sure you have all the files from the distro on github, it looks like you’re missing some of them.
how can i get the value scanned from the barcode using ps2?
Can I do the same with a fingerprint reader? Thanks
It depends. If you can find a reader which supports some generic protocol then yes. Sadly, all fingerprint readers I’ve seen so far used proprietary protocols.
Hey Oleg,
Thanks a ton for this tutorial.
I have assembled all the required circuitry for this project but I am stuff at one point.
I was running the board_qc programme and was getting this error:
error: too few arguments to function ‘void Notify(const char*, int)’
In addition, when I was using the KpdBootHID sketch I got the following error:
error: no matching function for call to ‘PrintHex(uint8_t&)’
When I entered the printhex.h code I realised that the inputs indeed do not match what is stated in printhex.h.
How do I overcome this problem?
I hope you could help me with this.
Thanks in advance 🙂
the
Notify()
syntax has changed rather suddenly. Change all Notify calls to Notify(PSTR(“xxx”), 0x80)) . I will correct the examples within next day or two. Sorry for the inconvenience.Thanks Oleg!
What about the PtintHex function?
The syntax in the printhex.h is:
void PrintHex(T val, int lvl)
In the USBHIDBootKbd.pde however, we call the the function through:
PrintHex(key)
I get an error at this point in my sketch.
*PrintHex
I got both fixed, please download new versions from github. Let me know if anything else is broken.
Thanks
the int value is the debug level, just use 0x80, this way at the sketch level, if you do not want the debug info, you change it in setup.
Example from one of my test sketches…
void setup() {
// Set this to higher values to enable more debug information
// minimum 0x00, maximum 0xff
UsbDEBUGlvl = 0x51;
…
}
The idea also is that this allows you to change debug levels on-the-fly, and it also allows you to change the debug noise level.
Hey Oleg,
I am working with the Arduino Mega 2560 R3.
What changes do I make to the header files in order to use the code?
Some forums seems to suggest that I need to make some changes to the SPI pins definition in Usb.h. Not to0 clear though.
Could you provide some clarity on this ?
Thanks again 🙂
In particular, I think I am stuck at the MAX_INT pin.
Which is the MAX_INT pin in the Arduino Mega 2560?
Are you using an Arduino Mega 2560 or an Arduino ADK: http://arduino.cc/en/Main/ArduinoBoardADK?
If you are using an Arduino Mega 2560 then you don’t have to change anything. If you are using an Arduino ADK, then uncomment the following line: https://github.com/felis/USB_Host_Shield_2.0/blob/master/avrpins.h#L25.
i am currently working on a project to read data from a smart card reader connected to a usb host shield. I am new to arduino. Could you tell me where to finda a good tutorial?
Dear Oleg
what is the exact use of Notyfi() Syntax? and how does Board_qc output the test result? i tried to use serial monitor , but it gives scratch characters like “þüYªoÿöYº÷ý¿4~ÿì2Äýý¿´¿þßL*þÿYÊwýÿYÊý¿ ¾ýlþÿÿã¸ý¿4Ä¿ÿÿÄ~¿4ÿl:Íÿÿìÿ¿ÿ~ÄþÿÄþ¿4ÿüXÄÿüYª;ÿl ~ûÿÿÄþ¿ ¾öüüÃ8ÿü~Äþÿîþÿ4cÿÿ4·ûoþýßÿþû|KþÿöÁ¿ÿwý¿ þýÿ¾Äßn¸vþ¿4~ÿì²°~û|Äþÿ¸Åþï¾Å¿üþÄþü¾ÄþÿYÚwý¿4®xÿ~YÊ·þßY¾ÿìYÊ÷ý¿4Äþù¾Äþ첿cÿÿ4f÷ÿ¾ÿöLÄþ¿Ê·ùÿ¼ÿÿlÄül°îýl²ÊÿýßYÊ¿ÿn°~ùþY°îý¿4Ã8ýÿ²¾ýì¾Åþÿ~Äþðþ¾ýÿÿ.þÿÉþÿ4ÿì]Å|¿ÿÿ|®ôÿk¾n~¾?~~üRâÿÒüÅìÉ/þ¾64~¾t~
úû”
can you help?
you need to set serial speed in your terminal to 115200
thank you Oleg, it is solved now, how fool i am haha
dear can you help me of good project for connecting Android 4 devices with Ardino using USB cable, and Android 4?, i need to read analog signal from arduino on Android tablets, thank you for help
thank you Oleg, it is solved now, how fool i am haha
dear can you help me of good project for connecting Android 4 devices with Ardino using USB cable, and Android 4?, i need to read analog signal from arduino on Android tablets, thank you for help
Hazem check out the following example: https://github.com/felis/USB_Host_Shield_2.0/blob/master/examples/adk/ArduinoBlinkLED/ArduinoBlinkLED.ino and the source code for the Android app is available here: https://github.com/Lauszus/ArduinoBlinkLED.
Hi Oleg,
I’m trying to use boot mouse connected via USB Host Shield and IR receiver. Separately each of them works ok. But as I place in my loop() function both Usb.task() and irrecv.decode(&results) program stop responding to IR remote control. I think that’s because Usb.task() blocks for too long if mouse is not moved or pressed. Could this behaviour of Usb.task()
be modified?
there is a Poll() method which does polling of the mouse. You can change that to return control more quickly or play with bmNakPower or both.
Thank you so much, Oleg! You saved my project!
I set bmNakPower to USB_NAK_NONAK and USB_XFER_TIMEOUT to 100 and that works fine for me. Mouse and IR receiver both function responsively now.
Thanks!
Which barcode reader should i buy?? I need suggestions, it seems not all barcode scanners work?
Buy a cheap one.
Hello Oleg, so I have an Arduino Mega 2560, a saintsmart usb shield and a ZT-800U barcode reader, i downloaded your library i applied everything you said, to start of when i connect everything I used the USB_Desc and also the USBHID_Desc and my serial monitor just shows:
Start
OSC did not start
i did remove the comment for the arduino 2560 but still was showing the same thing.
So i tried with an Arduino UNO and this time I ran both examples and it only showed:
Start
So im just wondering what could be the problem?
thanks in advance
I’m getting the following output from the USB Desc example program
Interface descriptor:
Intf.number: 00
Alt.: 00
Endpoints: 01
Intf. Class: 03
Intf. Subclass: 00
Intf. Protocol: 01
Intf.string: 00
Unknown descriptor:
Length: 09
Type: 21
Contents: 01010001223F000705
Endpoint descriptor:
Endpoint address: 81
Attr.: 03
Max.pkt size: 0008
Polling interval: 0A
Endpoint descriptor:
Endpoint address: 01
Attr.: 03
Max.pkt size: 0001
Polling interval: 0A
Addr:1(0.0.1)
what solution for connecting my barcode scanner to arduino uno use usb host shield ?
What do you mean by solution?
iwant use your source code to connecting my barcode scanner to arduino. what should i change from your source code?
where Intf. Subclass my barcode is zero.
please somebody, im not getting no response for my barcode also i tried to get the description but i will go to serial monitor and it only shows: Start
what could i do?
dear
i also involved in a project
i bought a barcode scanner and it is not responding to the code anymore.
so
can u mention any good products in ebay compatible with the project?
You need one which emulates USB keyboard so look at ones advertising ‘keyboard emulation’ and/or ‘no driver necessary’.
Hey Oleg,
Running the USB_Desc gives
Start
01
—
Device descriptor:
Descriptor Length: 12
Descriptor type: 01
USB version: 0200
Device class: 00
Device Subclass: 00
Device Protocol: 00
Max.packet size: 08
Vendor ID: 03EB
Product ID: 6201
Revision ID: 0001
Mfg.string index: 01
Prod.string index: 02
Serial number index: 03
Number of conf.: 01
Configuration descriptor:
Total length: 0029
Num.intf: 01
Conf.value: 01
Conf.string: 00
Attr.: C0
Max.pwr: 32
Interface descriptor:
Intf.number: 00
Alt.: 00
Endpoints: 02
Intf. Class: 03
Intf. Subclass: 00
Intf. Protocol: 00
Intf.string: 00
Unknown descriptor:
Length: 09
Type: 21
Contents: 110100012239000705
Endpoint descriptor:
Endpoint address: 81
Attr.: 03
Max.pkt size: 0003
Polling interval: 02
Endpoint descriptor:
Endpoint address: 82
Attr.: 03
Max.pkt size: 0001
Polling interval: 0A
Addr:1(0.0.1)
The important statistics are
Intf. Class: 03
Intf. Subclass: 00
Intf. Protocol: 00
Clearly my device does not support boot protocol. Is it possible to change the code to enable my device to work?
I answered your e-mail with the same question.
Hey Oleg,
I came across this cue cat barcode scanner.
http://www.ebay.com.sg/itm/USB-Barcode-Reader-Scanner-Cue-Cat-CueCat-UPC-/380319763899?pt=US_Scanners&hash=item588cd30dbb&_uhb=1#ht_3439wt_1242
You think it will work?
I have already bought one scanner (the one above) which said no drivers required but was not compatible with boot protocol.
I am trying to read the entire code rather than print each one character one at a time and then store this code in a variable.
I made these changes to OnKeyPressed.
Note: I have initialized buffer as char buffer[5]=”XXXX”;
void KbdRptParser::OnKeyPressed(uint8_t key)
{
// initializing buffer
if(buffer[0] == ‘X’)
buffer[0]= (char) key;
else
if(buffer[1] == ‘X’)
buffer[1]= (char) key;
else
if(buffer[2] == ‘X’)
buffer[2]= (char) key;
else
if(buffer[3] == ‘X’)
buffer[3]= (char) key;
};
I re-intialized buffer to “XXXX” before the next scan.
The code however, gives me erratic values in buffer.
Any better way to do this?
I am using 4 character bar codes for the above example