Shopping Cart

Posts

Connecting barcode scanner to Arduino using USB Host Shield

Scanning barcodes using Arduino and USB Host Shield

Scanning barcodes using Arduino and USB Host Shield

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 need OnKeyDown() and OnKeyPressed() 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 calls OnKeyPressed()
  • 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.

Reading RFID tags with Arduino/USB Host Shield

Reading RFID tags with Arduino/USB Host Shield

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?

No related posts.

148 comments to Connecting barcode scanner to Arduino using USB Host Shield

  • Thom Brooks

    Can you please show how this code could be modified to make use of the Max_LCD library instead of LiquidCrystal? (i.e. make use of the GPOUT pins on the shield itself)

    Thank you!

  • JVC

    Hi Oleg,

    I’m interested in using this kind of project to help my company update statuses on orders. I have absolutely no idea what I’m doing, but I’ll need to hookup to the internet with the arduino. Would you suggest an Arduino Ethernet plus your USB shield – is that a good combo? Also, can you give me an example of an LCD display to use?

  • Hi Oleg,
    I have a project in which i need to interface a barcode reader with Mbed.. Kindly reply if this can be done using and Mbed?
    Secondly it will be very kind of you to mention more about the type of scanners that can be interfaced easily.mention a link so i could know what should i actually buy ..I will be very grateful to you for your help.

  • Toan

    Could anyone explain for me the line of code do?
    HIDBoot Keyboard(&Usb);

    what is the role of “” in this line of code?
    Thank you.

  • Toan

    Could anyone explain for me the line of code do?
    HIDBoot Keyboard(&Usb);

    what is the role of “ ” in this line of code?
    Thank you.

  • Syafiq

    Hello,im using an usb host shield and also lcd host shield with button..by the program..i still can’t understand how can arduino read the data from my barcode scanner..and how i can display into my lcd??

  • Afonso

    Hi,

    I am using a barcode scanner connected to the Arduino Mega though UHS. The scanner works fine at the PC, but does not when connected to Arduino.
    When the scanner is attached, we have the message:
    BM Init
    Addr:01
    bAddr:01
    bNumEP:02
    totalEndpoints:0002
    Cnf:01
    If:00
    BM configured
    but the scanner does not work. The leds stay blinking and the scanner does not read any barcode, and also does not send anything to the USB Host.

    The USB_desc output is:
    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: 40
    Vendor ID: 24EA
    Product ID: 0197
    Revision ID: 0200
    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: 00
    Attr.: 80
    Max.pwr: C8

    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: 010100012240000705

    Endpoint descriptor:
    Endpoint address: 81
    Attr.: 03
    Max.pkt size: 0008
    Polling interval: 0A

    Addr:1(0.0.1)

    The HID_desc is:
    Start
    0000: 05 01 09 06 A1 01 05 07 19 E0 29 E7 15 00 25 01
    0010: 95 08 75 01 81 02 95 01 75 08 81 01 05 08 19 01
    0020: 29 03 95 03 75 01 91 02 95 05 75 01 91 01 95 06
    0030: 75 08 15 00 26 E7 00 05 07 19 00 29 E7 81 00 C0
    0040: 00 00 00 00 00 00 00 00 00 00
    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 Count(08)
    Report Size(01)
    Input(00000010)
    Report Count(01)
    Report Size(08)
    Input(00000001)

    Usage Page LEDs(08)
    Usage Min(01)
    Usage Max(03)
    Report Count(03)
    Report Size(01)
    Output(00000010)
    Report Count(05)
    Report Size(01)
    Output(00000001)
    Report Count(06)
    Report Size(08)
    Logical Min(00)
    Logical Max(E700)

    Usage Page Kbrd/Keypad(07)
    Usage Min(00)
    Usage Max(E7)
    Input(00000000)
    End Collection

    Do you have any advice?
    Thanks

  • hi oleg, really2 thanks for the code. It works fine with my logitech keyboard.

    but when I try to use it with argox as-8000 barcode scanner, it seems hang or sometime it says osc didnot start.

    when use board_qc sometime work, mostly not. but when I use lib version 1, board_test always works fine.

    Please need help. Thx

      • below is usb desc, almost the same as your example. just different on max pwr. does it need extra power? if yes, how to do?

        Device descriptor:
        Descriptor Length: 12
        Descriptor type: 01
        USB version: 0110
        Device class: 00
        Device Subclass: 00
        Device Protocol: 00
        Max.packet size: 08
        Vendor ID: 04B4
        Product ID: 0100
        Revision ID: 0001
        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: 32

        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: 00010001223F000705

        Endpoint descriptor:
        Endpoint address: 81
        Attr.: 03
        Max.pkt size: 0008
        Polling interval: 0A

        Addr:1(0.0.1)

      • Thanks oleg, now succeed sent barcode to a web server. arduino, usb host shield and ethernet shield. I modified a bit on file usbcore.h

        Many thanks again

    • Hi Oleg, I think you’re right. We decide to buy another barcode scanner. Will get back after we bought it today.

      Mean while, if I want to use usb host shield an ethernet shield together, I guest I need to modify the SS pin so it would not conflict. If I am right, so I need to modify avrpins.h?

    • Hi oleg, apparently it is power issue. Still use old barcode (argox) and now it works. Next target is send it over ip.

      Thanks again, any clue on send it aver ip?

  • It works now on lib version 2 but still could not read an argox barcode scanner

    Below, USBHID_desc from my barcode scanner and have tried read barcode

    Start
    HU Init
    Addr:01
    NC:01

    Cnf:01
    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 FF 05 07 19 00 29 FF 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(FF)
    Usage Page Kbrd/Keypad(07)
    Usage Min(00)
    Usage Max(FF)
    Input(00000000)
    End Collection

    • Amre

      hi, bintanghd, I want to know how setup u setup all of this project, because my project already same equipment but i cant get the output result. why? interface for HID, usb desc I cant get any point.. please help me!!

  • pranshu

    hi, i just want to extract the barcode and not print it on the lcd then will the same code work if i use it till the 60th line? the “key” variable will have all the bits of the scanned number right?
    thanks

  • Hi Oleg,

    Initially I managed to run this example using my barcode reader (removed LCD code, just using Serial.println’s).

    In order to connect an ethernet shield, I moved SS pin to 5 (modifying UsbCore.h to say typedef MAX3421e MAX3421E;) – the code continued to work.

    However, when physically connecting the ethernet shield on top of the usb host shield, the example stopped working. I double checked that pin 10 is no longer connected to SS on the host shield as before.
    I did find out that when bending the ethernet shield’s pin 10 so that it does not get connected, the example returns to working fine.

    Could you advise a course of action here?
    at least what can I do to investigate what’s happening?

    Thanks!
    Zvika

    • Some shields which use SPI won’t release the bus when not active. My shield does release the bus but if there is another one which doesn’t there is no remedy other than remove it and find one which was designed properly.

      • Thanks!

        Do you mean that while not transmitting/receiving the bus pins (11-13) are not left floating as required? Isn’t there something that can be done via hacking? like, watching pin 10 and physically disconnecting pins 11-13 via optocouplers (?) when it is not active?

        Also, since I am using the semi-official Ethernet shield (Wiz5100 manufactured in the far East) – from your experience may moving to the European ones fix the problem? I’ve been reading about people who did manage to connect USB host shield and the ethernet shield together without much hassle.

  • Mukelpump

    Hi Oleg,

    can you send me the code for the rfid reader?
    Ive bought the same and now id like to read out my tags.

    Thanks to you and have a good night.

    Kind regards Mukelpump

  • Anthony

    Hi!

    Thank you so much for publishing this! I do not have the LCD, nor am I planning on getting it, I am just trying to use the barcode scanner to read different IDs using your code or even just the keyboard example code, but I keep getting outputs in this form:
    üþÿýýüüþþþþþÿÿýýüÿþþÿÿþ

    do you have any ideas of what could be going wrong?

    Thanks so much and have a great weekend

Leave a Reply

  

  

  



You can use these HTML tags

<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong> <pre lang="" line="" escaped="" highlight="">