Using multiple dongles with MetaHub

I recently purchased a MetaHub so that I can collect from multiple MMRs. The eventual goal is to stream quaternions from 8 boards simultaneously. I'm using the two USB BLE dongles that came with my MetaHub. I have written a shell script that starts streaming using a config file as outlined in the README file. This method works perfectly, but only when I use 4 boards or less. When I try it with 5 boards it works, but the CSV file from the 5th board is only half the size of the other 4 because the sampling frequency for that 5th board is not consistent - sometimes there is up to 100 ms between samples.

From other posts here, I believe that the problem is that I need to explicitly assign the boards to both BLE dongles and that without doing this I am using only one dongle and overloading it. I believe that to use both dongles, I need to set the environment variable NOBLE_REPORT_ALL_HCI_EVENTS=1 and then start the streaming from the command line (or my shell script) like so:

sudo NOBLE_HCI_DEVICE_ID=1 npm start -- --device "C6:EE:8B:E0:4B:24=TRNK" --sensor Quaternion='{ "accRange": 8.0, "gyroRange": 1000.0 }' --command stream --no-graph

This is where I run into trouble. If I do not include the NOBLE_HCI_DEVICE_ID=1 in this line it works fine, but when I do include it, I get an error:

info: Connecting to device mac=C6:EE:8B:E0:4B:24
warn: Could not find device mac=C6:EE:8B:E0:4B:24
error: Failed to connect to any devices, terminating app

The problem may be with how I am setting the environment variable NOBLE_REPORT_ALL_HCI_EVENTS=1. I'm not sure of how to do this properly, but I have added

export NOBLE_REPORT_ALL_HCI_EVENTS=1

at the beginning of my shell script. I am also not sure if I need to run noble with a statement like:

sudo setcap cap_net_raw+eip $(eval readlink -f /usr/bin/node)

I can enter this from the command line but it seems to have no effect.

The dongles seem to be recognized and operating. hciconfig returns the following:

hci2:   Type: Primary  Bus: UART
    BD Address: B8:27:EB:30:AB:58  ACL MTU: 1021:8  SCO MTU: 64:1
    UP RUNNING 
    RX bytes:5007791 acl:157582 sco:0 events:1432 errors:0
    TX bytes:26534 acl:1524 sco:0 commands:222 errors:0

hci1:   Type: Primary  Bus: USB
    BD Address: 00:1A:7D:DA:71:10  ACL MTU: 640:4  SCO MTU: 64:8
    UP RUNNING 
    RX bytes:1410 acl:0 sco:0 events:101 errors:0
    TX bytes:3410 acl:0 sco:0 commands:101 errors:0

hci0:   Type: Primary  Bus: USB
    BD Address: 00:1A:7D:DA:71:10  ACL MTU: 640:4  SCO MTU: 64:8
    UP RUNNING 
    RX bytes:1062 acl:0 sco:0 events:50 errors:0
    TX bytes:943 acl:0 sco:0 commands:50 errors:0

If anyone has advice on how I can solve this problem, it would be much appreciated. Thanks!

