USB Host Shield library Version 2.0 released.

By Oleg Mazurov

Hub demo

What started as a quick re-factoring effort transformed to a major redevelopment, but finally all pieces fit together tightly and I am pleased to announce that initial release of USB Host Shield library ver.2.0 has been posted to github. This new version contains several major improvements:

The low-level interface to MAX3421E has been re-designed. Arduino pin manipulation routines has been replaced with mechanism inspired by Konstantin Chizhov’s C++ AVR pin templates. As a result, low-level transfers became approximately 3.5 times faster. Also, pin reassignment can be done much easier by passing pin numbers into MAX3421E template during instantiation.

The high-level interface to USB devices has been re-designed as well. It is now possible to connect USB hub to the shield and have many devices on USB bus, up to 7 daisy-chained 8-port hubs plus up to 44 devices connected to hub ports left after daisy-chaining, memory permitting. Also, a standard mechanism of device initialization/polling/releasing has been added to enumeration.

Several minor code improvements has also been made. NAK_LIMIT is now tied to an endpoint – it is now possible to have NAK_LIMIT set to 1 for interrupt endpoint and 32000 for bulk endpoint of the same device simultaneously. Control transfer function now accepts callback in order to split long chunks of data, if necessary. inTranser() function now is able to return actual number of bytes received.

Support for several popular device classes has been added. Device initialization and event handling is now moved to a library specific to device class, therefore user application does’n need to do this and only needs to process actual device data. The following devices are now supported by the library code:

Asynchronous Serial over USB AKA CDC. Devices of this class provide serial connectivity. For example, newer Arduino boards, such as UNO and Mega 2560 communicate to a PC using CDC ACM-class device, while older boards, such as Duemilanove, use FTDI FT232 USB-to-serial converter. 3 main types of converters are supported – CDC ACM (newer Arduinos and most modern cell phones), FTDI FT232 (older Arduinos plus a ton of standalone converters ) and Prolific PL2303 (mainly used in USB cables for various cellphones).

Several other device classes are in the works and will be available soon. They include:

Mass Storage Devices – Flash Drives, USB sticks, card readers, etc.

PTP – a protocol used in digital cameras. The PTP code is being transferred from current PTP project with minor changes.

In addition to that, USB hub is supported by its own class; however, in order to use it nothing special needs to be done apart from defining an instance of hub class for each hub.

Library code is compatible with current revisions of USB Host Shield, i.e. full-size shield r2.0 and Mini shield r1.1. Older shields can be made compatible with new library by performing a simple hardware modification. I will add a section to hardware manual eventually, in the mean time, if you still have an old shield and want to know how to mod it to make it compatible with new library, drop me a line. It also should be noted that due to extra code needed for multi-device support binaries compiled from this library are larger than old one – before migrating your existing project make sure it will fit into your Arduino.

A hub_demo directory under examples contains a sketch demonstrating hub functionality. The sketch goes from hub to hub initializing devices and then prints their device and configuration descriptors. As can be seen on the title picture, I have a 24 port hub, which actually consists of four daisy-chained 7-port hubs, 3 cell phones, couple mice, USB-to-serial converter, Xbee plugged into Explorer board, digital scale, a pair of RC controllers, digital camera, and RFID reader. The output of a sketch running this setup can be seen here.

create hub instances, if you need more than four (up to 7), add USBHub Hub5(&Usb);, USBHub Hub6(&Usb);, USBHub Hub7(&Usb);. If you need to address more than 16 devices, including hubs, increase USB_NUMDEVICES in Usb.h.

Except for hubs, the sketch doesn’t make any attempts to configure any devices, it can be run with any USB devices which are available.

At present, I only have one other sample sketch in acm directory. It is a simple terminal intended to be used with cell phones. I will post details about using it soon. In the mean time, take a look at the cdoe, run sketches and let me know what you think.

Guys, I haven’t found any clue that you released “Mass Storage Devices” support, any progress now? I am interesting in your shield and wondering whether it can make arduino to read the flash drive and show on LCD.

It means Get Device Descriptor request has failed. This is strange since USB_desc outputs it easily. Your device may need additional delays in initialization, try to add them and see if it makes any difference.

Im using the FTDI loopback example and everything is working fine, but Im unsure of how to use the hub function. What Im trying to do is send “Deadbeef1″ to one device and “Deadbeef2″ to another device, and make them both output on the serial monitor. Im just not sure how to address each device using the USBhub class. any help would be much appreciated.

