Posts

USB Host Shield library Version 2.0 released.

Hub demo

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:

  1. Only 5 Arduino pins are now required for USB Host Shield to function – 3 standard SPI pins (SCK, MISO, MOSI) and 2 remappable pins (SS and INT).
  2. 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.
  3. 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:

  • Human Interface Device AKA HID. Keyboards, mice, game controllers, bar code scanners, magnetic card and RFID readers – the list goes on. Initialization, polling, report descriptor parsing, as wellas reading and sending reports is possible.
  • 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.
  • Android ADK protocol, recently introduced in versions 3.1 and 2.3.4 of Android OS. Simple lightweight protocol for bi-directional communication with Android phone or tablet.

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.

The following lines:

USBHub  Hub1(&Usb);
USBHub  Hub2(&Usb);
USBHub  Hub3(&Usb);
USBHub  Hub4(&Usb);

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.

Oleg.

382 comments to USB Host Shield library Version 2.0 released.

  • Toh. E

    I’ve been trying to write the codes for a self balancing robot with an arduino Uno and MPU6050 for the balancing control. A separate PS3 will be used to do steering and manouvering via the USB host shield and PS3 controller (via blue tooth dongle). My current issue is code length exceeding the Unocapacity. Just the code length and library to get the PS3 blue tooth working in itself is already 19,648 bytes out of the 32,256 bytes (60%)(after lots of trimming). I’ve been trying very hard to cut down on the unnecessary components of the PS3BT libraries.

    Since for a start, I am trying to save space, I will be using just the leftHatY to use it to influence my forward/backward maneuvering.

    You can see I have deleted lots of the other PS3 controller buttons but still I am using too much space. I need to bring it down to at least 51% so that I can fit the other 49% for my MPU6050 library and my PID control codes. I understand that Serial.printing out the leftHatY is also not necessary, but even if I remove the few lines, I am still far off from the target size 🙁

    May I check betweem, USB and PS3BT and SPI libraries, where are the places where I can further trim off the codes, and if so how, to squeeze as much out of my Uno please?

    Thanks.

    #include
    //#include

    // Satisfy the IDE, which needs to see the include statment in the ino too.
    #ifdef dobogusinclude
    //#include
    #include
    #endif

    USB Usb;
    //USBHub Hub1(&Usb); // Some dongles have a hub inside

    BTD Btd(&Usb); // You have to create the Bluetooth Dongle instance like so
    /* You can create the instance of the class in two ways */
    //PS3BT PS3(&Btd); // This will just create the instance
    PS3BT PS3(&Btd, 0x00, 0x1a, 0x7d, 0xda, 0x71, 0x0f); // This will also store the bluetooth address – this can be obtained from the dongle when running the sketch

    //bool printTemperature;
    //bool printAngle;

    void setup() {
    Serial.begin(115200);
    #if !defined(__MIPSEL__)
    while (!Serial); // Wait for serial port to connect – used on Leonardo, Teensy and other boards with built-in USB CDC serial connection
    #endif
    if (Usb.Init() == -1) {
    Serial.print(F(“\r\nOSC did not start”));
    while (1); //halt
    }
    // Serial.print(F(“\r\nPS3 Bluetooth Library Started”));
    }
    void loop() {
    Usb.Task();

    if (PS3.PS3Connected){ //|| PS3.PS3NavigationConnected) {
    if (PS3.getAnalogHat(LeftHatX) > 137 || PS3.getAnalogHat(LeftHatX) 137 || PS3.getAnalogHat(LeftHatY) 137 || PS3.getAnalogHat(RightHatX) 137 || PS3.getAnalogHat(RightHatY) < 117)
    Serial.print(F("\r\nLeftHatX: "));
    Serial.print(PS3.getAnalogHat(LeftHatX));
    Serial.print(F("\tLeftHatY: "));
    Serial.print(PS3.getAnalogHat(LeftHatY));
    }
    }
    }

  • Hi Oleg,

    I am not able to get the USB Host library (v2.0) to work with a Sparkfun FTDI Basic break-out USB bit (https://www.sparkfun.com/products/9716) on an Arduino Pro Mini. Reading these comments, I am assuming it’s not supported by your library and differs from the shield that you offer in some fundamental way, so I am looking at getting the USB Host shield for the Mini, however I was wondering if it comes as a 5v version? The rest of my setup – inc. the Pro Mini – is 5v so it would be great if I could get a 5v variant of your USB Host shield! Is this possible? Otherwise, is there any other way I could get the library to work with my USB shield in order to use your camera control library?

    Much thanks!

    Tom

  • Jerry

    Hi Oleg-

    I have successfully ran the board_qc sketch, and gotten a response.

    I am simply trying to connect a USB keyboard.

    I have your USB Host Mini shield (with the +5v VBUS mod/jumper implemented to power the keyboard)

    I then uploaded the USBHIDBootKbd example…

    Here are my questions/behavior I want to test in the USBHIDBootKbd example.

    1.) I took the USB keyboard, and plugged it into my laptop to test things out.

    a.) when I plug the keyboard in normally, (without USB Host shield), both the laptop keyboard & the USB keyboard both ‘type’ text in the open application (notepad for example)

    b.)when I plug in the USB keyboard using the USB Host shield (and the USBHIDBootKbd example sketch loaded).. I see the data in the serial monitor:

    Start
    DN >0A05<
    ASCII: b
    ..etc..etc.

    but the USB keyboard doesnt type/pass anything through to the applicaiton (notepad was used again and was in focus).. although I could still see the serial monitor data coming through? Is there a specific method/function/command to actually send the data/text typed from the USB keyboard TO the PC/application?

    2.) Is there a way to stop all data from passing over to the PC/application/device?

    Example: if I have a button/switch connected to an open/free I/O pin.. and when pressed, it stops all keypresses from being passed to the PC/device/app

    3.) Can you conditionally chek the kaypress/data that is being sent and choose to send it or not? or even replace it?

    Example 1:
    If I press 'P', can I detect that shift + p keys were presssed/sent, and then NOT send it at all.. (skipping/discarding it, while continuing along with the rest of the text/data being sent to the PC/device?

    Example 2:
    If I press the character/key 'p', can I detect that, and then always send a capital 'P' *or another character, any character for that matter (say the 'o' character for example)

    3.) As a first step,…when looking at the example sketch, I am was not sure where to 'hook' in, to start checking the 'character/data' being sent..

    I tried to add this to the OnKeyPressed() function..

    mykey = (char)key;
    if(mykey == "p"){
    //Keyboard.print("M");
    Serial.println("P");
    }

    but I get this error:

    ISO C++ forbids comparison between pointer and integer [-fpermissive], but I am not sure how?

    If you could help answer the 2/3 questions, and help me understand how to use the library/example better I would appreciate it!

    thanks!
    -Jerry

  • Jerry

    Well thats for allowing the question to be posted at least! 🙂

    Any other members/users here that can help with the questions?

    Changing:
    if(mykey == “p”){

    to:
    if(mykey == ‘p’){

    (single quotes) seemed to do the trick for getting the: “ISO C++ forbids comparison between pointer and integer [-fpermissive]” error to go away..

    but what I dont understand currently is:

    1.) When connected to my netbook/laptop.. why does the external keyboard (thats connected to the USB Host Shield, ONLY output to the Serial Monitor.. and not the actual application that is open?, In this example I had Notepad open expecting to see some keys being typed/passed along from the keyboard connected to the USB Host shield?) IS it because of the two keyboards? (the built in one and the 3rd party one connected to the USB Host shield?… and when used on a device or PC that will only have this USB Host connected keyboard, it will behave fine?)

    (doesnt do much good to only be able to send data to the serial monitor! haha) 🙂

    Is it my set-up? plugging in a keyboard to e netbook/laptop that is the problem?
    or
    Is it that I need to use some sort of method to actually pass the keypress to the end device (in this test a PC with Notepad application open)

    Thats a pretty direct question.. Is it supposed to output the key presses to the PC/application? or is the example only supposed to output to the Serial Monitor ONLY? IF it supposed to output to the monitor ONLY in the USBBootKbd example sketch, then what is the method to actually pass the key pressed to the PC/end device?

    Is there documentation on the methods available for use in this class/library? (or just the example sketches?)

    If not.. do I look in the .h or .cpp files for this info?

    thanks!

  • I’m looking for a tutorial on running USB Host on Arduino MEGA ADK (not connected to Android).
    My intent is to create a host for a MIDI instrument.
    Experience-wise, I’ve been a professional programmer for decades, including C++, but I’m relatively new to Arduino and Git.
    I was able to run a sketch exercising a MIDI shield (serial MIDI out via standard 5-pin MIDI connectors).

    I’m running Arduino IDE 1.6.5 on Mac OSX 10.9.5 Mavericks.
    I installed USB Host Shield Library 2.0 version 1.1.0 from the Arduino IDE Library manager.

    Whenever I try to compile and example sketch from the internet, I get compile errors.
    for example, I get the following error from the hub_demo sketch
    ====
    Arduino: 1.6.5 (Mac OS X), Board: “Arduino Mega ADK”

    hub_demo.ino:2:24: fatal error: pgmstrings.h: No such file or directory
    compilation terminated.
    Error compiling.

    This report would have more information with
    “Show verbose output during compilation”
    enabled in File > Preferences.
    ====

    Errors I’ve gotten from other sketches say that certain #includes should not be there,
    or certain other files can’t be found.

    I admit I don’t really know what I’m doing, but I don’t know where to go to find out.
    For example, how should I know where to put the pgmstrings.h file?
    Or if I need to get something from GitHub,
    how should I know where to put it and how to “connect” it to the IDE?

    Thanks for your help

  • Jerry

    I believe this is the current library to use:
    https://github.com/felis/USB_Host_Shield_2.0/archive/master.zip

    I dont anything about MIDI.. and done use a MEGA.. but it sounds like the library isnt current or perhaps not installed correctly..
    (but if you used the manager to DL and install it.. I’m not sure what could be wrong?)

    If you add the library manually, you sometimes get a folder within a folder (nested).. you want the directory INSIDE of that.. so that the files/examples are in the _root of the directory once opened..

    Not USB2.0 >> USB2.0 >> example/files..etc

    Just:

    USB2.0 >> examples/files..etc

    Once the library is installed correctly you shouldnt need to place any files anywhere (I dont believe)

  • Thanks. I was able to get the hub_demo sketch working by placing pgmstrings.h in the hub_demo folder created by the IDE when I opened hub_demo.ino the first time. Now I have another question.

  • hub_demo not seeing devices connected thru a hub
    I’m running hub_demo from: https://www.circuitsathome.com/mcu/usb-host-shield-library-version-2-0-released
    Config: Arduino MEGA ADK, Max OSX 10.9.5 Arduio IDE 1.6.5
    After powering the MEGA ADK @ 12v 2A, I was able to get the descriptors for all my devices, one at a time, when plugged directly into the MEGA ADK. Also I got a descriptor for my Belkin 4-port hub powered @ 5v 2.5A.
    But the sketch is not providing any info for devices connected TO the hub. Also, with the hub connected to the MEGA ADK,
    and ADK connected directly to the MAC USB port,
    the lights on the hub indicating a connected device do not light up when devices are plugged in to it. (They do light up and connected devices work when the hub is connected directly to the Mac, so I know the hub is good.)
    Any ideas what I should be looking for?

  • Jerry

    I’m not 100% clear on your set-up.

    (and I’m still trying to get some basic answers of my own..like how get the data/key press from a USB keyboard passed onto the PC/device its connected to..just shows up in serial monitor)..

    anyways.. from reading around here, try powering externally. I dont think the usb can provide enough current for all these devices perhaps?

  • Perhaps my config description was not clear, but yes, I am providing external power to both the Arduino Mega ADK board and to a 4-port hub to which the devices are attached.
    I was actually able to get the port status lights to go on briefly, (indicating “fully operational,” whatever that means) but not consistently.

    Right now I’m searching for documentation on using the library;
    the “documentation” link at http://felis.github.io/USB_Host_Shield_2.0/
    is circular!

  • I’m trying to use the USB Host Shield Library to program a MEGA ADK.
    Where is the documentation or source for the USB Host Shield Library 2.0 that is in the Arduino IDE 1.6.5?

    The hub_demo example on:

    https://github.com/felis/USB_Host_Shield_2.0/blob/master/examples/hub_demo/hub_demo.ino

    contains a call for Usb.Init (CAPITAL I),

    but the source I found found at:

    http://felis.github.io/USB_Host_Shield_2.0/_usb_8cpp_source.html#l00424

    doesn’t have such a call (It has only USB::init(…) [small i ).

    But the sketch compiles and runs.

  • Jerry

    I think my initial understand of the shield/library was flawed.

    It does -not- pass on the key strokes to the PC/end device…. as is? (by default)… correct?

    You need to grab/parse this data, and pass it along using the Arduino to do.. (in this case a Leonardo based board.. with built-in emulated USB HID)… correct?

    Maybe this has been done before somewhere? And I dont need to re-invent the wheel? (per se`)

    I am currently doing Keyboard.begin().. and then sending over the key press/data to the PC using Keyboard.write()..etc.. but havent gotten to passing over modifiers/control keys..etc..

    Is this the correct approach? Or is there a better way to achieve all of this? I want to check/parse then pass along ALL keyboard presses. (I am checking if a lower case p is pressed and passing along a capital ‘P’… or if o is pressed.. not pass that along AT ALL)

    I have not figured out how to get a return (carriage return) passed over though? (when the enter key is pressed)

    The short, one word/one line answers are killing me!!! 🙂

    thanks!

  • Josh

    In the event it is helpful for 3.0 development, I’ve encountered a rather bizarre issue when using USB Host Library 2.0 with the new Symbol LI2208 barcode scanner. Following your barcode scanner post, the barcode scanner was not being successfully detected by the library. I tracked the issue down to the Init function in hidboot.h on the line:

    byte retval = pUsb->getConfDescr(bAddress, 0, i, &confDescrParserA);

    For a reason unknown to me, this fails when it reaches USB::InTransfer and then USB::dispatchPkt with rcode equal to hrNAK. However, if you manually get the config description size, then the entire config description before explicitly calling the config parser on the result, it works. In other words, replace the line above with:

    char confBuf[ 64 ];
    char* confBufPtr = confBuf;
    byte conf = 0;

    USB_CONFIGURATION_DESCRIPTOR *ucd = reinterpret_cast(confBuf);
    rcode = pUsb->getConfDescr( bAddress, 0, 9, (uint8_t)conf, (uint8_t*)confBuf ); //get total length

    if(rcode) {
    //Serial.println(“getConfDescr size not ready”);

    }
    else {
    rcode = pUsb->getConfDescr( bAddress, 0, ucd->wTotalLength, (uint8_t)conf, (uint8_t*)confBuf ); //get the whole descriptor

    if(rcode) {
    //Serial.println(“getConfDescr not ready”);
    }
    else {
    confDescrParserA.Parse(ucd->wTotalLength, (uint8_t*)confBufPtr, 0);
    break;
    }
    }

    Any idea why this works? Let me know if there are any additional tests I can perform to help determine what is causing the problem.

    Also, many thanks for an incredibly useful library!

    • Can you post your configuration descriptor?

      • Josh

        I didn’t see anything obvious.

        LI2208:

        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
        Class: 03
        Subclass: 01
        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: 03

        LS2208 (previous model barcode reader which works without modifying the library):
        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: 05E0
        Product ID: 1200
        Revision ID: 0201
        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: 04
        Attr.: 80
        Max.pwr: C8
        Interface descriptor:
        Intf.number: 00
        Alt.: 00
        Endpoints: 01
        Class: 03
        Subclass: 01
        Protocol: 01
        Intf.string: 00
        Unknown descriptor:
        Length: 09
        Type: 21
        Contents: 100121012241000705
        Endpoint descriptor:
        Endpoint address: 81
        Attr.: 03
        Max.pkt size: 0008
        Polling interval: 0A

  • Matt

    Is there any example code anywhere which demonstrates reading from multiple HIDs on a Hub?

    The Hub example code just looks at hubs, and ignores the devices. The HID example works if you instantiate a hub device, but it only collects reports form the first device, and there’s no obvious way to collect reports from others.

  • joska

    Matt: I believe I have the same problem as you with hubs. If I use the hub demo it will only enumerate the hub, not any devices connected to it. Also, if I use the HID keyboard+mouse demo, it will only work with devices connected directly to the USB host shield. The same devices are not found if connected via a hub.

    I’ve tried two different hubs, unfortunately not powered hubs. But I’m feeding VBUS on the shield with 5V from a 30A 5V regulated PSU so I believe there should be enough juice…

  • Simon

    @Matt

    Ive managed to get 2xHID devices (joystick and pedals) to work with the following strategy:

    USB Usb;
    USBHub Hub(&Usb);
    HIDUniversal Hid(&Usb); //Joystick
    HIDUniversal Hid2(&Usb); //pedals
    //HIDUniversal Hid3(&Usb); //Headtracker

    JoystickEvents JoyEvents;
    PedalEvents PedEvents;
    //HeadEvents HDEvents;

    JoystickReportParser Joy(&JoyEvents);
    PedalReportParser Ped(&PedEvents);
    //HeadReportParser Head(&HDEvents);

    void setup() {

    Serial.begin(115200);
    Serial.println(“Start”);
    if (Usb.Init() == -1) lcd.print(“OSC did not start.”);
    delay(200);

    if (!Hid.SetReportParser(0,(HIDReportParser*) &Joy)) ErrorMessage(PSTR(“SetReportParser”), 1 );
    if (!Hid2.SetReportParser(0,(HIDReportParser*) &Ped)) ErrorMessage(PSTR(“SetReportParser”), 1 );
    // if (!Hid3.SetReportParser(0,(HIDReportParser*) &Head)) ErrorMessage(PSTR(“SetReportParser”), 1 );

    etc, etc

    You will see that i have commented out the 3rd instance (for a usb HID head tracker). This method does not extend to 3 devices it seems. Cant work out how to parse 3 or more HID reports.

    The above method has a flaw too : You have to power up the USB host then plug the devices in after powered up in the order they are listed ie plug in joystick then the pedals. Otherwise the wrong parser is allocated.

    Cant find anything in the library to match the parser with the HID device. Any ideas?

  • Jeff Williams

    My goal is to have 2 BT dongles on a hub and have the Arduino use both of them to send slightly different data to 2 endpoints concurrently. I have what seems to be the same issue as Joseph Austin above where with an Mega ADK and a powered hub connected I do not get a list of all devices on the hub, I only get the details of the hub itself. But the hub was working so I moved on to just trying to get 2 BT dongles to work. Each dongle works on its own in the hub or in the ADK USB slot. What I can’t seem to get to work is for both BT dongles to be detected and be usable.

    Should this work? 2 BT dongles on hub?

    In the mean time I am trying to work backward in the code to determine how the BTD code enumerates and picks a dongle and see if a second instance will find the next dongle if one is already taken by a BTD instance.

    Thanks, Jeff

    #include
    #include

    // Satisfy the IDE, which needs to see the include statment in the ino too.
    #ifdef dobogusinclude
    #include
    #include
    #endif

    USB Usb;
    USBHub Hub1(&Usb); // Some dongles have a hub inside
    BTD Btd1(&Usb); // You have to create the Bluetooth Dongle instance like so
    BTD Btd2(&Usb); // You have to create the Bluetooth Dongle instance like so

    SPP SerialBT1(&Btd1, “DAC1”, “0000”); // You can also set the name and pin like so
    SPP SerialBT2(&Btd2, “DAC2”, “0000”); // You can also set the name and pin like so

    bool firstMessage = true;

    void setup() {
    // put your setup code here, to run once:
    Serial.begin(115200);
    #if !defined(__MIPSEL__)
    while (!Serial); // Wait for serial port to connect – used on Leonardo, Teensy and other boards with built-in USB CDC serial connection
    #endif
    if (Usb.Init() == -1) {
    Serial.print(F(“\r\nOSC did not start”));
    while (1); //halt
    }
    Serial.print(F(“\r\nSPP Bluetooth Library Started”));

    }

    void loop() {
    // put your main code here, to run repeatedly:
    Usb.Task(); // The SPP data is actually not send until this is called, one could call SerialBT.send() directly as well
    if (SerialBT1.connected) {
    if (firstMessage) {
    firstMessage = false;
    SerialBT1.println(F(“Hello DAC1 from Arduino”)); // Send welcome message
    SerialBT2.println(F(“Hello DAC2 from Arduino”)); // Send welcome message
    }

    }

    • Only create one BTD instance and then use it as argument for both SPP instances:

      BTD Btd(&Usb);
      SPP SerialBT1(&Btd, “DAC1″, “0000″);
      SPP SerialBT2(&Btd, “DAC2″, “0000″);