Fuser Dataprocessor - Crash on subscribe

Hi there,

I'm able to read gyro and accelerometer data from the board with seperate callback functions (I subscribed seperatly to the acc_signal and the gyro_signal).
For the sake of efficiency I want to use the Fuser Dataprocessor and cut the number of BLE messages in half. Seems easy, but I hit a snag, the program crashes without an obvious error code.

The code I'm using is the one I found in the tutorials:

#include "metawear/processor/fuser.h"
#include "metawear/sensor/accelerometer.h"
#include "metawear/sensor/gyro_bmi160.h"

void setup_adc_delta(MblMwMetaWearBoard* board) {
    static auto proc_created = [](void* context, MblMwDataProcessor* fuser) {
        mbl_mw_datasignal_subscribe((MblMwDataSignal*)fuser, context, [](void* context, const MblMwData* data) {
            auto fused = (MblMwData**)data->value;

            // 0 - acc data
            // 1 - gyro data
            auto acc = (MblMwCartesianFloat*) fused[0]->value;
            auto gyro = (MblMwCartesianFloat*) fused[1]->value;
            printf("acc = (%.3f, %.3f, %.3f), gyro = (%.3f, %.3f, %.3f)\n",
                    acc->x, acc->y, acc->z,gyro->x, gyro->y, gyro->z);
        });
    };

    auto acc_signal = mbl_mw_acc_get_acceleration_data_signal(board);
    auto gyro_signal = mbl_mw_gyro_bmi160_get_rotation_data_signal(board);

    mbl_mw_dataprocessor_fuser_create(acc_signal, &gyro_signal, 1, nullptr, proc_created);
}

The processor gets created, but the program then crashes when calling the mbl_mw_datasignal_subscribe function, spitting out a register dump which points to mbl_mw_datasignal_subscribe in datasignal.cpp:

Guru Meditation Error: Core  0 panic'ed (LoadProhibited). Exception was unhandled.
Core 0 register dump:
PC      : 0x401b609b  PS      : 0x00060730  A0      : 0x800d2256  A1      : 0x3ffe6a40
A2      : 0x00000000  A3      : 0x00000000  A4      : 0x400d2258  A5      : 0x00000000
A6      : 0x80000020  A7      : 0x3ffc49a4  A8      : 0x800fb934  A9      : 0x3ffe6a20
A10     : 0x00000002  A11     : 0x3f400152  A12     : 0x00060120  A13     : 0x000000fe
A14     : 0x00000001  A15     : 0x00000000  SAR     : 0x00000016  EXCCAUSE: 0x0000001c
EXCVADDR: 0x00000000  LBEG    : 0x400919b5  LEND    : 0x400919c5  LCOUNT  : 0xffffffff

Any ideas? :)

