MbientLab MetaWear (MetaMotionR)

From phyphox
Jump to: navigation, search

So far, we only had an MbientLab MetaMotionR in our hands for a short time, but we were able to make it work with phyphox. The MbientLab provides a range of well-documented SDKs to allow using their devices in your own code, but unfortunately there is no documentation of the actual Bluetooth communication. So, since we do not plan on including specific SDKs for each supported device, this gives us some trouble, because the MetaWear devices seem to implement a serial communication over two characteristics. You can set up rather complex measurement, logging and analysis scenarios right on the device and therefore a configuration has to be written before being able to receive anything.

Therefore, at the moment, you can use our examples below, but if you want to create your only configurations to read any other sensor on a MetaWear device, you need to dive into the communications.

Accelerometer

To read the accelerometer, you can use this configuration in phyphox:

MetaWear Accelerometer

Orientation

To read fused orientation data (Euler angles), you can use this configuration in phyphox:

MetaWear Orientation

Advanced version based on Quaternions to measure rotations with settable zero:

MetaWear Rotation

Creating phyphox configurations for MetaWear

As outlined above, you need to write a suitable configuration to the MetaWear device first and then interpret the received packages. The approach we used to get the configuration packages, was to create a setup using MbientLab's Python SDK (for its convenience), actually connect to a MetaMotionR and log the setup sequence with WireShark. Alternatively, you might be able to simply get the byte sequence from the SDK, as especially die C++ SDK requires you to provide function to handle the data, so if you prefer the C++ version, it might be easier to just write a function that outputs anything sent to the MetaMotionR.

The setup sequence can be rather long and we found that you also should prepend it with a reset sequence (remove all macros with the SDK) or you get weird results when subsequently connecting to your MetaWear device with different setups. We simply put anything sent by the SDK into a long sequence of config blocks for phyphox as shown in the following two examples.

Setup sequence to read the accelerometer. The reset sequence stems from removing all macros and the setup sequence is the result of setting an output rate of 100 Hz and an accelerometer range of 16g.

        <bluetooth name="MetaWear" mode="notification">
            <!--Reset-->
            <config char="326a9001-85cb-9195-d9dd-464cfbbae75a" conversion="hexadecimal">0b84</config>
            <config char="326a9001-85cb-9195-d9dd-464cfbbae75a" conversion="hexadecimal">0f08</config>
            <config char="326a9001-85cb-9195-d9dd-464cfbbae75a" conversion="hexadecimal">fe05</config>
            <!--Setup accelerometer-->
            <config char="326a9001-85cb-9195-d9dd-464cfbbae75a" conversion="hexadecimal">0b84</config>
            <config char="326a9001-85cb-9195-d9dd-464cfbbae75a" conversion="hexadecimal">11090600060000005802</config>
            <config char="326a9001-85cb-9195-d9dd-464cfbbae75a" conversion="hexadecimal">0303280c</config>
            <config char="326a9001-85cb-9195-d9dd-464cfbbae75a" conversion="hexadecimal">030401</config>
            <config char="326a9001-85cb-9195-d9dd-464cfbbae75a" conversion="hexadecimal">03020100</config>
            <config char="326a9001-85cb-9195-d9dd-464cfbbae75a" conversion="hexadecimal">030101</config>
            <!-- -->

...
        </bluetooth>