Thankyou for the immediate response Oleg, this clears up a lot of things.
So, because I want deadbeef1 and deadbeef2 to alternate in the serial monitor, do I have to extra lines like this:
rcode2 = Ftdi2.SndData(strlen(strbuf), (uint8_t*)strbuf);
?

or is it something much more trivial, which Im too dopey to even think about lol,

I have an arduino uno r3, and am trying to get the usb host shield 2.0 compiled so i can communicate with the android phone.

i get the following errors

In file included from HelloAndroid.cpp:3:
C:\Documents and Settings\Stuart.CLARK\My Documents0 Software Development\arduino\arduino-1.0.1-windows\arduino-1.0.1\libraries\AndroidAccessory/AndroidAccessory.h:37: error: ‘EP_RECORD’ does not name a type

C:\Documents and Settings\Stuart.CLARK\My Documents0 Software Development\arduino\arduino-1.0.1-windows\arduino-1.0.1\libraries\AndroidAccessory/AndroidAccessory.h:50: error: ‘EP_RECORD’ has not been declared

C:\Documents and Settings\Stuart.CLARK\My Documents0 Software Development\arduino\arduino-1.0.1-windows\arduino-1.0.1\libraries\AndroidAccessory/AndroidAccessory.h:50: error: ‘EP_RECORD’ has not been declared

C:\Documents and Settings\Stuart.CLARK\My Documents0 Software Development\arduino\arduino-1.0.1-windows\arduino-1.0.1\libraries\AndroidAccessory/AndroidAccessory.h:64: error: ‘USB_NAK_LIMIT’ was not declared in this scope

C:\Documents and Settings\Stuart.CLARK\My Documents0 Software Development\arduino\arduino-1.0.1-windows\arduino-1.0.1\libraries\USB_Host_Shield\Max3421e.cpp:58: error: ‘PORTJ’ was not declared in this scope

C:\Documents and Settings\Stuart.CLARK\My Documents0 Software Development\arduino\arduino-1.0.1-windows\arduino-1.0.1\libraries\USB_Host_Shield\Max3421e.cpp:58: error: ‘PJ2′ was not declared in this scope

C:\Documents and Settings\Stuart.CLARK\My Documents0 Software Development\arduino\arduino-1.0.1-windows\arduino-1.0.1\libraries\USB_Host_Shield\Max3421e.cpp:60: error: ‘PORTJ’ was not declared in this scope

C:\Documents and Settings\Stuart.CLARK\My Documents0 Software Development\arduino\arduino-1.0.1-windows\arduino-1.0.1\libraries\USB_Host_Shield\Max3421e.cpp:60: error: ‘PJ2′ was not declared in this scope

C:\Documents and Settings\Stuart.CLARK\My Documents0 Software Development\arduino\arduino-1.0.1-windows\arduino-1.0.1\libraries\USB_Host_Shield\Max3421e.cpp:65: error: ‘PINE’ was not declared in this scope

C:\Documents and Settings\Stuart.CLARK\My Documents0 Software Development\arduino\arduino-1.0.1-windows\arduino-1.0.1\libraries\USB_Host_Shield\Max3421e.cpp:65: error: ‘PE6′ was not declared in this scope

C:\Documents and Settings\Stuart.CLARK\My Documents0 Software Development\arduino\arduino-1.0.1-windows\arduino-1.0.1\libraries\USB_Host_Shield\Max3421e.cpp:77: error: ‘DDRE’ was not declared in this scope

C:\Documents and Settings\Stuart.CLARK\My Documents0 Software Development\arduino\arduino-1.0.1-windows\arduino-1.0.1\libraries\USB_Host_Shield\Max3421e.cpp:77: error: ‘PE6′ was not declared in this scope

C:\Documents and Settings\Stuart.CLARK\My Documents0 Software Development\arduino\arduino-1.0.1-windows\arduino-1.0.1\libraries\USB_Host_Shield\Max3421e.cpp:78: error: ‘DDRJ’ was not declared in this scope

C:\Documents and Settings\Stuart.CLARK\My Documents0 Software Development\arduino\arduino-1.0.1-windows\arduino-1.0.1\libraries\USB_Host_Shield\Max3421e.cpp:78: error: ‘PJ2′ was not declared in this scope

I tried the acm_terminal example with a CDC-ACM device. It seems to work because I don’t receive any errors and see “ACM configured” printed out at the end. But from what I understand, since the acm_terminal example was successful, then the device I am using should be enumerated but I don’t think it is. The device I am using should send a signal once it’s enumerated and this is not happening. Do you know what could be going wrong in the enumeration process even though I receive a successful “ACM configured” message?

