Central/ Peripheral example: Central Device connects to a Peripheral called "LED" and a characteristic is toggled automatically with a random sleep interval (10-100ms) -> BLE_LED_PERIPHERAL needed With a external uC the latency Time of a round trip is measured via pin interrupts.

Dependencies:   BLE_API mbed nRF51822

Fork of BLE_LED_CENTRAL_TIME_AUTO by Alex Gernhaeuser

Committer:
Alexgerni
Date:
Tue Oct 24 18:13:18 2017 +0000
Revision:
0:c201f85a188c
Child:
1:e79b40b523b4
Central/ Peripheral example: Central Device connects to a Peripheral called "LED", additionally a led is toggled with a random interval -> BLE_LED_PERIPHERAL needed.; Furthermore latency time is measured from toggle command until update of the service

Who changed what in which revision?

UserRevisionLine numberNew contents of line
Alexgerni 0:c201f85a188c 1 /* mbed Microcontroller Library
Alexgerni 0:c201f85a188c 2 * Copyright (c) 2006-2015 ARM Limited
Alexgerni 0:c201f85a188c 3 *
Alexgerni 0:c201f85a188c 4 * Licensed under the Apache License, Version 2.0 (the "License");
Alexgerni 0:c201f85a188c 5 * you may not use this file except in compliance with the License.
Alexgerni 0:c201f85a188c 6 * You may obtain a copy of the License at
Alexgerni 0:c201f85a188c 7 *
Alexgerni 0:c201f85a188c 8 * http://www.apache.org/licenses/LICENSE-2.0
Alexgerni 0:c201f85a188c 9 *
Alexgerni 0:c201f85a188c 10 * Unless required by applicable law or agreed to in writing, software
Alexgerni 0:c201f85a188c 11 * distributed under the License is distributed on an "AS IS" BASIS,
Alexgerni 0:c201f85a188c 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
Alexgerni 0:c201f85a188c 13 * See the License for the specific language governing permissions and
Alexgerni 0:c201f85a188c 14 * limitations under the License.
Alexgerni 0:c201f85a188c 15 */
Alexgerni 0:c201f85a188c 16
Alexgerni 0:c201f85a188c 17 #include "mbed.h"
Alexgerni 0:c201f85a188c 18 #include "ble/BLE.h"
Alexgerni 0:c201f85a188c 19 #include "ble/DiscoveredCharacteristic.h"
Alexgerni 0:c201f85a188c 20 #include "LowPowerTimer.h"
Alexgerni 0:c201f85a188c 21
Alexgerni 0:c201f85a188c 22 DigitalOut alivenessLED(p16, 1);
Alexgerni 0:c201f85a188c 23 DigitalOut gateLED(p15,1);
Alexgerni 0:c201f85a188c 24 //InterruptIn button(p9);
Alexgerni 0:c201f85a188c 25 Serial pc(p5, p4);
Alexgerni 0:c201f85a188c 26 Ticker ticker, loop;
Alexgerni 0:c201f85a188c 27 Timer latency;
Alexgerni 0:c201f85a188c 28
Alexgerni 0:c201f85a188c 29 uint16_t latencyTime;
Alexgerni 0:c201f85a188c 30 uint8_t toggledValue = 0x1;
Alexgerni 0:c201f85a188c 31 uint8_t counter = 0;
Alexgerni 0:c201f85a188c 32 uint8_t randNumber = 5;
Alexgerni 0:c201f85a188c 33 uint8_t randCount = 10;
Alexgerni 0:c201f85a188c 34 bool connectionValid = false;
Alexgerni 0:c201f85a188c 35
Alexgerni 0:c201f85a188c 36 static DiscoveredCharacteristic ledCharacteristic;
Alexgerni 0:c201f85a188c 37 static const char PEER_NAME[] = "LED";
Alexgerni 0:c201f85a188c 38
Alexgerni 0:c201f85a188c 39
Alexgerni 0:c201f85a188c 40 void periodicCallback(void)
Alexgerni 0:c201f85a188c 41 {
Alexgerni 0:c201f85a188c 42 if(!connectionValid){
Alexgerni 0:c201f85a188c 43 alivenessLED = !alivenessLED; /* Do blinky on LED1 while waiting for BLE events */
Alexgerni 0:c201f85a188c 44 gateLED = 1;
Alexgerni 0:c201f85a188c 45 }
Alexgerni 0:c201f85a188c 46 counter += 1;
Alexgerni 0:c201f85a188c 47 }
Alexgerni 0:c201f85a188c 48
Alexgerni 0:c201f85a188c 49 void buttonPressedCallback(void)
Alexgerni 0:c201f85a188c 50 {
Alexgerni 0:c201f85a188c 51 randCount = 0;
Alexgerni 0:c201f85a188c 52 if(!connectionValid){
Alexgerni 0:c201f85a188c 53 //pc.printf("not connected \n");
Alexgerni 0:c201f85a188c 54 return;
Alexgerni 0:c201f85a188c 55 }
Alexgerni 0:c201f85a188c 56 else{
Alexgerni 0:c201f85a188c 57 if(counter > 5){
Alexgerni 0:c201f85a188c 58 alivenessLED = 1;
Alexgerni 0:c201f85a188c 59 latency.reset();
Alexgerni 0:c201f85a188c 60 latency.start();
Alexgerni 0:c201f85a188c 61 toggledValue = toggledValue ^ 0x1;
Alexgerni 0:c201f85a188c 62 ledCharacteristic.write(1, &toggledValue);
Alexgerni 0:c201f85a188c 63 //pc.printf("LED toggled... \n");
Alexgerni 0:c201f85a188c 64 }
Alexgerni 0:c201f85a188c 65 }
Alexgerni 0:c201f85a188c 66 }
Alexgerni 0:c201f85a188c 67
Alexgerni 0:c201f85a188c 68 void randCallback(void)
Alexgerni 0:c201f85a188c 69 {
Alexgerni 0:c201f85a188c 70 randCount += 1;
Alexgerni 0:c201f85a188c 71 if(randCount > randNumber+1 && connectionValid){
Alexgerni 0:c201f85a188c 72 buttonPressedCallback();
Alexgerni 0:c201f85a188c 73 gateLED = !gateLED;
Alexgerni 0:c201f85a188c 74 }
Alexgerni 0:c201f85a188c 75 }
Alexgerni 0:c201f85a188c 76
Alexgerni 0:c201f85a188c 77 void advertisementCallback(const Gap::AdvertisementCallbackParams_t *params)
Alexgerni 0:c201f85a188c 78 {
Alexgerni 0:c201f85a188c 79 for (uint8_t i = 0; i < params->advertisingDataLen; ++i) {
Alexgerni 0:c201f85a188c 80
Alexgerni 0:c201f85a188c 81 const uint8_t record_length = params->advertisingData[i];
Alexgerni 0:c201f85a188c 82 if (record_length == 0) {
Alexgerni 0:c201f85a188c 83 continue;
Alexgerni 0:c201f85a188c 84 }
Alexgerni 0:c201f85a188c 85 const uint8_t type = params->advertisingData[i + 1];
Alexgerni 0:c201f85a188c 86 const uint8_t* value = params->advertisingData + i + 2;
Alexgerni 0:c201f85a188c 87 const uint8_t value_length = record_length - 1;
Alexgerni 0:c201f85a188c 88
Alexgerni 0:c201f85a188c 89 if(type == GapAdvertisingData::COMPLETE_LOCAL_NAME) {
Alexgerni 0:c201f85a188c 90 if ((value_length == sizeof(PEER_NAME)) && (memcmp(value, PEER_NAME, value_length) == 0)) { /* compares name LED with advertisingData*/
Alexgerni 0:c201f85a188c 91 pc.printf(
Alexgerni 0:c201f85a188c 92 "adv peerAddr[%02x %02x %02x %02x %02x %02x] rssi %d, isScanResponse %u, AdvertisementType %u\r\n",
Alexgerni 0:c201f85a188c 93 params->peerAddr[5], params->peerAddr[4], params->peerAddr[3], params->peerAddr[2],
Alexgerni 0:c201f85a188c 94 params->peerAddr[1], params->peerAddr[0], params->rssi, params->isScanResponse, params->type
Alexgerni 0:c201f85a188c 95 );
Alexgerni 0:c201f85a188c 96 BLE::Instance().gap().connect(params->peerAddr, Gap::ADDR_TYPE_RANDOM_STATIC, NULL, NULL);
Alexgerni 0:c201f85a188c 97 break;
Alexgerni 0:c201f85a188c 98 }
Alexgerni 0:c201f85a188c 99 }
Alexgerni 0:c201f85a188c 100 i += record_length;
Alexgerni 0:c201f85a188c 101 }
Alexgerni 0:c201f85a188c 102 }
Alexgerni 0:c201f85a188c 103
Alexgerni 0:c201f85a188c 104 void characteristicDiscoveryCallback(const DiscoveredCharacteristic *characteristicP)
Alexgerni 0:c201f85a188c 105 {
Alexgerni 0:c201f85a188c 106 pc.printf(" C UUID-%x valueAttr[%u] props[%x]\r\n", characteristicP->getUUID().getShortUUID(), characteristicP->getValueHandle(), (uint8_t)characteristicP->getProperties().broadcast());
Alexgerni 0:c201f85a188c 107 if (characteristicP->getUUID().getShortUUID() == 0xa001) { /* LED characteristic of device (Read/Write) */
Alexgerni 0:c201f85a188c 108 ledCharacteristic = *characteristicP;
Alexgerni 0:c201f85a188c 109 connectionValid = true;
Alexgerni 0:c201f85a188c 110 }
Alexgerni 0:c201f85a188c 111 }
Alexgerni 0:c201f85a188c 112
Alexgerni 0:c201f85a188c 113 void triggerReadCallback(const GattWriteCallbackParams *response)
Alexgerni 0:c201f85a188c 114 {
Alexgerni 0:c201f85a188c 115 if (response->handle == ledCharacteristic.getValueHandle()) {
Alexgerni 0:c201f85a188c 116 ledCharacteristic.read();
Alexgerni 0:c201f85a188c 117
Alexgerni 0:c201f85a188c 118 latency.stop();
Alexgerni 0:c201f85a188c 119 latencyTime = latency.read_us();
Alexgerni 0:c201f85a188c 120
Alexgerni 0:c201f85a188c 121 //pc.printf("ledCharacteristic: %d %d\r\n",response->data[0],response->data[1]);
Alexgerni 0:c201f85a188c 122 pc.printf("Latency Time: %d",latencyTime);
Alexgerni 0:c201f85a188c 123 pc.printf(" us \n");
Alexgerni 0:c201f85a188c 124 //writeVal(latencyTime);
Alexgerni 0:c201f85a188c 125 randNumber = rand()%10; //number between 0 and 9
Alexgerni 0:c201f85a188c 126
Alexgerni 0:c201f85a188c 127 }
Alexgerni 0:c201f85a188c 128 }
Alexgerni 0:c201f85a188c 129
Alexgerni 0:c201f85a188c 130 void connectionCallback(const Gap::ConnectionCallbackParams_t *params)
Alexgerni 0:c201f85a188c 131 {
Alexgerni 0:c201f85a188c 132 if (params->role == Gap::CENTRAL) {
Alexgerni 0:c201f85a188c 133 BLE &ble = BLE::Instance();
Alexgerni 0:c201f85a188c 134 //ble.gattClient().onServiceDiscoveryTermination(discoveryTerminationCallback);
Alexgerni 0:c201f85a188c 135 ble.gattClient().launchServiceDiscovery(params->handle, NULL, characteristicDiscoveryCallback, 0xa000, 0xa001);
Alexgerni 0:c201f85a188c 136 }
Alexgerni 0:c201f85a188c 137 }
Alexgerni 0:c201f85a188c 138
Alexgerni 0:c201f85a188c 139 void disconnectionCallback(const Gap::DisconnectionCallbackParams_t *)
Alexgerni 0:c201f85a188c 140 {
Alexgerni 0:c201f85a188c 141 pc.printf("disconnected\r\n");
Alexgerni 0:c201f85a188c 142 /* Start scanning and try to connect again */
Alexgerni 0:c201f85a188c 143 BLE::Instance().gap().startScan(advertisementCallback);
Alexgerni 0:c201f85a188c 144 connectionValid = false;
Alexgerni 0:c201f85a188c 145 counter = 0;
Alexgerni 0:c201f85a188c 146 }
Alexgerni 0:c201f85a188c 147
Alexgerni 0:c201f85a188c 148 void onBleInitError(BLE &ble, ble_error_t error)
Alexgerni 0:c201f85a188c 149 {
Alexgerni 0:c201f85a188c 150 /* Initialization error handling should go here */
Alexgerni 0:c201f85a188c 151 }
Alexgerni 0:c201f85a188c 152
Alexgerni 0:c201f85a188c 153 void bleInitComplete(BLE::InitializationCompleteCallbackContext *params)
Alexgerni 0:c201f85a188c 154 {
Alexgerni 0:c201f85a188c 155 BLE& ble = params->ble;
Alexgerni 0:c201f85a188c 156 ble_error_t error = params->error;
Alexgerni 0:c201f85a188c 157
Alexgerni 0:c201f85a188c 158 if (error != BLE_ERROR_NONE) {
Alexgerni 0:c201f85a188c 159 /* In case of error, forward the error handling to onBleInitError */
Alexgerni 0:c201f85a188c 160 onBleInitError(ble, error);
Alexgerni 0:c201f85a188c 161 return;
Alexgerni 0:c201f85a188c 162 }
Alexgerni 0:c201f85a188c 163
Alexgerni 0:c201f85a188c 164 /* Ensure that it is the default instance of BLE */
Alexgerni 0:c201f85a188c 165 if (ble.getInstanceID() != BLE::DEFAULT_INSTANCE) {
Alexgerni 0:c201f85a188c 166 return;
Alexgerni 0:c201f85a188c 167 }
Alexgerni 0:c201f85a188c 168
Alexgerni 0:c201f85a188c 169 ble.gap().onDisconnection(disconnectionCallback);
Alexgerni 0:c201f85a188c 170 ble.gap().onConnection(connectionCallback);
Alexgerni 0:c201f85a188c 171
Alexgerni 0:c201f85a188c 172 ble.gattClient().onDataWrite(triggerReadCallback);
Alexgerni 0:c201f85a188c 173
Alexgerni 0:c201f85a188c 174 // scan interval: 400ms and scan window: 400ms.
Alexgerni 0:c201f85a188c 175 // Every 400ms the device will scan for 400ms
Alexgerni 0:c201f85a188c 176 // This means that the device will scan continuously.
Alexgerni 0:c201f85a188c 177 ble.gap().setScanParams(400, 400);
Alexgerni 0:c201f85a188c 178 ble.gap().startScan(advertisementCallback);
Alexgerni 0:c201f85a188c 179 }
Alexgerni 0:c201f85a188c 180
Alexgerni 0:c201f85a188c 181
Alexgerni 0:c201f85a188c 182 int main(void) {
Alexgerni 0:c201f85a188c 183 pc.baud(115200);
Alexgerni 0:c201f85a188c 184 pc.printf("Initialization starts... \n");
Alexgerni 0:c201f85a188c 185
Alexgerni 0:c201f85a188c 186 ticker.attach(periodicCallback, 1); /* Blink LED every second */
Alexgerni 0:c201f85a188c 187 //button.rise(buttonPressedCallback);
Alexgerni 0:c201f85a188c 188 loop.attach(randCallback, 0.1);
Alexgerni 0:c201f85a188c 189 srand(time(NULL));
Alexgerni 0:c201f85a188c 190
Alexgerni 0:c201f85a188c 191 BLE &ble = BLE::Instance();
Alexgerni 0:c201f85a188c 192 ble.init(bleInitComplete);
Alexgerni 0:c201f85a188c 193
Alexgerni 0:c201f85a188c 194 counter = 0;
Alexgerni 0:c201f85a188c 195 latency.reset();
Alexgerni 0:c201f85a188c 196
Alexgerni 0:c201f85a188c 197 while (true) {
Alexgerni 0:c201f85a188c 198 ble.waitForEvent();
Alexgerni 0:c201f85a188c 199 }
Alexgerni 0:c201f85a188c 200 }