Control barcode scanner with arduino and USB host shield

Good Morning,

I am trying to read the barcodes using Honeywell’s quantumt ms3580 scanner https://www.honeywellaidc.com/es-es/products/barcode-scanners/hands-free/quantumt-3580 an arduino mega 2560 and a USB host shield 2.0.
I have followed the example https://www.circuitsathome.com/connecting-barcode-scanner-to-arduino-using-usb-host-shield/
the parameters of my scanner are:
Intf. Class: 03
Intf. Subclass: 01
Intf. Protocol: 01

But I still can’t get the scanner to power up, and therefore read the barcodes. I connect it to my PC and if it feeds and reads the barcodes correctly.

I leave you my code:

#include <usbhid.h>
#include <usbhub.h>
#include <hiduniversal.h>
#include <hidboot.h>
#include <SPI.h>

class MyParser : public HIDReportParser {
  public:
    MyParser();
    void Parse(USBHID *hid, bool is_rpt_id, uint8_t len, uint8_t *buf);
  protected:
    uint8_t KeyToAscii(bool upper, uint8_t mod, uint8_t key);
    virtual void OnKeyScanned(bool upper, uint8_t mod, uint8_t key);
    virtual void OnScanFinished();
};

MyParser::MyParser() {}

void MyParser::Parse(USBHID *hid, bool is_rpt_id, uint8_t len, uint8_t *buf) {
  // If error or empty, return
  if (buf[2] == 1 || buf[2] == 0) return;

  for (uint8_t i = 7; i >= 2; i--) {
    // If empty, skip
    if (buf[i] == 0) continue;

    // If enter signal emitted, scan finished
    if (buf[i] == UHS_HID_BOOT_KEY_ENTER) {
      OnScanFinished();
    }

    // If not, continue normally
    else {
      // If bit position not in 2, it's uppercase words
      OnKeyScanned(i > 2, buf, buf[i]);
    }

    return;
  }
}

uint8_t MyParser::KeyToAscii(bool upper, uint8_t mod, uint8_t key) {
  // Letters
  if (VALUE_WITHIN(key, 0x04, 0x1d)) {
    if (upper) return (key - 4 + 'A');
    else return (key - 4 + 'a');
  }

  // Numbers
  else if (VALUE_WITHIN(key, 0x1e, 0x27)) {
    return ((key == UHS_HID_BOOT_KEY_ZERO) ? '0' : key - 0x1e + '1');
  }

  return 0;
}

void MyParser::OnKeyScanned(bool upper, uint8_t mod, uint8_t key) {
  uint8_t ascii = KeyToAscii(upper, mod, key);
  Serial.print((char)ascii);
}

void MyParser::OnScanFinished() {
  Serial.println(" - Lectura Correcta!!");
}

USB          Usb;
USBHub       Hub(&Usb);
HIDUniversal Hid(&Usb);
MyParser     Parser;

void setup() {
  Serial.begin( 115200 );
  Serial.println("Escaner Iniciado Correctamente!");

  if (Usb.Init() == -1) {
    Serial.println("OSC did not start.");
  }

  delay( 200 );

  Hid.SetReportParser(0, &Parser);
}

void loop() {
  Usb.Task();
}

I hope your help to see if it is possible to know where I am failing and if it is possible to find a solution.
Thank you very much in advance.

Have you tried the descriptors sample code USB_desc yet, without a hub? It would not run your scanner but will print out useful information regarding the descriptors. I would take a big step back and run that sample code first and post everything here.

1 Like

Thank you very much for your response, I just tried the example USB_desc, and this is the result of my scanner:

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:	08
Vendor  ID:		0C2E
Product ID:		0200
Revision ID:		5881
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:		03
Attr.:			80
Max.pwr:		96

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:		0008
Polling interval:	0A


Addr:1(0.0.1)

I will be very grateful for any help or clue to solve this problem, thank you very much in advance.

I’ve not used the UHS V2.0 library for bar code scanners but I can give you some general assistance. First, a bar code scanner, like yours, is a USB keyboard and acts pretty much like one.

I went ahead with the USBHIDBootKbd sample code. I could use a keyboard, a small handheld barcode scanner, but not a larger desktop scanner. With a larger desktop scanner, it fails to respond to some of the requests so it never gets initialized. My library has dates of Nov 2020 so it is recent.
I also tried the USB_desc code. It’s very inconsistent. One scanner doesn’t print anything and another prints out everything. This could be the library itself. The scanners that require extra time with dozens of polling are the ones that fail the keyboard sample code. These scanners all work on PC.

I also tested a version I downloaded back in 2019. Same issue. I pinpointed it to the address setting command wasn’t polling the scanner multiple times. The scanner must respond within one SOF, which works for some but not for all. The USB_desc program mostly works because its set address command does polling multiple times. In my case less than 10 polls later the device responds. If the host isn’t polling, then the response wasn’t received and that cascaded into a series or issues such as address stuck at 0 etc. and eventually host library just gives up and disconnects. You should ask the developers to look into this issue. The library, last I looked, was a labyrinth of code with lots of template classes that I don’t like reading.

Keyboard example, where the red line is should be polling for IN but not:

USB_desc example has polling, 5 times before my scanner responded:

The two commands are exactly the same, setting device address to 1. But in different examples, must be different parts of the code that did the address setting, and one place polling for control request was not enabled, causing trouble with some scanners.

I can’t help you fix the library. It’s best done by the developers.

The scanner is a Honeywell 7580g. The details of which scanner isn’t important. Enabling polling on the set_address command request is.

Thank you very much liuzengqiang, finaly a solved it with an external power supply.