After “ACM configured” you should see data coming from device – if said device is sending something. If you have access to serial side of the converter, short TX and RX together and then type something in the terminal, the characters you’re typing should echo back to the screen.

Oleg,
Just started coding again after long absence and just picked up USB Shield for Arduino UNO and am testing with Logitech Gamepad. Ran the HID Joystick code in library examples and the hardware is working fine.

It’s been a long time since working with C++, so am trying to figure out a way to access the GamePadEventData. I tried calling JoystickEvents::OnGamePadChanged and passing in a pointer to a GamePadEventData variable, but obviously since I don’t know if the data has changed, or is available from the device that will not work. Was looking for a high level function I could call and check for changed data, but could not find one.

I saw some PS3 examples where there were functions to test for changed data, then you could use a function to read the joystick or button values. That is what I am ultimately trying to develop. Since this is an HID device, which could be pretty generic, do I need to write my own routines to accomplish this? I see in your code example where you check the buffer for a change, and then call the various event handlers, so I guess my ultimate question is do I need to emulate the bulk of this code on my own to get usable data out?

I have a degree in Computer Engineering, so I feel really dumb right now not being able to figure this out. My C++ knowledge has evaporated with age it seems.

Oleg,
Stepped away from the computer to take a break and clear my head. Think I figured this out. If I add a boolean flag variable to the JoystickReportParser class, then when the Parse function is called and the data has changed I can set the variable to True. I can also add a few member functions to the class, one that returns the state if the flag, and another JoystickValue function that can return the GamePadEventData structure values passed in by pointer. I could then reset the flag to False, so I don’t keep reading the same data within my main program.

Will see how this works in a bit.

Jeff

BTW, I am inspired by the effort you have taken to support this code library. Great stuff. I am mentoring a USFirst.org FRC robotics team, and am having a lot of fun working with the high school students on this kind of fun programming. A lot different from the code I wrote while in the military.

Oleg,
Thanks for the references. The approach I mentioned in earlier comment works just fine. The only minor glitch I found is if I stop moving the joystick then the JoystickEvents::OnGamePadChanged function does not get called and motion of my driven servo stops. As long as the joystick is changing values, things move just fine. So I thought about storing old joystick values to use when new data is not present. Trying this required me to determine and/or monitor polling frequency to calculate a time basis for desired rate of servo movement over time. Seeing your code from the Poll() function shed some light on a better way to try and implement smooth motion.

Is there any way to shrink the code size of the Wiimote code to fit on a 32Kb AVR like the Uno or the Leonardo? I don’t need things like hub support or any of the bluetooth profiles not supported by the Wiimote. This is one of the many times I’ve wished Atmel would release a chip with more than 32Kb flash in a small package… Mega1284P is probably going to be my best bet :/

Hello Oleg. I’m relative new using the Arduino Board and the USB-Shield. I’m using a Arduino Leonardo and the USB-Shield from circuits@home. I use it for reprogramming a Keyboardlayout. the programm function good. But when I plug the Arduino with the Keyboard in another PC it doesn’t function anymore. It should works as a Plug and Play. can you help me? Because with the old USB-Shield Library it function normally. I also wrote an art extention for a mouse function in the same programm but it doesn’t work like it should.
Thank You for your answer.
Carolina

I’m using a generic medical device – I need to send it simple commands like FF 02 01 and FF 04 00.
When I plug the device into the laptop, it presents itself as a COM (virtual serial port).
I’ve been able to use the board_qc test and everything works fine on my USB host shield.

What sketch in your library would you suggest that would enable me to send serial commands through a virtual port using your shield? Are there any modifications I would need to make to the code to get it to work with my specific device?

There are 3 USB to serial converter types supported by the library: CDC ACM, FTDI, and Prolific PL2303. First type can be determined by class/subclass/protocol (same as Arduino UNO ), other two have unique VID/PID. Run USB_Desc and post output here – I’ll take a look.

There are also other USB to serial converters which are not yet supported.

I got the FTDI example code to send a char [0xFF, 0x02, 0x01] to the medical device. It received the command and turned on. I can’t figure out how to send it a second command after a short delay in the program. I tried inputting a delay(500) and then copied and pasted the send code but it didn’t work. What aspects do I need to repeat, what can I erase?

Thank you for helping so far, if I can get this working our company plans on buying 50-100 units of your shield in the next year or two so I hope it’s worth your time.

