Using more than two sensors from sensor fusion (as streaming)

I have a quick question.
I downloaded a iOS MetaBase App.
I wanted to use both EULER ANGLES & LINEAR ACCELERATION (as streaming).
But, I got the below message.
"Error Total transmission frequency cannot exceed 100Hz over a BLE connection"

If the metabase application is not allowed to use these two sensors (as streaming),
are there any methods to use the two sensors with 100Hz (as streaming) using iOS metawear SDK?

Actually, with Android metawear SDK, I already implemented the android app to use EULER ANGLES & LINEAR ACCELERATION & CORRECTED GYRO (as streaming).

so, I hope that iOS metawear SDK also allows using sensor fusion sensors with 100Hz.

Comments

  • Yes it does though actual performance may vary depending on your iOS device when going over 100Hz.

  • I wonder whether iOS Metawear SDK could configure Sampling rate of Sensor Fusion Sensors?

    Using iOS Metawear SDK, I want to use more than two sensors from sensor fusion with a concrete sampling rate (e.g., 50Hz)

  • Hello Eric,

    I understand that under iOS, thanks to "dataprocessor" options that it is possible to reduce the sampling rate of BLE transmission but I do not understand where and when use the related code.
    I would appreciate some help or advice.

    Here is my code regarding mil_mw_processor_time_create to try to reduce sampling rate for sensor fusion to 50Hz.

    let quaternion = mbl_mw_sensor_fusion_get_data_signal(device_quat.board, MBL_MW_SENSOR_FUSION_DATA_QUATERNION);
    
    mbl_mw_dataprocessor_time_create(quaternion, MBL_MW_TIME_ABSOLUTE, 20, bridge(obj: self)) { (context, new_processor_created) in
         let _self : DeviceViewController = bridge(ptr: context!)
         //what to do here of new_processor_created here ???
         DispatchQueue.main.async {
              print("rate sensor")
              _self.printRate()
         }
    }
    

    I put this code between mbl_mw_sensor_fusion_get_data_signal and mbl_mw_datasignal_subscribe but without any effect on sampling rate ?

    Thanks in advance for your help.

  • Try with 15ms.

  • Thanks Eric,

    I tried with this value instead of 20 but It doesn't change anything...
    Then I guess that mbl_mw_dataprocessor_time_create is not called where it should...

    Clearly, a small iOS demo app (as before with old SDK) with best code practice would be appreciated to help us qualify our apps.

  • @patrice said:
    Thanks Eric,

    I tried with this value instead of 20 but It doesn't change anything...
    Then I guess that mbl_mw_dataprocessor_time_create is not called where it should...

    What does your call to mbl_mw_datasignal_subscribe look like?

  • here it is :

    mbl_mw_datasignal_subscribe(quaternion, bridge(obj: self)) { (context, dataPtr) in
        let _self: DeviceViewController = bridge(ptr: context!)
        let quat_rate = dataPtr!.pointee.valueAs() as MblMwQuaternion
        //print("(%f, %f, %f, %f)\n", quat_rate.w, quat_rate.x, quat_rate.y, quat_rate.z)
        DispatchQueue.main.async {
            _self.getQuaternion(obj_x: quat_rate.x, obj_y: quat_rate.y, obj_z: quat_rate.z, obj_w: quat_rate.w)
        }
    }
    mbl_mw_sensor_fusion_enable_data(device_quat.board, MBL_MW_SENSOR_FUSION_DATA_QUATERNION);
    mbl_mw_sensor_fusion_start(device_quat.board);
    
  • @patrice said:
    here it is :

    mbl_mw_datasignal_subscribe(quaternion, bridge(obj: self)) { (context, dataPtr) in
      let _self: DeviceViewController = bridge(ptr: context!)
      let quat_rate = dataPtr!.pointee.valueAs() as MblMwQuaternion
      //print("(%f, %f, %f, %f)\n", quat_rate.w, quat_rate.x, quat_rate.y, quat_rate.z)
      DispatchQueue.main.async {
          _self.getQuaternion(obj_x: quat_rate.x, obj_y: quat_rate.y, obj_z: quat_rate.z, obj_w: quat_rate.w)
      }
    }
    mbl_mw_sensor_fusion_enable_data(device_quat.board, MBL_MW_SENSOR_FUSION_DATA_QUATERNION);
    mbl_mw_sensor_fusion_start(device_quat.board);
    

    Subscribe to the data processor signal, not the original quarternion signal.

  • Hello Eric,

    I tried different ways but it keeps impossible for me to subscribe to my "new_processor_created" which is of type MblMwFnDataProcessor, and as mbl_mw_datasignal_subscribe is expected an OpaquePointer.

    Sincerely, some small examples would be great as using these Unsafe and Opaque pointers is really not very easy...
    It would be also the best way to be sure to use the best practice and then be able to optimize the usage of metawear sensors...

    Happy Christmas !

  • edited December 2018
        let quaternion = mbl_mw_sensor_fusion_get_data_signal(device_quat.board, MBL_MW_SENSOR_FUSION_DATA_QUATERNION);
    
        mbl_mw_dataprocessor_time_create(quaternion, MBL_MW_TIME_ABSOLUTE, 20, bridge(obj: self)) { (context, dataPtr) in
                let _self : DeviceViewController = bridge(ptr: context!)
                mbl_mw_datasignal_subscribe(dataPtr, bridge(obj: _self)) { (context, dataPtr) in
    
                }
        }
    

    better to use the Bolts Tasks for each part

  • Many thanks fryjs for your help ; i really do appreciate but calling mbl_mw_datasignal_subscribe inside mbl_mw_dataprocessor_time_create do not start for me. Regarding my code bellow, DEBUG_1 message is working well, but impossible to print the "DEBUG_2" message in the console... I must still be missing something...

        mbl_mw_dataprocessor_time_create(quaternion_stream, MBL_MW_TIME_ABSOLUTE, 20, bridge(obj: self)) { (context, dataPtr) in
            let _self : DeviceViewController = bridge(ptr: context!)
            print("### DEBUG_1")
    
            mbl_mw_datasignal_subscribe(dataPtr, bridge(obj: _self)) { (context, dataPtr) in
                print("### DEBUG_2")
                let _self : DeviceViewController = bridge(ptr: context!)
                let quat_rate = dataPtr!.pointee.valueAs() as MblMwQuaternion
                DispatchQueue.main.async {
                    _self.getQuaternion(obj_x: quat_rate.x, obj_y: quat_rate.y, obj_z: quat_rate.z, obj_w: quat_rate.w)
                }
           }
    
       }
    
  • edited January 2019

    hmm, are you still calling:

    mbl_mw_sensor_fusion_enable_data(device_quat.board, MBL_MW_SENSOR_FUSION_DATA_QUATERNION);
    mbl_mw_sensor_fusion_start(device_quat.board);

    after mbl_mw_datasignal_subscribe ?

        mbl_mw_dataprocessor_time_create(quaternion_stream, MBL_MW_TIME_ABSOLUTE, 20, bridge(obj: self)) { (context, dataPtr) in
            let _self : DeviceViewController = bridge(ptr: context!)
            print("### DEBUG_1")
    
            mbl_mw_datasignal_subscribe(dataPtr, bridge(obj: _self)) { (context, dataPtr) in
                print("### DEBUG_2")
                let _self : DeviceViewController = bridge(ptr: context!)
                let quat_rate = dataPtr!.pointee.valueAs() as MblMwQuaternion
                DispatchQueue.main.async {
                    _self.getQuaternion(obj_x: quat_rate.x, obj_y: quat_rate.y, obj_z: quat_rate.z, obj_w: quat_rate.w)
                }
           }
    
      mbl_mw_sensor_fusion_enable_data(device_quat.board, MBL_MW_SENSOR_FUSION_DATA_QUATERNION);
      mbl_mw_sensor_fusion_start(device_quat.board);
    
       }
    
  • also I think you should be using bridgeRetained & bridgeTransfer for the timer create bridge (not for the subscribe, as it needs to persist, I think...)

  • Thanks fryjs for your help.
    I tried with bridgeRetained & bridgeTransfer for the timer but nothing new.

    Otherwise, after mbl_mw_datasignal_subscribe, I always have my two lines "enable" and "start" but they are outside the mbl_mw_dataprocessor_time_create function. Should they be inside ? I tried but it does not work...
    And in this case how would you declare pointers to avoid the error "A C function pointer cannot be formed from a closure that captures context".

    Concretely I just try to reduce the frequency of sensorfusion to get a better stability with my three metamotion-R streaming together. And as BLE 5 expected improvements are not yet available, I would like to try to optimize throughput limitations with BLE 4...

  • you have to have an object that can be bridged that has a pointer to a handler. Also, you do have to call mbl_mw_sensor_fusion_set_mode and mbl_mw_sensor_fusion_write_config before it will start streaming also. Much better to separate them into tastks

    Here's what I use:
    https://gist.github.com/simplecohesion/6b36be51687334ba7e45d40ac3077759

    Then you use it by
    var metaWear: MetaWear
    var sensorDataBridge: SensorDataBridge

    metaWear.configureSensorFusion().continueOnSuccessWithTask {
            return metaWear.createQuaternionTimerSignal(samplePeriod: UInt32(100))
    }.continueOnSuccessWithTask { timerPointer in
            return metaWear.startStreamingQuaternion(timerSignal: timerPointer, sensorDataBridge: sensorDataBridge)
    }.continueOnError{ error in
            //handle error
    }
    
Sign In or Register to comment.