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?

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

  • tommy

    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(;;);

    }
    }

    • Brandon P

      Tommy,I am trying to do the same thing as you. Did you ever get this solved?

      • Omar

        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

      • ehvie

        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?

  • 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?

  • Arisone

    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

  • Kartik Sanghi

    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.

  • Kartik Sanghi

    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?

  • Braithers

    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.

  • wova

    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

      • wova

        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.

          • wova

            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

      • wova

        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

          • wova

            Alright thank you, i will look over it.

          • wova

            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,

          • wova

            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!!!

  • Ben M

    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’

    • Ben M

      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).

  • wova

    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

  • Weerapongh

    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…

  • weerapongh

    Thank you for your advise…

  • Weerapongh

    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 ?

  • Weerapongh

    I use arduino adk mega2560 board.
    Please advise…

  • Weerapongh

    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.

  • Weerapongh

    Thank you very much for your advic.
    I will try and update status to you.

  • Leonardo

    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!

  • Mark F

    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….

  • Mark F

    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();
    }

  • Mark F

    includes that don’t show are….

    Usb.h
    HIDBoot.h
    Wire.h

  • Mark F

    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();
    }

    • Brandon P

      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

  • ilarson007

    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

  • Leow Cheah Wei

    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?

  • ilarson007

    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.

      • ilarson007

        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.

          • ilarson007

            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?

          • ilarson007

            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.

  • PH

    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.

  • kennedy

    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.

      • kennedy

        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

  • kennedy

    what should i do? i already imported the usb host shield library but still the error exist.

  • kennedy

    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.

  • kennedy

    how can i get the value scanned from the barcode using ps2?

  • Ben

    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.

  • Arvin

    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.

  • Arvin

    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.

  • Arvin

    *PrintHex

  • Andrew Kroll

    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.

  • Arvin

    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 🙂

  • Larry Kiniu

    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?

  • Hazem

    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ÿÿ4”f÷ÿ¾ÿöLÄþ¿œÊ·ùÿ¼ÿÿlÄül°îýl²ÊÿýßYÊ¿ÿn˜°~ùþY°îý¿4Ã8ýÿ²¾ýì¾Åþÿ~Äþðþ¾ýÿÿ.þÿÉþÿ4ÿì]Å|¿ÿÿ|®ôÿk¾n~¾?~~üRâÿÒüÅìɐ/þ¾64~¾t~
    úû”

    can you help?

  • Vladimir

    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.

      • Vladimir

        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!

  • Andrés Puerta

    Which barcode reader should i buy?? I need suggestions, it seems not all barcode scanners work?

  • Andres Puerta

    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

  • handika

    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 ?

  • Andres Puerta

    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?

  • raje

    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’.

  • Arvin

    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?

  • Arvin

    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.

  • Arvin

    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?

  • Arvin

    I am using 4 character bar codes for the above example