This actually doesn’t work. I’m missing some key element to do that either clears the RX/TX lines or resets the board to send the 2nd command. If I hit reset on the arduino it will then send through the 2nd command. As if it was waiting in the buffer for some signal to push it through.

Is there some function I need to use between issuing multiple commands? Is there a function that could simply reset everything?

Using an executable that the company provided, I then monitored my serial port and found a sequence of events that the laptop sends to the device to operate it. Every command is prefaced with these events:
COM is open

Hi Oleg,
I’ve been trying to use an ACM device to receive data from (its a Serial USB thermistor) and transmit that data to an Android tablet. I am unable to recognize both the ACM device and the android at once (through a powered Hub). Both are able to be recognized and communicated to individually, but not simultaneously.
I setup the code like so:

USB Usb;
USBHub Hub1(&Usb);

ACMAsyncOper AsyncOper;
ACM Acm(&Usb, &AsyncOper);

ADK adk(&Usb,”Example”,
“Example”,
“Example,
“1.0″,
“1.0″,
“1.0″);

If I list the acm device first, it reads that just fine and ignores the android
If I list the ADK first, it connects to the android but ignores the ACM device.
Any thoughts on what I am doing wrong?
Thanks for ll your help!
Dan

It is in fact a 7 port hub. However, using two Hub instances makes no difference..
I switched to a 4 port hub and only one instance and still the same behavior.
This sounds similar to the 2 mouse issue I saw some people were having in the comments…could it be related?
Thanks again for your fast responses!

I bought the USB host shield for arduino a couple weeks ago, but I just started playing with it a couple days ago
I have arduino uno r2.
Somehow when I connected the usb host shield and arduino board together, then
plugged in my Bluetooth device/ PS3 controller, my computer did not recognize the devices that connected through the usb host shield at all.
I tried to run the sample codes from usb host shield library that I downloaded online, and they give me the same result whether I have the usb host shield
connected to the arduino uno board or not.

For example when I upload the example code “acm_terminal” with and without the usb host shield on, it didn’t give me any error.
And when I upload the example code “PS3BT” with and without the usb host shield on, it gave me

Thank you.
That’s probably the reason.
I borrowed my friend’s arduino uno r3 to test it out, and it works great.

But I run into another problem.
when I run PS3USB code, all the buttons work and also show on the serial monitor.
But, when I tried to run PS3BT code and link the Bluetooth and PS3 controller together, everything works except L2 & R2.

That is caused by your dongle not supporting EDR (Enhanced Data Rate). If it doesn’t support it, it won’t be able to read all the data from the PS3 controller.
You will have to get another dongle, as it’s a hardware issue with the dongle.

I am unable to get the USB host board to connect to my Arduino Mega 2560 R3 board. It does not get past the following code:

Serial.begin(115200);
while (!Serial);
if (Usb.Init() == -1) {
Serial.print(F(“\r\nOSC did not start”));
while (1); //halt
}

I always get the OSC did not start message.

I am using the XBOXRECV tutorial code to connect and Xbox 360 wireless controller to a wireless receiver. I am powering it with an external power supply and it works just fine on an Arduino UNO R3 board.

Thank you for the quick reply. The SPI signals on the Mega appear to be: D50:MISO D51:MOSI D52:SCK D53:SS I will jumper them to D12, D11, D13 and D10 respectively on the USB Host Shield and see if I can get it to work.

I hooked up logic analyzer to SPI pins (mega2560) with a USB mouse. As expected SPI clock was 8mhz. I see lots of 4 byte SPI events with 37.3 us between events. And about every 10.2 ms there is a more complex SPI sequence, poll request? I figured I’d just see SPI activty every 10ms. I was surpised at the higher rate of SPI events (NAKs?).

MAX3421E gets polled by several processes. 37us is likely the turnaround time of loop(), from which Usb.Task() is called. If you’re curious, run UsbTask() every millisecond or so, you’ll likely see traffic every millisecond or so. To see what it does look at the source code.

Hi,
Is there any example that can send for example {0×33 0×44} to a specific endpoint?
I’ve looked into the github examples and i didnt found anything that would do that. Also i´ve looked into the max3421e library to see that such functions exist in a similar way.
Im asking for this because i want to send instructions to another device that uses usb without using a pc.
Cheers

In USB, you can’t send random data to random endpoints. The device first needs to be initialized and initialization depends on the device type. Once this is done, the device class provides SndData() and RcvData() methods which can be used.

