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-25
- Revision:
- 0:45e5a1daf7c0
- Child:
- 1:e8d3536c7f99
File content as of revision 0:45e5a1daf7c0:
/* 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
Serial 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");
}
