Shapes


Integrating MbientLab MetaMotionR sensors with Python

Overview

MbientLab is a manufacture of different wearable devices, an example of these are the Meta sensors family, which is formed by different wearable devices like MetaTracker, MetaMotionC and MetaMotionR. The Meta family devices are formed by different sensors, like Accelerometers, Gyroscopes, Barometes, etc… In this case, we are going to see how to use a Python library for the MetaMotionR, which enable the user to read the sensors of this device. The measures that can be read with the Library are the acceleration, motion, tap, step counter by an Accelerometer and the rotation by a Gyroscope.

Ingredients

In order to follow the next recipe you will need the this ingredients:

In order to install al the dependencies you must execute the next commands

console
sudo apt install bluez build-essential libboost-all-dev libbluetooth-dev
pip3 install metawear --upgrade
pip3 install bleak
sudo apt install metamotion

In the following sections, we are going to explain the main funcionalities of the library, read a value from a sensor, attach a handler to a value produced by the sensor and create logs of data that will be downloaded lately. Almost every measure of the sensor can be readed, but not all the measures support the use of a handler.

Connecting and Reading data from the device

In this section, we are going to explain how you can read the battery from a MetaMotionR board. The first step is import the metamotion library in the following way.

snippet.py
#!/usr/bin/python3

from metamotion import MetaMotion

Once you import the library you must instantiate your chip. In order to do that you must call the constructor MetaMotion with the MAC address of the chip, which can be observer in the label of the device. Once the sensor is instantiated, call the connect() method in order to establish the Bluetooth connection

snippet.py
sensor = MetaMotion("E9:75:41:AF:11:AE")
sensor.connect()

Finally you can read any value of the chip, in this case we are going to read the remanent percentage battery invoking the method read_battery of the class. This method returns a struct that is formed by two fields, voltage, which represents the voltage that receives the chip, and battery which is the percentage of battery that the device has.

snippet.py
measure = sensor.read_battery()
print(measure.battery)

Before the end of the program is important to invoke the disconnect method, in order to close the communication.

snippet.py
sensor.disconnect()

The full code is listed here below

snippet.py
#!/usr/bin/python3

from metamotion import MetaMotion

sensor = MetaMotion("E9:75:41:AF:11:AE")
sensor.connect()

measure = sensor.read_battery()
print(measure.battery)

sensor.disconnect()

Read a measure from a sensor

Like it was said before, the MetaMotionR device is formed by several sensors. The most important sensors, and those to which the library gives access to, are the Acceleromter and the Gyro sensor. In order to access to the measures of this sensors, a MetaMotion instance has two attributes representing it, accelerometer and gyroscope. Following, we are going to see an example in which we are going to read the acceleration.

In order to read the acceleration, the first step is to active and initialize the accelerometer. For this purpose you must invoke the method setup_accelerometer with the aim of active and initialize the accelerometer sensor. If you don’t do this, and you try to access the accelerometer sensor, an exception will be raised.

snippet.py
sensor.setup_accelerometer()

Once initialized the sensor, you can read the acceleration invoking the method form the accelerometer read_acceleration, which returns the acceleration calculated by the sensor in G units.

snippet.py
sensor.accelerometer.read_acceleration()

The full code is listed below

snippet.py
#!/usr/bin/python3

from metamotion import MetaMotion

sensor = MetaMotion("E9:75:41:AF:11:AE")
sensor.connect()
sensor.setup_accelerometer()

measure = sensor.accelerometer.read_acceleration()
print(measure)

sensor.disconnect()

Add a handler to a measure

With the MetaMotion library you can read any values produced by the sensor, but this library also provides the funcionality to subscribe to a measure and attach a handler. In this way, if the sensor which we are subscribed send a value, the handler will be executed and will process the data with the user function.

In this section we are going to see an example where we add a handler to an accelertion sample.

The first step is to declare the handler that will process the data, in this case the handler is going to print the data.

snippet.py
def handler(data):
    print(f"The acceleration is: {data.x} {data.y} {data.z}")

