![](/media/cache/img/default_profile.jpg.50x50_q85.jpg)
Techcon 2014 BLE sample Police HRM (button-based) for Nordic
Dependencies: BLE_API BufferedSerial mbed nRF51822
Fork of BLE_Police_HRM by
main.cpp
- Committer:
- ansond
- Date:
- 2014-09-26
- Revision:
- 1:e8d3536c7f99
- Parent:
- 0:45e5a1daf7c0
File content as of revision 1:e8d3536c7f99:
/* mbed Microcontroller Library * Copyright (c) 2006-2013 ARM Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "mbed.h" #include "BLEDevice.h" #include "HeartRateService.h" // ********************* BEGIN Tunables for TechCon 2014 // !!!!IMPORTANT!!!! CHANGE DEVICE_NAME so that you can find *YOUR* Nordic board in the workshop on your phone!! const static char DEVICE_NAME[] = "Policeman #1234"; // what we want to appear as in mBED device server #define HRM_INCREMENT 10 // increment of HRM per button press (+/-) #define HRM_DEFAULT_INIT 70 // default HRM (button only... earbud defaults to offline status) #define ENABLE_CONSOLE 1 // 0 - no serial output, 1 - serial output #define HRM_MIN 10 // min heartrate #define HRM_MAX 250 // max heartrate #define HRM_DEFAULT_INIT 70 // initial heartrate (buttons only, earbud will default differently) // ********************* END Tunables for Techcon 2014 volatile uint16_t hrmCounter = HRM_DEFAULT_INIT; // initial heartrate int oldhrmCounter = HRM_MAX+1; // tracker so that we only send when things change appropriately // Support for the Grove Ear-Clip Earbud #define USE_EARBUD false // true - enable (pin P0_0), false - disable (default) // Globals BLEDevice ble; DigitalOut led1(LED1); volatile bool connected = false; // Console allocation #if ENABLE_CONSOLE #include "BufferedSerial.h" BufferedSerial pc(USBTX, USBRX); #define LOG_CONSOLE(...) { pc.printf(__VA_ARGS__); } #else #define LOG_CONSOLE(...) #endif // Earbud allocation (or button usage) #if USE_EARBUD #include "GroveEarbudSensor.h" InterruptIn sensor(P0_0); GroveEarbudSensor earbud(&sensor,&pc); #else DigitalIn up(BUTTON1); DigitalIn down(BUTTON2); #endif // BLE Globals static const uint16_t uuid16_list[] = {GattService::UUID_HEART_RATE_SERVICE}; static volatile bool triggerSensorPolling = false; // Disconnection callback void disconnectionCallback(Gap::Handle_t handle, Gap::DisconnectionReason_t reason) { LOG_CONSOLE("Disconnected handle %u!\r\n", handle); LOG_CONSOLE("Restarting the advertising process\r\n"); ble.startAdvertising(); connected = false; oldhrmCounter = HRM_MAX+1; #if USE_EARBUD hrmCounter = HEARTRATE_OFF; #else hrmCounter = HRM_DEFAULT_INIT; #endif } // Connection callback void connectionCallback(Gap::Handle_t handle, const Gap::ConnectionParams_t *parms) { LOG_CONSOLE("Endpoint is connected!\r\n"); connected = true; } // Periodic callback void periodicCallback(void) { led1 = !led1; /* Do blinky on LED1 while we're waiting for BLE events */ /* Note that the periodicCallback() executes in interrupt context, so it is safer to do * heavy-weight sensor polling from the main thread. */ triggerSensorPolling = true; } #if USE_EARBUD // Heartrate callback (Earbud) void heartrateCallback(float heartrate,void *data) { hrmCounter = (int)heartrate; } #endif // main entry point int main(void) { bool do_loop = true; led1 = 1; Ticker ticker; ticker.attach(periodicCallback, 1); #if USE_EARBUD LOG_CONSOLE("\r\nmbed PoliceHRM (EARBUD) v1.0 (ARM Techcon 2014)\r\n"); #else LOG_CONSOLE("\r\nmbed PoliceHRM (BUTTON) v1.0 (ARM Techcon 2014)\r\n"); #endif ble.init(); ble.onDisconnection(disconnectionCallback); ble.onConnection(connectionCallback); /* setup advertising */ LOG_CONSOLE("Starting BLE Advertising...\r\n"); ble.accumulateAdvertisingPayload(GapAdvertisingData::BREDR_NOT_SUPPORTED | GapAdvertisingData::LE_GENERAL_DISCOVERABLE); ble.accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LIST_16BIT_SERVICE_IDS, (uint8_t *)uuid16_list, sizeof(uuid16_list)); ble.accumulateAdvertisingPayload(GapAdvertisingData::HEART_RATE_SENSOR_HEART_RATE_BELT); ble.accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LOCAL_NAME, (uint8_t *)DEVICE_NAME, sizeof(DEVICE_NAME)); ble.setAdvertisingType(GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED); ble.setAdvertisingInterval(1600); /* 1000ms; in multiples of 0.625ms. */ ble.startAdvertising(); #if USE_EARBUD // initialize the earbud LOG_CONSOLE("Initializing Earbud...\r\n"); hrmCounter = HEARTRATE_OFF; earbud.registerCallback(heartrateCallback); #endif // Start the HRM Service LOG_CONSOLE("Starting HRM Service...\r\n"); #if !USE_EARBUD HeartRateService hrService(ble, hrmCounter, HeartRateService::LOCATION_WRIST); #else HeartRateService hrService(ble, hrmCounter, HeartRateService::LOCATION_EAR_LOBE); #endif // Loop LOG_CONSOLE("Entering main loop...\r\n"); while (do_loop) { if (triggerSensorPolling) { triggerSensorPolling = false; #if !USE_EARBUD // see if either button was pressed and adjust the heartrate accordingly //LOG_CONSOLE("Updating HRM via button...\r\n"); if (up) hrmCounter += HRM_INCREMENT; if (down) hrmCounter -= HRM_INCREMENT; // boundary checking if (hrmCounter < 0) hrmCounter = 0; else if (hrmCounter < HRM_MIN) hrmCounter = HRM_MIN; else if (hrmCounter > HRM_MAX) hrmCounter = HRM_MAX; #endif // update the heartrate service if it has changed if (hrmCounter != oldhrmCounter) { LOG_CONSOLE("Updating HRM values...%d bpm\r\n",hrmCounter); hrService.updateHeartRate(hrmCounter); if (connected == true) oldhrmCounter = hrmCounter; } } else { ble.waitForEvent(); } } // we have exited LOG_CONSOLE("Application exiting...\r\n"); }