Comments

  • @Laura Thanks for the response.

    The javascript version looks identical with the difference that the mbl_mw_datasignal_subscribe takes a MblMwDataProcessor* as argument (similar to the Python API, which I've successfully tested).

    In the cpp version this has to be a MblMwDataSignal*, so a cast is needed. (Which is also mentioned in the cpp tutorial).

    The same crash happens when I try to use another dataprocessor.
    Sample frequencies are the same for the gyroscope and accelerometer.

    Allas no solution so far, any more ideas? :#

  • edited June 2021

    Can you update to use the latest SDK. The stuff you are using is the old CPP sdk.

    For one,

    #include "metawear/sensor/gyro_bmi160.h" 
    

    is now

    #include "metawear/sensor/gyro_bosch.h"
    

    Also as such, you need to make sure you are using the right calls depending on which sensors you are using (mms = bmi270, mmrl = bmi160 for example). This wouldn't work for the MMS but you aren't tell me so I don't really know what sensors you even have:

    auto gyro_signal = mbl_mw_gyro_bmi160_get_rotation_data_signal(board);
    
  • @Laura The code snippet came from the cpp-tutorial

    I've already adjusted it to the new SDK and confirmed that I can read out the accelerometer and gyroscope seperatly, just when I'm trying to use any dataprocessor the program crashes on calling mbl_mw_datasignal_subscribe. The register dump doesn't give much info even with debug on, just that it crashes the moment it calls it.

    I'm using the MMRL+ sensors, so a BMI160 is used. (which the board also confirmes).

    Is there an updated tutorial for the new SDK?
    Something I can test to narrow it down?

    Thank you for your input!

  • Be careful, the tutorials are just code snippets and copy pasting them is usually not enough.
    As I mentioned in my previous post, did you update the SDK yet? It's at 20.1 currently. I already mentioned the #include as the biggest differentiator.

  • @Laura The SDK version I'm using is the latest version 20.1.
    I've always used this version of the SDK, the #include was an error while making this thread, in the code I've always used the correct #include.

    I'm following the correct setup procedure for the board, I know this because I can subscribe to any other MblMwDataSignal* without problems.

    So I'm following exactly the same setup procedure as with subscribing to the accelerometer and the gyroscope, with the difference that I don't subscribe to the accelerometer and gyropscope but instead:
    1. Create the dataprocessor with the acc_signal and gyro_signal
    2. Wait for the callback
    3. Check if the dataprocessor object is valid
    4. Cast the dataprocessor to a MblMwDataSignal*
    5. Subscribe
    ==> Programs crashes when entering the subscribe function

  • @Laura Any ideas left? :)
    You don't have a minimal code sample with the latest sdk for the fuser dataprocessor?

  • edited June 2021

    I just updated the Java and python examples with the latest SDK. Check those out.

    I won't get around to update the CPP docs until later in July since I am working through Android and USB code right now.

  • Hi @Laura , I've been busy with another project since June but I'm picking this back up now.

    I still haven't resolved this issue, but I got another clue; the reason the program crashes is because the returned MblMwDataProcessor* is always a null pointer, although the return code of mbl_mw_dataprocessor_fuser_create is 0.

    Any idea why this could be?

    I was looking in the code where the callback is called and I could only find this in dataprocessor.cpp:

    void create_processor(MblMwDataSignal* source, MblMwDataProcessor* processor, void *context, MblMwFnDataProcessor processor_created) {
        auto state = GET_DATAPROCESSOR_STATE(processor->owner);
        state->pending_fns.push([state, processor, context, processor_created, source](void) -> void {
            state->next_processor= processor;
            state->processor_context= context;
            state->processor_callback= processor_created;
    
            vector<uint8_t> command = { MBL_MW_MODULE_DATA_PROCESSOR, ORDINAL(DataProcessorRegister::ADD), source->header.module_id, 
                    source->header.register_id, source->header.data_id, source->get_data_ubyte(), type_to_id.at(processor->type) };
            command.insert(command.end(), (uint8_t*) processor->config, ((uint8_t*) processor->config) + processor->config_size);
    
            state->timeout= ThreadPool::schedule([state](void) -> void {
                if (state->next_processor->state != nullptr) {
                    delete state->next_processor->state;
                }
                state->next_processor->remove = false;
                delete state->next_processor;
                state->processor_callback(state->processor_context, nullptr); // ALWAYS NULLPTR?
    
                state->create_next(true);
            }, source->owner->time_per_response);
            send_command(source->owner, command.data(), (uint8_t) command.size());
        });
        state->create_next(false);
    }
    

    Here the callback function is called but always with a nullptr value - but this is in state->timeout, which doesn't look like the place where the callback function is called when the dataprocessor is created.

    Any tips would be very welcome.

  • I took a closer look at the code and found when and how the callback function is called from dataprocessor.cpp. While doing this I've noticed something is wrong with my BLE library, in particular when writing with a response required, I suspect that's the issue !

    So no action required from you ;)

  • Hi @Laura ,
    Sad story, it wasn't the BLE library, it's working fine.

    Recap: Issue is that the returned dataprocessor is always a nullpointer, which is comming from the state->timeout-Thread. I see that after create_processor a BLE message - without response required- is send to the sensor, but no callback is made afterwards to the dataprocessor-callback function...

    Ideas?
    Are there specific cpp versions I should work with?

  • Hi @Laura , did you have time to look at my question above?

  • Full reset of the board and extra delay in the code did the trick

  • @benodisee,
    Sorry I was OOO, thank you for the fix and update!

Sign In or Register to comment.