High Frequency Streaming - Callback Problem

Hi,

I am trying to stream data from 2 devices simultaneously using the C++ API but I am having some problems.
To be more specific, I can connect to both devices but when I enable acceleration sampling, data are processed only from one of
the device structs. Through some debugging I have confirmed that the packets from both devices arrive to my application
correctly and non-stop but for some reason the callback function responsible for handling the received data of the one
sensor is not called by the MetaWear library. This means that the function responsible for processing GATT notifications
receives the packet correctly but when your handler is called nothing happens.
When I connect to only one of the devices I can stream data without any problem (for both devices).

Please note that I have enabled high frequency streaming to both devices using the following functions before enabling acceleration sampling and starting streaming:
mbl_mw_acc_set_odr(board, 200.0f);
mbl_mw_acc_set_range(board, 4.0f);
mbl_mw_acc_write_acceleration_config(board);
mbl_mw_settings_set_connection_parameters(board, 7.5f, 7.5f, 0, 6000);

Something interesting that I have noticed is that there is a certain pattern at the beginning of the stream. From the device that cannot
process data correctly, 3 "smaller" packets arrive, then 1 "bigger" and the callback function is called 3 times. This happens 3 or 4
times and then the "bigger" packets simply stop and the callback function is never called again.

The "smaller' packets are something like this: [ 0x3 0x4 0xe4 0x5 0x6d 0x1 0x27 0x1f ]
whereas the "bigger" ones are like this: [ 0x3 0x1c 0xe4 0x5 0x6d 0x1 0x27 0x1f 0xfc 0x5 0x41 0x1 0xf3 0x1e 0x6 0x6 0x21 0x1 0x2a 0x1e ]

I am using Ubuntu 16.0.4, my BlueZ version is 5.42 and the devices that I use are MetaWearRG sensors.

Comments

  • Post the full code you are running.

  • Hi Eric.

    Thanks for your response. I cannot post the entire code that I am running because I have created an entire API over your library and a complex demo application that involves a Bluetooth Low Energy library. However I can post the parts that I believe that you need. (next post)

    One interesting workaround that I have found is to enable high frequency streaming but use the acceleration_data_signal instead of packed_acceleration_data_signal. This way your handler seems to recognize the "smaller" packets that I have talked about and call the callback function without any problem. I don't know if this is the correct way but it seems to work for some reason.

  • edited May 2018

    The following code is for streaming from the accelerometer:

        /* Set parameters for High Frequency Streaming */
        mbl_mw_acc_set_odr(board, 200.0f);
        mbl_mw_acc_set_range(board, 4.0f);
        mbl_mw_acc_write_acceleration_config(board);
    
        /* Reduce the max connection interval to 7.5ms. */
        mbl_mw_settings_set_connection_parameters(board, 7.5f, 7.5f, 0, 6000);
    
        /* Create a callback function */
        auto data_handler = [](void * context, const MblMwData * data) -> void
        {
            if (context == NULL) return;
            auto acceleration = (MblMwCartesianFloat*) data->value;
    
            /* Formula: theta = arcsin(a/g) */
            int angle = 90;
            errno = 0;
            std::asin(acceleration->x);
            if (errno != EDOM) angle = std::abs(static_cast<int> (asin(acceleration->x) * (180 / 3.14159)) - 2);
            //std::cout << "Angle: " << angle << std::endl;
    
            PressureSensor * sensor = static_cast<PressureSensor *> (context);
            if (sensor->streamCallback != NULL) sensor->streamCallback(angle);
        };
    
        accSignal = mbl_mw_acc_get_packed_acceleration_data_signal(board);
    
        /* Subscribe the callback as a signal handler */
        mbl_mw_datasignal_subscribe(accSignal, this, data_handler);
    
        /* Start streaming */
        mbl_mw_acc_enable_acceleration_sampling(board);
        mbl_mw_acc_start(board);
    

    And then the code responsible for handling the GATT characteristic notifications is the following. Please pay no attention to mutexes and semaphores, they are used for thread safety. Also I use an std::map called notify_handlers to store your handlers like you described in C++ Documentation.

    while (true)
        {
            sem_wait(&object->fullSlot); /* Wait for available notification */
            pthread_mutex_lock(&object->mutex); /* Enter critical region */
    
            /* Notify the MbientLab library handler */
            auto iterator = object->notify_handlers.find(object->sharedMemory.caller);
            if (iterator != object->notify_handlers.end()) (*iterator).second(object->sharedMemory.caller, object->sharedMemory.data, object->sharedMemory.data_length);
            else std::cerr << "Could not find appropriate notification handler" << std::endl;
    
            pthread_mutex_unlock(&object->mutex); /* Leave critical region */
            sem_post(&object->emptySlot); /* Can process new notification */
        }
    
  • Code looks correct to me.

    Based on the notification behavior, it appears that both the normal and packed data signals are being enabled at some point in your code. When using packed data, only the 20 byte data packet should be arriving from the device.

  • Yes that's what I thought. For some reason only the 8byte packets arrive and I think that these are normal accelerometer data packets. When I enable high frequency streaming but use the standard acceleration data signal, I am able to connect 4 MetaWear boards to one Bluetooth adapter and stream data from all of them simultaneously. So perhaps this is the right way?

    One other issue that I have noticed is that although all 4 boards have the same streaming frequency I do not receive the same amount of data packets. For instance, I receive about 700 samples from sensor1, 1400 from sensor2, 2000, from sensor 3 and 700 from sensor4 . I suppose that this is not related to your library and it is more related to the Bluetooth adapter, the threads that I use, the scheduler, etc. Am I correct?

  • No, you should only be using the packed data signals for high frequency streaming and/or streaming from multiple devices. Somewhere or somehow, the boards are still streaming the normal data so you need check your code to ensure only packed signals are used and reset the boards to clear any previous changes.

    You can't stream that much data to 1 adapter. Either lower the frequency or split the devices across multiple dongles.

This discussion has been closed.