Version working with both Nucleo-F411RE and Nucleo-F404RE

Dependencies:   BLE_API X_NUCLEO_IDB0XA1 mbed

Fork of BLE_HeartRate_IDB0XA1 by ST

Committer:
leonardoaraujosantos
Date:
Tue Nov 03 23:12:18 2015 +0000
Revision:
5:cc8528cbf546
Parent:
4:821e9af5e750
Working version;

Who changed what in which revision?

UserRevisionLine numberNew contents of line
leonardoaraujosantos 4:821e9af5e750 1 /* BLE Example Heart rate tutorial, just pay attention that the
leonardoaraujosantos 4:821e9af5e750 2 * X-Nucleo-BLE board driver is not compatible to the new mbed BLE_API
leonardoaraujosantos 4:821e9af5e750 3 * so don't update the newest version of BLE_API, also on this example
leonardoaraujosantos 4:821e9af5e750 4 * we added a custom service (LED-ON/OFF) with 2 characteristics (Read and Write)
leonardoaraujosantos 4:821e9af5e750 5 * to turn on/off the led
screamer 0:eb7f02ad28a7 6 */
screamer 0:eb7f02ad28a7 7
screamer 0:eb7f02ad28a7 8 #include "mbed.h"
screamer 0:eb7f02ad28a7 9 #include "ble/BLE.h"
screamer 0:eb7f02ad28a7 10 #include "ble/services/HeartRateService.h"
screamer 0:eb7f02ad28a7 11 #include "ble/services/BatteryService.h"
screamer 0:eb7f02ad28a7 12 #include "ble/services/DeviceInformationService.h"
screamer 0:eb7f02ad28a7 13
screamer 0:eb7f02ad28a7 14 BLE ble;
leonardoaraujosantos 4:821e9af5e750 15
leonardoaraujosantos 4:821e9af5e750 16 // If you apply the D13 pin patch you cannot use this led anymore
screamer 0:eb7f02ad28a7 17 DigitalOut led1(LED1);
screamer 0:eb7f02ad28a7 18
leonardoaraujosantos 4:821e9af5e750 19 const static char DEVICE_NAME[] = "LeoBoard";
leonardoaraujosantos 4:821e9af5e750 20 // Has the heart service, device information,
leonardoaraujosantos 4:821e9af5e750 21 // and a custom service (for controllign the leds)
screamer 0:eb7f02ad28a7 22 static const uint16_t uuid16_list[] = {GattService::UUID_HEART_RATE_SERVICE,
leonardoaraujosantos 4:821e9af5e750 23 GattService::UUID_DEVICE_INFORMATION_SERVICE, 0xFFFF
leonardoaraujosantos 4:821e9af5e750 24 }; //Custom UUID, FFFF is reserved for development
screamer 0:eb7f02ad28a7 25 static volatile bool triggerSensorPolling = false;
screamer 0:eb7f02ad28a7 26
leonardoaraujosantos 4:821e9af5e750 27 // Custom service and characteristics UUIDS
leonardoaraujosantos 4:821e9af5e750 28 uint16_t customServiceUUID = 0xA000;
leonardoaraujosantos 4:821e9af5e750 29 uint16_t readCharUUID = 0xA001;
leonardoaraujosantos 4:821e9af5e750 30 uint16_t writeCharUUID = 0xA002;
leonardoaraujosantos 4:821e9af5e750 31
leonardoaraujosantos 4:821e9af5e750 32 // Set Up custom Characteristics (Package max size is 20bytes)
leonardoaraujosantos 4:821e9af5e750 33 static uint8_t readValue[20] = {0};
leonardoaraujosantos 4:821e9af5e750 34 ReadOnlyArrayGattCharacteristic<uint8_t, sizeof(readValue)> readChar(readCharUUID, readValue);
leonardoaraujosantos 4:821e9af5e750 35 static uint8_t writeValue[20] = {0};
leonardoaraujosantos 4:821e9af5e750 36 WriteOnlyArrayGattCharacteristic<uint8_t, sizeof(writeValue)> writeChar(writeCharUUID, writeValue);
leonardoaraujosantos 4:821e9af5e750 37 // Set up custom service
leonardoaraujosantos 4:821e9af5e750 38 GattCharacteristic *characteristics[] = {&readChar, &writeChar};
leonardoaraujosantos 4:821e9af5e750 39 GattService customService(customServiceUUID, characteristics, sizeof(characteristics) / sizeof(GattCharacteristic *));
leonardoaraujosantos 4:821e9af5e750 40
leonardoaraujosantos 4:821e9af5e750 41 void disconnectionCallback(const Gap::DisconnectionCallbackParams_t *params) {
leonardoaraujosantos 4:821e9af5e750 42 printf("Start advertising\r\n");
screamer 0:eb7f02ad28a7 43 ble.gap().startAdvertising(); // restart advertising
screamer 0:eb7f02ad28a7 44 }
screamer 0:eb7f02ad28a7 45
leonardoaraujosantos 4:821e9af5e750 46 // Handle writes to writeCharacteristic
leonardoaraujosantos 4:821e9af5e750 47 void writeCharCallback(const GattWriteCallbackParams *params) {
leonardoaraujosantos 4:821e9af5e750 48 // check to see what characteristic was written, by handle
leonardoaraujosantos 4:821e9af5e750 49 if(params->handle == writeChar.getValueHandle()) {
leonardoaraujosantos 4:821e9af5e750 50 // toggle LED if only 1 byte is written
leonardoaraujosantos 4:821e9af5e750 51 if(params->len == 1) {
leonardoaraujosantos 4:821e9af5e750 52 led1 = params->data[0];
leonardoaraujosantos 4:821e9af5e750 53 (params->data[0] == 0x00) ? printf("led off\n\r") : printf("led on\n\r"); // print led toggle
leonardoaraujosantos 4:821e9af5e750 54 }
leonardoaraujosantos 4:821e9af5e750 55 else {
leonardoaraujosantos 4:821e9af5e750 56 printf("Data received: length = %d, data = 0x",params->len);
leonardoaraujosantos 4:821e9af5e750 57 for(int x=0; x < params->len; x++) {
leonardoaraujosantos 4:821e9af5e750 58 printf("%x", params->data[x]);
leonardoaraujosantos 4:821e9af5e750 59 }
leonardoaraujosantos 4:821e9af5e750 60 printf("\n\r");
leonardoaraujosantos 4:821e9af5e750 61 }
leonardoaraujosantos 4:821e9af5e750 62 // update the readChar with the value of writeChar
leonardoaraujosantos 4:821e9af5e750 63 ble.updateCharacteristicValue(readChar.getValueHandle(), params->data,params->len);
leonardoaraujosantos 4:821e9af5e750 64 }
leonardoaraujosantos 4:821e9af5e750 65 }
leonardoaraujosantos 4:821e9af5e750 66
screamer 0:eb7f02ad28a7 67 void periodicCallback(void)
screamer 0:eb7f02ad28a7 68 {
screamer 0:eb7f02ad28a7 69 /* Note that the periodicCallback() executes in interrupt context, so it is safer to do
screamer 0:eb7f02ad28a7 70 * heavy-weight sensor polling from the main thread. */
screamer 0:eb7f02ad28a7 71 triggerSensorPolling = true;
screamer 0:eb7f02ad28a7 72 }
screamer 0:eb7f02ad28a7 73
leonardoaraujosantos 4:821e9af5e750 74 int main(void){
screamer 0:eb7f02ad28a7 75 Ticker ticker;
screamer 0:eb7f02ad28a7 76 ticker.attach(periodicCallback, 1); // blink LED every second
screamer 0:eb7f02ad28a7 77
leonardoaraujosantos 4:821e9af5e750 78 printf("Initialize BLE\r\n");
screamer 0:eb7f02ad28a7 79 ble.init();
screamer 0:eb7f02ad28a7 80 ble.gap().onDisconnection(disconnectionCallback);
screamer 0:eb7f02ad28a7 81
leonardoaraujosantos 4:821e9af5e750 82 ble.gattServer().onDataWritten(writeCharCallback);
leonardoaraujosantos 4:821e9af5e750 83
screamer 0:eb7f02ad28a7 84 /* Setup primary service. */
screamer 0:eb7f02ad28a7 85 uint8_t hrmCounter = 100; // init HRM to 100bps
screamer 0:eb7f02ad28a7 86 HeartRateService hrService(ble, hrmCounter, HeartRateService::LOCATION_FINGER);
screamer 0:eb7f02ad28a7 87
leonardoaraujosantos 4:821e9af5e750 88 // Device Information
leonardoaraujosantos 4:821e9af5e750 89 DeviceInformationService deviceInfo(ble, "StarkIndustires", "Quadcopter", "SN1", "hw-rev1", "fw-rev1", "BetaVer");
screamer 0:eb7f02ad28a7 90
leonardoaraujosantos 4:821e9af5e750 91 // add our custom service
leonardoaraujosantos 4:821e9af5e750 92 ble.addService(customService);
leonardoaraujosantos 4:821e9af5e750 93
leonardoaraujosantos 4:821e9af5e750 94 // Setup advertising. Indicate that we only support bluetooth low energy
screamer 0:eb7f02ad28a7 95 ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::BREDR_NOT_SUPPORTED | GapAdvertisingData::LE_GENERAL_DISCOVERABLE);
screamer 0:eb7f02ad28a7 96 ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LIST_16BIT_SERVICE_IDS, (uint8_t *)uuid16_list, sizeof(uuid16_list));
screamer 0:eb7f02ad28a7 97 ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::GENERIC_HEART_RATE_SENSOR);
screamer 0:eb7f02ad28a7 98 ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LOCAL_NAME, (uint8_t *)DEVICE_NAME, sizeof(DEVICE_NAME));
screamer 0:eb7f02ad28a7 99 ble.gap().setAdvertisingType(GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED);
screamer 0:eb7f02ad28a7 100 ble.gap().setAdvertisingInterval(1000); /* 1000ms */
screamer 0:eb7f02ad28a7 101 ble.gap().startAdvertising();
leonardoaraujosantos 4:821e9af5e750 102
screamer 0:eb7f02ad28a7 103 while (1) {
screamer 0:eb7f02ad28a7 104 // check for trigger from periodicCallback()
screamer 0:eb7f02ad28a7 105 if (triggerSensorPolling && ble.getGapState().connected) {
screamer 0:eb7f02ad28a7 106 triggerSensorPolling = false;
screamer 0:eb7f02ad28a7 107
screamer 0:eb7f02ad28a7 108 // Do blocking calls or whatever is necessary for sensor polling.
screamer 0:eb7f02ad28a7 109 // In our case, we simply update the HRM measurement.
screamer 0:eb7f02ad28a7 110 hrmCounter++;
screamer 0:eb7f02ad28a7 111
screamer 0:eb7f02ad28a7 112 // 100 <= HRM bps <=175
screamer 0:eb7f02ad28a7 113 if (hrmCounter == 175) {
screamer 0:eb7f02ad28a7 114 hrmCounter = 100;
screamer 0:eb7f02ad28a7 115 }
screamer 0:eb7f02ad28a7 116
screamer 0:eb7f02ad28a7 117 // update bps
screamer 0:eb7f02ad28a7 118 hrService.updateHeartRate(hrmCounter);
screamer 0:eb7f02ad28a7 119 } else {
screamer 0:eb7f02ad28a7 120 ble.waitForEvent(); // low power wait for event
screamer 0:eb7f02ad28a7 121 }
screamer 0:eb7f02ad28a7 122 }
screamer 0:eb7f02ad28a7 123 }