Version working with both Nucleo-F411RE and Nucleo-F404RE

Dependencies:   BLE_API X_NUCLEO_IDB0XA1 mbed

Fork of BLE_HeartRate_IDB0XA1 by ST

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers main.cpp Source File

main.cpp

00001 /* BLE Example Heart rate tutorial, just pay attention that the
00002  * X-Nucleo-BLE board driver is not compatible to the new mbed BLE_API
00003  * so don't update the newest version of BLE_API, also on this example
00004  * we added a custom service (LED-ON/OFF) with 2 characteristics (Read and Write)
00005  * to turn on/off the led
00006  */
00007 
00008 #include "mbed.h"
00009 #include "ble/BLE.h"
00010 #include "ble/services/HeartRateService.h"
00011 #include "ble/services/BatteryService.h"
00012 #include "ble/services/DeviceInformationService.h"
00013 
00014 BLE  ble;
00015 
00016 // If you apply the D13 pin patch you cannot use this led anymore
00017 DigitalOut led1(LED1);
00018 
00019 const static char     DEVICE_NAME[]        = "LeoBoard";
00020 // Has the heart service, device information,
00021 // and a custom service (for controllign the leds)
00022 static const uint16_t uuid16_list[]        = {GattService::UUID_HEART_RATE_SERVICE,
00023         GattService::UUID_DEVICE_INFORMATION_SERVICE, 0xFFFF
00024                                              }; //Custom UUID, FFFF is reserved for development
00025 static volatile bool  triggerSensorPolling = false;
00026 
00027 // Custom service and characteristics UUIDS
00028 uint16_t customServiceUUID  = 0xA000;
00029 uint16_t readCharUUID       = 0xA001;
00030 uint16_t writeCharUUID      = 0xA002;
00031 
00032 // Set Up custom Characteristics (Package max size is 20bytes)
00033 static uint8_t readValue[20] = {0};
00034 ReadOnlyArrayGattCharacteristic<uint8_t, sizeof(readValue)> readChar(readCharUUID, readValue);
00035 static uint8_t writeValue[20] = {0};
00036 WriteOnlyArrayGattCharacteristic<uint8_t, sizeof(writeValue)> writeChar(writeCharUUID, writeValue);
00037 // Set up custom service
00038 GattCharacteristic *characteristics[] = {&readChar, &writeChar};
00039 GattService        customService(customServiceUUID, characteristics, sizeof(characteristics) / sizeof(GattCharacteristic *));
00040 
00041 void disconnectionCallback(const Gap::DisconnectionCallbackParams_t *params) {
00042     printf("Start advertising\r\n");
00043     ble.gap().startAdvertising(); // restart advertising
00044 }
00045 
00046 // Handle writes to writeCharacteristic
00047 void writeCharCallback(const GattWriteCallbackParams *params) {
00048     // check to see what characteristic was written, by handle
00049     if(params->handle == writeChar.getValueHandle()) {
00050         // toggle LED if only 1 byte is written
00051         if(params->len == 1) {
00052             led1 = params->data[0];
00053             (params->data[0] == 0x00) ? printf("led off\n\r") : printf("led on\n\r"); // print led toggle
00054         }        
00055         else {
00056             printf("Data received: length = %d, data = 0x",params->len);
00057             for(int x=0; x < params->len; x++) {
00058                 printf("%x", params->data[x]);
00059             }
00060             printf("\n\r");
00061         }
00062         // update the readChar with the value of writeChar
00063         ble.updateCharacteristicValue(readChar.getValueHandle(), params->data,params->len);
00064     }
00065 }
00066 
00067 void periodicCallback(void)
00068 {
00069     /* Note that the periodicCallback() executes in interrupt context, so it is safer to do
00070      * heavy-weight sensor polling from the main thread. */
00071     triggerSensorPolling = true;
00072 }
00073 
00074 int main(void){
00075     Ticker ticker;
00076     ticker.attach(periodicCallback, 1); // blink LED every second
00077 
00078     printf("Initialize BLE\r\n");
00079     ble.init();
00080     ble.gap().onDisconnection(disconnectionCallback);
00081 
00082     ble.gattServer().onDataWritten(writeCharCallback);
00083 
00084     /* Setup primary service. */
00085     uint8_t hrmCounter = 100; // init HRM to 100bps
00086     HeartRateService hrService(ble, hrmCounter, HeartRateService::LOCATION_FINGER);
00087 
00088     // Device Information
00089     DeviceInformationService deviceInfo(ble, "StarkIndustires", "Quadcopter", "SN1", "hw-rev1", "fw-rev1", "BetaVer");
00090 
00091     // add our custom service
00092     ble.addService(customService);
00093 
00094     // Setup advertising. Indicate that we only support bluetooth low energy
00095     ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::BREDR_NOT_SUPPORTED | GapAdvertisingData::LE_GENERAL_DISCOVERABLE);
00096     ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LIST_16BIT_SERVICE_IDS, (uint8_t *)uuid16_list, sizeof(uuid16_list));
00097     ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::GENERIC_HEART_RATE_SENSOR);
00098     ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LOCAL_NAME, (uint8_t *)DEVICE_NAME, sizeof(DEVICE_NAME));
00099     ble.gap().setAdvertisingType(GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED);
00100     ble.gap().setAdvertisingInterval(1000); /* 1000ms */
00101     ble.gap().startAdvertising();
00102     
00103     while (1) {
00104         // check for trigger from periodicCallback()
00105         if (triggerSensorPolling && ble.getGapState().connected) {
00106             triggerSensorPolling = false;
00107 
00108             // Do blocking calls or whatever is necessary for sensor polling.
00109             // In our case, we simply update the HRM measurement.
00110             hrmCounter++;
00111 
00112             //  100 <= HRM bps <=175
00113             if (hrmCounter == 175) {
00114                 hrmCounter = 100;
00115             }
00116 
00117             // update bps
00118             hrService.updateHeartRate(hrmCounter);
00119         } else {
00120             ble.waitForEvent(); // low power wait for event
00121         }
00122     }
00123 }