I understand how USB works, perhaps i didnt explain well what i wanted to ask.
I already have a program in windows that communicates to a device through usb, i know that to communicate you need the vid, pid, the endpoints to write on the host and device and their length, etc…
I wanted to ask if there was an example that could provide me some light on how to utilize the libraries available for any type of device. For example, ill show you some of the code i used on windows to send data to a usb device:

Hi
I’m using arduino uno with usb host shield 2.0.
I try to connect one keyboard and one mouse to the shiled one by one.
The keyboard work fine when I try to use the code “USBHIDBootKbdAndMouse”, but the six button can’t(No any output on serial Monitor).
On the other hand, I try to connect these through a usb hub,I combine the code “hub_demo” and “USBHIDBootKbdAndMouse”. The serial monitor seem detect the hub only.

Hello
I have a hard time making the USB Host Shield run with my Arduino (both Mini). USB seems to be properly initialized, but the task loop remains in “USB_DETACHED_SUBSTATE_WAIT_FOR_DEVICE” no matter if the board comes up with a device plugged in or the device is plugged in after power-up. I use an additional power source to support the board and tried a BT adapter, a mouse and a keyboard.

Thanks for your reply, Oleg. I have an Arduino Mini 3,3V. My USB Mini Shield has the following pins soldered to the Arduino: 9,10,11,12,13, VCC, GND, RAW, RST. The label on BT Adapter says “GBU521″. The additional power source is a regulated lab power adapter with up to 1.5A which I’ve set to 5V and connected to the RAW pin. USB library is on commit b82835c877adecf507312b742dd687e2ea03628f, which should be the most recent.

Hello, im trying to get an USB HUB working with Arduino MEGA ADK board, but with the HUB_demo i only get back the HUB itself. Is there anythink special needed for ADK Board? Maybe some change in one of the library? The devices i want to connect via HUB work fine with the board itself(barcodescanner & multimeter). Thanks a lot!
Fabian

I have the USB shield and Arduino Mega working with a missile launcher. If I insert a USB hub between the USB shield and the launcher, the commands are sent but the launcher does not respond. I assume some USB hub code must be added but can find no examples. I assume usbhub.h must be included and some usb addressing code must be added, but what and where? Please help, thank you. ……. Gary

I am using a sketch that uses the MissileLaunch library. Both call USB.h The sketch calls the USB Init via the MissileLaunch library. So do I modify the sketch or library or both? All of this code was copied from GitHub. The reason to use a hub is to add a USB game controller (joystick) to control the launcher instead of the serial input. I don’t understand how the hub instance that you presented can be applied to missile launcher code. It is probably simple once one knows how but I don’t see it.
Thanks again……. Gary

I tried the hub_demo example. It worked but only displayed the descriptors for the hub, not for the launcher device plugged into the hub. I noticed a “stop” in the loop code. When the stop was deleted, the descriptors are displayed forever but after the first 4 hub descriptor sets the launcher descriptors were printed. I put in a counter to allow the loop to run 5 times and then stop. Then the launcher descriptors are seen after the 4 hub descriptor sets are displayed.
Not sure why. Now to get the launcher code to work with the hub?!?!…. Gary

It works. I needed to run hub_demo to learn the USB address for the launcher. That address is used in the USB command packet.
Both the missile library and the sketch need to be modified. I rewrote the sketch without using the library that now works the launcher through the USB hub. Here is the code:
//
// USB Missile Launcher
//

Hi Oleg,
Im trying to connect an Arduino UNO and an Arduino USB Host Shield(Sparkfun) to a Xenon 1900 barcode scanner using the usb host shield library version 2.0. With the “acm_terminal” example the barcode scanner turns on and prints the correct info to the Serial Monitor, but after a few succesful reads the scanner turns off, and the only way to make it work again is to restart the arduino. Sometimes it goes off after being in stand-by for a while too.

I can make it work using that code but i get the same problem.
They mention that the Class, Subclass and Protocol are relevant, and they should be:

Intf. Class: 03
Intf. Subclass: 01
Intf. Protocol: 01

But the “USB_desc” code shows that the Xenon 1900 cofiguration is:

Intf. Class: 03
Intf. Subclass: 00
Intf. Protocol: 00

Could that be the problem? And if it is, is there a way to fix it?

PS: The Xenon 1900 can be configured as HID keyboard, HID POS, and USB Serial. All the example codes work with the correct barcode configuration but the scanner turns off with all of them after a few succesful reads.

I’m using Arduino Mega 2560 in Linux.
I’m testing the code sample provided but I cant’t get show all usb connected to the hub(I connected 2 pendrives in FAT32). I get the impression that displays only information hub or is giving error.