Setup sequence to read the fused orientation data. The reset sequence again stems from removing all macros and the setup sequence is the result of setting the fusion mode NDOF, requesting Euler angles and subscribing to the fusion data.

        <bluetooth name="MetaWear" mode="notification">
            <!--Reset-->
            <config char="326a9001-85cb-9195-d9dd-464cfbbae75a" conversion="hexadecimal">0b84</config>
            <config char="326a9001-85cb-9195-d9dd-464cfbbae75a" conversion="hexadecimal">0f08</config>
            <config char="326a9001-85cb-9195-d9dd-464cfbbae75a" conversion="hexadecimal">fe05</config>
            <!--Setup accelerometer-->
            <config char="326a9001-85cb-9195-d9dd-464cfbbae75a" conversion="hexadecimal">11090600060000005802</config>
            <config char="326a9001-85cb-9195-d9dd-464cfbbae75a" conversion="hexadecimal">19020113</config>
            <config char="326a9001-85cb-9195-d9dd-464cfbbae75a" conversion="hexadecimal">0303280c</config>
            <config char="326a9001-85cb-9195-d9dd-464cfbbae75a" conversion="hexadecimal">13032800</config>
            <config char="326a9001-85cb-9195-d9dd-464cfbbae75a" conversion="hexadecimal">150100</config>
            <config char="326a9001-85cb-9195-d9dd-464cfbbae75a" conversion="hexadecimal">1504040e</config>
            <config char="326a9001-85cb-9195-d9dd-464cfbbae75a" conversion="hexadecimal">150306</config>
            <config char="326a9001-85cb-9195-d9dd-464cfbbae75a" conversion="hexadecimal">190801</config>
            <config char="326a9001-85cb-9195-d9dd-464cfbbae75a" conversion="hexadecimal">03020100</config>
            <config char="326a9001-85cb-9195-d9dd-464cfbbae75a" conversion="hexadecimal">13020100</config>
            <config char="326a9001-85cb-9195-d9dd-464cfbbae75a" conversion="hexadecimal">15020100</config>
            <config char="326a9001-85cb-9195-d9dd-464cfbbae75a" conversion="hexadecimal">030101</config>
            <config char="326a9001-85cb-9195-d9dd-464cfbbae75a" conversion="hexadecimal">130101</config>
            <config char="326a9001-85cb-9195-d9dd-464cfbbae75a" conversion="hexadecimal">150101</config>
            <config char="326a9001-85cb-9195-d9dd-464cfbbae75a" conversion="hexadecimal">19031000</config>
            <config char="326a9001-85cb-9195-d9dd-464cfbbae75a" conversion="hexadecimal">190101</config>
            <!-- -->
...
        </bluetooth>


Then, to read the sensor data, we need to subscribe to characteristic 326a9006-85cb-9195-d9dd-464cfbbae75a. We could not find a documentation on the resulting format, but for the two examples, it is rather obvious. The first two bytes do not seem to belong to the data (probably a prefix to denote that it is a data packet), but the remaining ones are more interesting.

For the accelerometer, we get three signed 16 bit integers (little endian), which can simply be scaled to the range we set up to get our setup sequence. So the +/-2^15 range of the signed 16bit integer corresponds to the +/-16g, resulting in a factor 1/2048. To get the acceleration in m/s², we apply a factor of 9.81/2048. So, the corresponding bluetooth part reads

        <bluetooth name="MetaWear" mode="notification">
...
            <output char="326a9006-85cb-9195-d9dd-464cfbbae75a" conversion="int16LittleEndian" offset="2" length="2">accXRaw</output>
            <output char="326a9006-85cb-9195-d9dd-464cfbbae75a" conversion="int16LittleEndian" offset="4" length="2">accYRaw</output>
            <output char="326a9006-85cb-9195-d9dd-464cfbbae75a" conversion="int16LittleEndian" offset="6" length="2">accZRaw</output>
        </bluetooth>

with matching analysis for calibration:

        <multiply>
            <input clear="false">accZRaw</input>
            <input type="value">0.004790039</input>
            <output clear="true">accZCal</output>
        </multiply>

Interestingly, the orientation data is even more straight forward. We get four angles (heading, pitch, roll and yaw) as single precision floats (32bit little endian). So, we just need to take them in our bluetooth block:

        <bluetooth name="MetaWear" mode="notification">
...
            <output char="326a9006-85cb-9195-d9dd-464cfbbae75a" conversion="float32LittleEndian" offset="2" length="4">heading</output>
            <output char="326a9006-85cb-9195-d9dd-464cfbbae75a" conversion="float32LittleEndian" offset="6" length="4">pitch</output>
            <output char="326a9006-85cb-9195-d9dd-464cfbbae75a" conversion="float32LittleEndian" offset="10" length="4">roll</output>
            <output char="326a9006-85cb-9195-d9dd-464cfbbae75a" conversion="float32LittleEndian" offset="14" length="4">yaw</output>
        </bluetooth>

This is only an outline on how to implement MetaWear devices in a phyphox configuration. We unfortunately had not much time to play with this device and to really dive into the documentation. If you can provide more insights into the communication or more configurations for other users, you are more than welcome to share it here or on our forum.