While the MbientLab MetaWear has a number of sensors built into the board, it also has the ability to interface with a host of analog sensors. With many wearable devices focusing on fitness, you might find yourself needing to integrate a heart rate sensor into your board.
Getting Started
To get started you will need to have a heart rate sensor in addition to a MetaWear board. This post on the MbientLab projects page will give you information on where to find and how to wire up the sensor to your board. Once you are done with this you will need to set up your project to include the MetaWear API, app permissions etc.. Our post on logging thermistor data here goes over the steps to set up your project and connect to the board.
Reading The Data
Now that you are able to connect to the board you will need to read analog data from a GPIO pin. To do that we first need to get the GPIO module.
try {
gpio = metaWearBoard.getModule(Gpio.class);
} catch (UnsupportedModuleException e) {
Log.e("HeartRateSensorFragment", e.toString());
return false;
}
For this application we are going to stream the data the GPIO pin to a stream that we will call HEART_RATE and pass in CompletionHandler called gpioHandler that will set up the rest of the chain once the route has been configured.
private final byte GPIO_PIN = 0;
private final String HEART_RATE = "heart_rate";
gpio.routeData().fromAnalogIn(GPIO_PIN, Gpio.AnalogReadMode.ADC).stream(HEART_RATE)
.commit().onComplete(gpioHandler);
Our CompletionHandler is going to do a couple of things in a over-ridden success method. First it is gonig to subscribe to our stream with a data handler that will process reads from the pin (more on that handler later in this post).
result.subscribe(HEART_RATE, dataHandler);
Then it needs to set up a timer to periodically get a reading from the pin.
private final int SCAN_INTERVAL = 50;
try {
AsyncOperation taskResult = metaWearBoard.getModule(Timer.class).scheduleTask(
new Timer.Task() {
@Override
public void commands() {
gpio.readAnalogIn(GPIO_PIN, Gpio.AnalogReadMode.ADC);
}
}, SCAN_INTERVAL, false);
taskResult.onComplete(
new AsyncOperation.CompletionHandler() {
@Override
public void success(Timer.Controller result) {
result.start();
}
}
);
} catch (UnsupportedModuleException e) {
Log.e("HeartRateSensorFragment", e.toString());
}
The entire handler ends up looking like this.
private final AsyncOperation.CompletionHandler gpioHandler = new AsyncOperation.CompletionHandler() {
@Override
public void success(RouteManager result) {
result.subscribe(HEART_RATE, dataHandler);
try {
AsyncOperation taskResult = metaWearBoard.getModule(Timer.class).scheduleTask(
new Timer.Task() {
@Override
public void commands() {
gpio.readAnalogIn(GPIO_PIN, Gpio.AnalogReadMode.ADC);
}
}, SCAN_INTERVAL, false);
taskResult.onComplete(
new AsyncOperation.CompletionHandler() {
@Override
public void success(Timer.Controller result) {
result.start();
}
}
);
} catch (UnsupportedModuleException e) {
Log.e("HeartRateSensorFragment", e.toString());
}
}
};
Then our MessageHandler (what we refer to as our dataHandler) will look like this.
private final RouteManager.MessageHandler dataHandler = new RouteManager.MessageHandler() {
@Override
public void process(Message message) {
short rawValue = message.getData(Short.class);
Log.i("HeartRateSensorFragment", String.valueOf(rawValue));
.
.
. heart rate calculations
.
.
getActivity().runOnUiThread(
new Runnable() {
@Override
public void run() {
bpmView.setText(String.valueOf(bpm));
}
}
);
Log.i("HRSFragment BPM", String.valueOf(bpm));
}
};
You can find the code here . Feel free to fork it and make it your own. The application can also be found on the play store here.