Once the handler is defined, you must attach it to the acceleration produced by the sensor, so that when an acceleration measure is received, the user function will be executed. The acceleration is produced by an accelerometer in the MetaMotionR device, for this reason, to add the handler you must call the on_acceleration method of the accelerometer attribute in your instance of the MetaMotion class. To avoid the end of the program, the method wait_until_break must be called. The full program can be seen below.

snippet.py
#!/usr/bin/python3

from metamotion import MetaMotion

def handler(data):
    print(f"The acceleration is: {data.x} {data.y} {data.z}")

sensor = MetaMotion("E9:75:41:AF:11:AE")
sensor.connect()

measure = sensor.accelerometer.on_acceleration(handler)
sensor.wait_until_break()

sensor.disconnect()

Using a logger

An interesting funcionality of the MetaMotionR devices is the posibility to create loggers. A logges make the users ables to register a set of data from a sensor in the device, and lately download all this data, avoiding maintaining a continuous streaming. This is very useful if you don’t want to communicate with the sensor in each measure. In the following example, we are going to create a logger for a rotation measure

As in all previous examples, the first step is to made the connection with the sensor. Once the connection is made, and beacuse we are going to log a measure from the Gyro, we must invoke the method setup_gyroscope and setup_logger from the gyroscope attribute to initialize the sensor and the logger. After that, invoke the method start_logging in order to start to save the data. Following, you can disconnect from the sensor until you want to download the data.

snippet.py
sensor.gyroscope.setup_gyroscope()
sensor.gyroscope.setup_logger()
sensor.start_logging()
sensor.disconnect()

Once you want to download data, connect to the sensor again and invoke the methods stop_logging in order to stop registering data.

snippet.py
sensor.stop_logging()

At this point, there is a problem, our instance doesn’t know which is the status of the sensor, which loggers were created, and which signal were registering. To solve this problem, can be used the method sync_host_with_device, that synchronize our instance with the actual status of our MetamotionR device. Now our instance knows which logger exists, but doesn’t knows which signals were subscribed, for this reason, and to download all data, you must invoke the method subscribe_anonymous_datasignals. Once our instance is prepared, download the data is as simple as call the method download_logs to get all the data from the device, and wait_until_download_completed, to avoid the finish of the program until all the data is downloaded. Finally, the downloaded data is in a list, in this case in the attribute rotation_log from the gyroscope.

snippet.py
sensor.stop_logging()
sensor.gyroscope.subscribe_logged_data()
sensor.download_logs()

sensor.gyroscope.wait_until_download_completed()
print("The rotation is ", sensor.gyrocope.rotation_log)

Finally, is needed to clean the logger created in the device before disconnection.

snippet.py
sensor.clean()
sensor.disconnect()

The full code is listed bellow

snippet.py
#!/usr/bin/python3

import sys
import time
from metamotion import MetaMotion

sensor = MetaMotion("E9:75:41:AF:11:AE")
sensor.connect()

sensor.gyroscope.setup_gyroscope()
sensor.gyroscope.setup_logger()
sensor.start_logging()
sensor.disconnect()

time.sleep(4) #Wait 4 seconds to let the sensor log data

sensor = MetaMotion("E9:75:41:AF:11:AE")
sensor.connect()

sensor.stop_logging()
sensor.sync_host_with_device()
sensor.subscribe_anonymous_datasignals()

sensor.download_logs()
sensor.wait_until_download_complete()
print("The rotation is ", sensor.gyroscope.rotation_log)

sensor.clean()
sensor.disconnect()

You can use as many logs as you want, but you must follow the next workflow:

  1. Connect the sensor
  2. Setup the necessary logger in their respective sensor from the chip
  3. Start the logging
  4. Wait a desired amount of time
  5. Connect with the sensor again
  6. Stop the logging
  7. Sync the client with the device status
  8. Subscribe to anonymous datasignals
  9. Download the logs
  10. Wait for each sensor to download its log data
  11. Clean and disconnect from the sensor

MetaMotion API

For more information you can see the API reference where you can find how to read all the measures available and the different methods to attach handlers: