Heart Rate Monitor example for the BLE API using ST BlueNRG native drivers

Dependencies:   BLE_API X_NUCLEO_IDB0XA1 mbed

Getting started with X-NUCLEO-IDB05A1

This example demonstrates how to use the X-NUCLEO-IDB05A1 component with one of the STM32 Nucleo platforms tested with the to obtain heart rate information:

First, attach the X-NUCLEO-IDB05A1 to the STM32 Nucleo platform as shown here: /media/uploads/apalmieri/nucleoble.jpg

Next, connect the STM32 Nucleo platform to your PC with a USB-mini USB cable.

Now return to the BLE_HeartRate_IDB0XA1 project homepage and import the project into your mbed compiler:

/media/uploads/apalmieri/homepage.jpg

Click “Import” button on the pop up window shown below

/media/uploads/apalmieri/import.jpg

Compile and load the image onto the STM32 Nucleo platform

Upon a successful compilation, a binary image will be created and a dialog box will ask you where to save it.

/media/uploads/apalmieri/xsaveimage.jpg

Now you can load the compiled code onto your Nucleo platform by saving the newly created binary file to your STM32 Nucleo drive.

Open a terminal window to display the status of your Bluetooth stack. For this example, set the terminal BAUD rate to 9600

Note

Included within the USB interface of the STM32 Nucleo platform is a Virtual COM port that can be used to send back messages to your PC within your embedded code.
You need a terminal emulator installed on your PC to perform serial communications with your STM32 Nucleo platform. If you do not have a terminal emulation program on your PC we recommend you download and install one of the following terminal emulation programs:

Upon a successful serial connection, you should now see the various Bluetooth stack status displayed on your console output.

/media/uploads/apalmieri/xteraterm.png

Test your application with an Android or iOS device

/media/uploads/apalmieri/1.splashscreen_800x1280.png

  • On the STM32 BLE Profiles app select HeartRateSensor

/media/uploads/apalmieri/2.scanningdevice_800x1280.png

  • Select Heart Rate

/media/uploads/apalmieri/3.profileselection_800x1280.png /media/uploads/apalmieri/7.heartrate_800x1280.png

Committer:
apalmieri
Date:
Tue Sep 29 15:06:46 2015 +0000
Revision:
3:a51ca6313ad2
Parent:
2:bc0c0d442a24
Child:
13:227a0149b677
Remove 'IDB0XA1_D13_PATCH' from main

Who changed what in which revision?

UserRevisionLine numberNew contents of line
screamer 0:eb7f02ad28a7 1 /* mbed Microcontroller Library
screamer 0:eb7f02ad28a7 2 * Copyright (c) 2006-2015 ARM Limited
screamer 0:eb7f02ad28a7 3 *
screamer 0:eb7f02ad28a7 4 * Licensed under the Apache License, Version 2.0 (the "License");
screamer 0:eb7f02ad28a7 5 * you may not use this file except in compliance with the License.
screamer 0:eb7f02ad28a7 6 * You may obtain a copy of the License at
screamer 0:eb7f02ad28a7 7 *
screamer 0:eb7f02ad28a7 8 * http://www.apache.org/licenses/LICENSE-2.0
screamer 0:eb7f02ad28a7 9 *
screamer 0:eb7f02ad28a7 10 * Unless required by applicable law or agreed to in writing, software
screamer 0:eb7f02ad28a7 11 * distributed under the License is distributed on an "AS IS" BASIS,
screamer 0:eb7f02ad28a7 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
screamer 0:eb7f02ad28a7 13 * See the License for the specific language governing permissions and
screamer 0:eb7f02ad28a7 14 * limitations under the License.
screamer 0:eb7f02ad28a7 15 */
screamer 0:eb7f02ad28a7 16
screamer 0:eb7f02ad28a7 17 #include "mbed.h"
screamer 0:eb7f02ad28a7 18 #include "ble/BLE.h"
screamer 0:eb7f02ad28a7 19 #include "ble/services/HeartRateService.h"
screamer 0:eb7f02ad28a7 20 #include "ble/services/BatteryService.h"
screamer 0:eb7f02ad28a7 21 #include "ble/services/DeviceInformationService.h"
screamer 0:eb7f02ad28a7 22
screamer 0:eb7f02ad28a7 23 BLE ble;
screamer 0:eb7f02ad28a7 24 DigitalOut led1(LED1);
screamer 0:eb7f02ad28a7 25
screamer 0:eb7f02ad28a7 26 const static char DEVICE_NAME[] = "HRM1";
screamer 0:eb7f02ad28a7 27 static const uint16_t uuid16_list[] = {GattService::UUID_HEART_RATE_SERVICE,
screamer 0:eb7f02ad28a7 28 GattService::UUID_DEVICE_INFORMATION_SERVICE};
screamer 0:eb7f02ad28a7 29 static volatile bool triggerSensorPolling = false;
screamer 0:eb7f02ad28a7 30
apalmieri 2:bc0c0d442a24 31 void disconnectionCallback(const Gap::DisconnectionCallbackParams_t *params)
screamer 0:eb7f02ad28a7 32 {
screamer 0:eb7f02ad28a7 33 ble.gap().startAdvertising(); // restart advertising
screamer 0:eb7f02ad28a7 34 }
screamer 0:eb7f02ad28a7 35
screamer 0:eb7f02ad28a7 36 void periodicCallback(void)
screamer 0:eb7f02ad28a7 37 {
screamer 0:eb7f02ad28a7 38 led1 = !led1; /* Do blinky on LED1 while we're waiting for BLE events */
screamer 0:eb7f02ad28a7 39 /* Note that the periodicCallback() executes in interrupt context, so it is safer to do
screamer 0:eb7f02ad28a7 40 * heavy-weight sensor polling from the main thread. */
screamer 0:eb7f02ad28a7 41 triggerSensorPolling = true;
screamer 0:eb7f02ad28a7 42 }
screamer 0:eb7f02ad28a7 43
screamer 0:eb7f02ad28a7 44 int main(void)
screamer 0:eb7f02ad28a7 45 {
screamer 0:eb7f02ad28a7 46 led1 = 1;
screamer 0:eb7f02ad28a7 47 Ticker ticker;
screamer 0:eb7f02ad28a7 48 ticker.attach(periodicCallback, 1); // blink LED every second
screamer 0:eb7f02ad28a7 49
screamer 0:eb7f02ad28a7 50 ble.init();
screamer 0:eb7f02ad28a7 51 ble.gap().onDisconnection(disconnectionCallback);
screamer 0:eb7f02ad28a7 52
screamer 0:eb7f02ad28a7 53 /* Setup primary service. */
screamer 0:eb7f02ad28a7 54 uint8_t hrmCounter = 100; // init HRM to 100bps
screamer 0:eb7f02ad28a7 55 HeartRateService hrService(ble, hrmCounter, HeartRateService::LOCATION_FINGER);
screamer 0:eb7f02ad28a7 56
screamer 0:eb7f02ad28a7 57 /* Setup auxiliary service. */
screamer 0:eb7f02ad28a7 58 DeviceInformationService deviceInfo(ble, "ARM", "Model1", "SN1", "hw-rev1", "fw-rev1", "soft-rev1");
screamer 0:eb7f02ad28a7 59
screamer 0:eb7f02ad28a7 60 /* Setup advertising. */
screamer 0:eb7f02ad28a7 61 ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::BREDR_NOT_SUPPORTED | GapAdvertisingData::LE_GENERAL_DISCOVERABLE);
screamer 0:eb7f02ad28a7 62 ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LIST_16BIT_SERVICE_IDS, (uint8_t *)uuid16_list, sizeof(uuid16_list));
screamer 0:eb7f02ad28a7 63 ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::GENERIC_HEART_RATE_SENSOR);
screamer 0:eb7f02ad28a7 64 ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LOCAL_NAME, (uint8_t *)DEVICE_NAME, sizeof(DEVICE_NAME));
screamer 0:eb7f02ad28a7 65 ble.gap().setAdvertisingType(GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED);
screamer 0:eb7f02ad28a7 66 ble.gap().setAdvertisingInterval(1000); /* 1000ms */
screamer 0:eb7f02ad28a7 67 ble.gap().startAdvertising();
screamer 0:eb7f02ad28a7 68
screamer 0:eb7f02ad28a7 69 // infinite loop
screamer 0:eb7f02ad28a7 70 while (1) {
screamer 0:eb7f02ad28a7 71 // check for trigger from periodicCallback()
screamer 0:eb7f02ad28a7 72 if (triggerSensorPolling && ble.getGapState().connected) {
screamer 0:eb7f02ad28a7 73 triggerSensorPolling = false;
screamer 0:eb7f02ad28a7 74
screamer 0:eb7f02ad28a7 75 // Do blocking calls or whatever is necessary for sensor polling.
screamer 0:eb7f02ad28a7 76 // In our case, we simply update the HRM measurement.
screamer 0:eb7f02ad28a7 77 hrmCounter++;
screamer 0:eb7f02ad28a7 78
screamer 0:eb7f02ad28a7 79 // 100 <= HRM bps <=175
screamer 0:eb7f02ad28a7 80 if (hrmCounter == 175) {
screamer 0:eb7f02ad28a7 81 hrmCounter = 100;
screamer 0:eb7f02ad28a7 82 }
screamer 0:eb7f02ad28a7 83
screamer 0:eb7f02ad28a7 84 // update bps
screamer 0:eb7f02ad28a7 85 hrService.updateHeartRate(hrmCounter);
screamer 0:eb7f02ad28a7 86 } else {
screamer 0:eb7f02ad28a7 87 ble.waitForEvent(); // low power wait for event
screamer 0:eb7f02ad28a7 88 }
screamer 0:eb7f02ad28a7 89 }
screamer 0:eb7f02ad28a7 90 }