Comments

  • There is an example of this here: https://github.com/mbientlab/MetaWear-SDK-JavaScript/blob/master/examples/led_dongle.js
    I want you to first get each unique hci device working to blink the led on the same sensor. Then take it from there.

  • Thank you for your reply, @Laura. This sounds like a good plan and I can see how this is supposed to work from reading the example code. Unfortunately I have not yet been successful getting the LED to blink. I'm probably making a simple mistake because I don't have much experience with JavaScript.

    I went through the JavaScript APIs tutorial and installed everything with no errors. Metawear appears to have installed successfully, because when I enter node and type the following:

    node > require('metawear')

    I get all the metawear functions etc. I am now trying to blink the LED using this script (myled.js), just a slightly modified version of the led.js example script:

    console.log("GOT HERE 1")
    
    var MetaWear = require('metawear');
    
    console.log("GOT HERE 2")
    
    // If you know the MAC address, you can uncomment this line
    MetaWear.discoverByAddress('C6:EE:8B:E0:4B:24', function(device) {
    // MetaWear.discover(function (device) {
      console.log("GOT HERE 3")
      device.connectAndSetUp(function (error) {
        console.log("GOT HERE 4")
        var pattern = new MetaWear.LedPattern()
        MetaWear.mbl_mw_led_load_preset_pattern(pattern.ref(), MetaWear.LedPreset.BLINK)
        MetaWear.mbl_mw_led_write_pattern(device.board, pattern.ref(), MetaWear.LedColor.GREEN)
        MetaWear.mbl_mw_led_play(device.board)
        setTimeout(function () {
          device.on('disconnect', function () {
            process.exit(0)
          })
          MetaWear.mbl_mw_debug_reset(device.board)
        }, 5000)
      })
    })
    
    console.log("GOT HERE 5")
    
    process.exit(0)
    

    The MAC address in the file belongs to one of my sensors that I have connected to previously using this address. To run my script, I navigate to the examples folder where this script is and run it by typing

    node myled.js

    I'm not yet trying to specify the BLE dongle - I want to blink the LED with the default HCI device first. When I run the script, the LED does not blink and I get this output:

    GOT HERE 1
    GOT HERE 2
    GOT HERE 5
    

    I get the same result when I comment the line with the MAC address and uncomment " MetaWear.discover(function (device) {" and also when I try to run the script with "sudo node myled.js". Again, I have the sense that I am missing something very basic here regarding how to use JavaScript to run metawear routines. Everything makes sense and I am not getting any errors, but I cannot understand why there is seemingly no attempt to connect to the sensor. Thank you for your patience and any advice on this would be much appreciated.

  • Hi @Laura -- I'm more comfortable with Python so I decided to see if i could get a sensor to blink its LED using Python instead, and I was able to get this to work! I had to use the Pi's onboard bluetooth controller to make this happen. Here is the script I used:

    # usage: python led.py [mac]
    from __future__ import print_function
    from mbientlab.metawear import MetaWear, libmetawear
    from mbientlab.metawear.cbindings import *
    from time import sleep
    from threading import Event
    import os
    import sys
    
    ### using this address for the dongle controller doesn't work
    # device = MetaWear(sys.argv[1], hci_mac="00:1A:7D:DA:71:10")
    
    ### using this address for the Pi controller works
    device = MetaWear(sys.argv[1], hci_mac="B8:27:EB:30:AB:58")
    
    device.connect()
    print("Connected")
    
    pattern= LedPattern(repeat_count= Const.LED_REPEAT_INDEFINITELY)
    libmetawear.mbl_mw_led_load_preset_pattern(byref(pattern), LedPreset.BLINK)
    libmetawear.mbl_mw_led_write_pattern(device.board, byref(pattern), LedColor.GREEN)
    libmetawear.mbl_mw_led_play(device.board)
    
    sleep(5.0)
    
    libmetawear.mbl_mw_led_stop_and_clear(device.board)
    sleep(1.0)
    
    device.disconnect()
    sleep(1.0)
    

    Note that my success depended on which hci_mac I used. It seems that I may just be having a bluetooth problem that is exactly the same as the one described in this discussion - I'm seeing exactly the same behavior described there. That user solved their problem by purchasing new dongles, which I am willing to try, but I would like to retry the bluetooth setup first before I do that. If I am successful at blinking the LED on a sensor from each dongle, then I think I'll be able to write a Python script that starts streaming on 8 sensors across two dongles. I'll continue working on this, but I would be grateful for any suggestions you have to offer. Thanks!

  • Use bluetoothctl to find out why 00:1A:7D:DA:71:10 isn't working.

    Also you have two controllers with the address "00:1A:7D:DA:71:10", remove one of your dongles as Python doesn't know which is which and rerun your script using that dongle.

  • Thanks, @Laura. When I use bluetoothctl, the controller on the Pi is fine, but when I select 00:1A:7D:DA:71:10 it appears that there are no devices to connect to and pair with (even though in reality there are plenty). "show" produces exactly the same description for both controllers except for the MAC address, name, alias, and class (one is 0x400000 and one is 0x480000).

    I think the problem is with how I setup bluetooth in the first place. I saw too late that you cautioned against doing the setup with both dongles inserted. I also wonder if it could be a problem with inconsistencies between sudo and no-sudo commands used during the installation and updating. I'm repeating everything with only one dongle inserted and doing both sudo & no-sudo.

    I still cannot blink the LED using the dongle controller, but now what I get when I run the script is

        mbientlab.warble.WarbleException: Timed out while trying to connect to remote device        
    

    It feels like I am getting closer. I will try a few more things, including switching dongles, before I try purchasing new dongles, which seemed to solve the problem for the other users who reported my same problem.

  • Make sure to only have 1 dongle and get that dongle working first before using another.

  • @Laura - I ordered new dongles and while I was waiting for them I tried just about everything I could think of to get my dongles to work. Nothing worked. The dongle adapters showed up, but I could never get them to scan for devices successfully.

    Today my new dongles (different manufacturer) arrived and they worked right away. I was able to blink the LEDs using different adapters and I modified one of the Python examples so that I could simultaneously stream from two MW boards using the two dongles. I think I am good now - I can see how to proceed with the Python code. I believe I need to write Python code (or JavaScript) to achieve my goal of simultaneously streaming 8 boards using 2 adapters, because I don't think I am able to do this using command-line calls as in the readme file. With the command line, I can start 4 boards streaming on one adapter, but they have to finish before I can start the second 4 boards streaming.

  • @Steve26
    Thank you for the update.
    While I don't have enough information to say why the previous dongles worked or didn't work, it is likely that the drivers weren't installed properly (or maybe they were just bad...).
    You will have to write your own code to get all the boards working at the same time; I recommend our Javascript APIs.

  • @Laura - Thanks. I've seen you recommend JavaScript before over Python before, and I was just wondering how strong this recommendation is. I'm more comfortable with Python and it would allow me to integrate the MetaWear code with some other data analysis routines I have already written in Python. Before I get too far into this, is Python a choice I will later regret, or does JavaScript offer just a slight advantage?

  • Python is great but the bluetooth third party libraries we use are more robust and reliable on Javacript.
    If you are doing something simple, Python is the way to go. If you have multiple dongles and sensors, Javascript is the way to go.

Sign In or Register to comment.