How to turn a WaveShare nRF51-BLE400 into a discoverable beacon using mbed

Dependencies:   mbed BLE_API nRF51822

Port for WaveShare BLE400 (chip nRF51 Aliexpress devboard)
Android Evothings good example for Nordic nRF51822-DK

As target for mbed-online used <Nordic nRF51822>
- (Large green board Nordic nRF51822-mKIT, actually deprecated on 01/03/2019)

Briefly: Handle via Evothings BLE Application 4 LEDs and 2 Buttons(via notify messages).

Figure 1: Evothings Android application screenshot

Evothings application screenshot

Android Evothings application sources

Android application APK

Happy coding!
maxxir 02/03/19

Committer:
maxxir
Date:
Fri Mar 01 19:51:06 2019 +0000
Revision:
17:9071edee0b13
Parent:
16:a84185b72bae
Child:
18:0cbeb28ce4f6
Add some minor comments

Who changed what in which revision?

UserRevisionLine numberNew contents of line
maxxir 16:a84185b72bae 1 /*
maxxir 16:a84185b72bae 2 Port for WaveShare BLE400 Evothings good example for Nordic nRF51822-DK
maxxir 16:a84185b72bae 3 As target for mbed-online used <Nordic nRF51822> (Large green board Nordic nRF51822-mKIT, actually deprecated on ~01/03/2019)
maxxir 16:a84185b72bae 4 Briefly: Handle via Evothings BLE Application 4 LEDs and 2 Buttons(via notify messages).
maxxir 16:a84185b72bae 5
maxxir 16:a84185b72bae 6 This example original:
maxxir 16:a84185b72bae 7 https://os.mbed.com/users/jensstruemper/code/Evothings-Updated/
maxxir 16:a84185b72bae 8 Android application:
maxxir 16:a84185b72bae 9 http://evothings.com/2.2/doc/examples/nordic-nRF51-ble.html
maxxir 16:a84185b72bae 10 This application explanation:
maxxir 16:a84185b72bae 11 How to turn a Nordic Semiconductor nRF51-DK into a discoverable beacon using mbed
maxxir 16:a84185b72bae 12 https://evothings.com/how-to-turn-a-nordic-semiconductor-nrf51-dk-into-a-discoverable-beacon-using-mbed/
maxxir 16:a84185b72bae 13
maxxir 16:a84185b72bae 14 Author porting:
maxxir 16:a84185b72bae 15 Ibragimov Maksim aka maxxir
maxxir 16:a84185b72bae 16 Russia Togliatty
maxxir 16:a84185b72bae 17 01/03/2019
maxxir 16:a84185b72bae 18 */
maxxir 16:a84185b72bae 19
maxxir 16:a84185b72bae 20 /*
maxxir 16:a84185b72bae 21 PS.
maxxir 16:a84185b72bae 22 My Win7 CMD script string example to flash BLE400 via STLINK-V2 && OpenOCD
maxxir 16:a84185b72bae 23 content from flash_ble400.bat:
maxxir 16:a84185b72bae 24 E:\stm32_eclipse_neon\OpenOCD\bin\openocd.exe -d2 -f interface/stlink-v2.cfg ; -f target/nrf51_stlink.tcl -c "program %1 verify reset exit"; shutdown;
maxxir 16:a84185b72bae 25
maxxir 16:a84185b72bae 26 Flash example via console:
maxxir 16:a84185b72bae 27 >flash_ble400.bat BLE_Evothings_NRF51822-BLE400.NRF51822.hex
maxxir 16:a84185b72bae 28 */
maxxir 16:a84185b72bae 29
maxxir 16:a84185b72bae 30 /*
maxxir 16:a84185b72bae 31 * nRF51-DK BLEDevice service/characteristic (read/write) using mbed.org
andresag 15:7e06fce6e4f8 32 */
maxxir 16:a84185b72bae 33
maxxir 16:a84185b72bae 34 // uncomment if not interested in a console log
maxxir 16:a84185b72bae 35 #define CONSOLE_LOG
maxxir 16:a84185b72bae 36
mbedAustin 0:5375be4301ed 37 #include "mbed.h"
andresag 14:1c15d473b42f 38 #include "ble/BLE.h"
andresag 14:1c15d473b42f 39
maxxir 16:a84185b72bae 40 //-------------------------------------------------------------------------
maxxir 16:a84185b72bae 41
maxxir 16:a84185b72bae 42 #ifdef CONSOLE_LOG
maxxir 16:a84185b72bae 43 #define INFO(x, ...) printf(x, ##__VA_ARGS__);
maxxir 16:a84185b72bae 44 #define INFO_NL(x, ...) printf(x "\r\n", ##__VA_ARGS__);
maxxir 16:a84185b72bae 45 #else
maxxir 16:a84185b72bae 46 #define INFO(x, ...)
maxxir 16:a84185b72bae 47 #define INFO_NL(x, ...)
maxxir 16:a84185b72bae 48 #endif
maxxir 16:a84185b72bae 49
maxxir 16:a84185b72bae 50 // a little routine to print a 128-bit UUID nicely
maxxir 16:a84185b72bae 51 void INFO_UUID(const char *prefix, UUID uuid)
maxxir 16:a84185b72bae 52 {
maxxir 16:a84185b72bae 53 uint8_t *p = (uint8_t *)uuid.getBaseUUID();
maxxir 16:a84185b72bae 54 INFO("%s: ", prefix);
maxxir 16:a84185b72bae 55 for (int i=0; i<16; i++)
maxxir 16:a84185b72bae 56 {
maxxir 16:a84185b72bae 57 INFO("%02x", p[i]);
maxxir 16:a84185b72bae 58 if ((i == 3) || (i == 5) || (i == 7) || (i == 9)) INFO("-");
maxxir 16:a84185b72bae 59 }
maxxir 16:a84185b72bae 60 INFO_NL("");
maxxir 16:a84185b72bae 61 }
maxxir 16:a84185b72bae 62
maxxir 16:a84185b72bae 63 //-------------------------------------------------------------------------
maxxir 16:a84185b72bae 64
maxxir 16:a84185b72bae 65 // name of the device
maxxir 17:9071edee0b13 66 const static char DEVICE_NAME[] = "nRF51-BLE400"; //Edit here your name device, and also fix on Evothings APP <index.html> look ~ #136-#137 NRF51_ble.connect('nRF51-BLE400', // BLE name
maxxir 16:a84185b72bae 67
maxxir 16:a84185b72bae 68 // GATT service and characteristic UUIDs
maxxir 17:9071edee0b13 69 const UUID nRF51_GATT_SERVICE = UUID((uint8_t *)"nRF51-DK "); //Decided not edit it too
maxxir 17:9071edee0b13 70 const UUID nRF51_GATT_CHAR_BUTTON = UUID((uint8_t *)"nRF51-DK button "); //Better not edit this, or need fix on Evothings APP <nordic-nRF51-ble.js> look ~ #108 device.setNotification..
maxxir 17:9071edee0b13 71 const UUID nRF51_GATT_CHAR_LED = UUID((uint8_t *)"nRF51-DK led "); //Better not edit this, or need fix on Evothings APP <nordic-nRF51-ble.js> look ~ #93 device.writeDataArray..
maxxir 16:a84185b72bae 72
maxxir 16:a84185b72bae 73 #define CHARACTERISTIC_BUTTON 0
maxxir 16:a84185b72bae 74 #define CHARACTERISTIC_LED 1
maxxir 16:a84185b72bae 75 #define CHARACTERISTIC_COUNT 2
maxxir 16:a84185b72bae 76
maxxir 16:a84185b72bae 77 // our bluetooth smart objects
maxxir 16:a84185b72bae 78 BLE ble;
maxxir 16:a84185b72bae 79 GattService *gatt_service;
maxxir 16:a84185b72bae 80 GattCharacteristic *gatt_characteristics[CHARACTERISTIC_COUNT];
maxxir 16:a84185b72bae 81 uint8_t gatt_char_value[CHARACTERISTIC_COUNT];
maxxir 16:a84185b72bae 82
maxxir 16:a84185b72bae 83 #ifdef CONSOLE_LOG
maxxir 16:a84185b72bae 84 Serial pc(USBTX,USBRX);
maxxir 16:a84185b72bae 85 #endif
maxxir 16:a84185b72bae 86
maxxir 16:a84185b72bae 87 //-------------------------------------------------------------------------
maxxir 16:a84185b72bae 88 // button handling
maxxir 16:a84185b72bae 89 //-------------------------------------------------------------------------
maxxir 16:a84185b72bae 90
maxxir 16:a84185b72bae 91 // define our digital in values we will be using for the characteristic
maxxir 16:a84185b72bae 92 //WaveShare BLE400 edited
maxxir 16:a84185b72bae 93 DigitalIn button1(P0_16);
maxxir 16:a84185b72bae 94 DigitalIn button2(P0_17);
maxxir 16:a84185b72bae 95 //DigitalIn button3(P0_14); //Just substitute for check, actually not present on WaveShare BLE400
maxxir 16:a84185b72bae 96 //DigitalIn button4(P0_15); //Just substitute for check, actually not present on WaveShare BLE400
maxxir 16:a84185b72bae 97
maxxir 16:a84185b72bae 98 uint8_t button_new_value = 0;
maxxir 16:a84185b72bae 99 uint8_t button_old_value = button_new_value;
andresag 14:1c15d473b42f 100
maxxir 16:a84185b72bae 101 void monitorButtons()
maxxir 16:a84185b72bae 102 {
maxxir 16:a84185b72bae 103 // read in the buttons, mapped into nibble (0000 = all off, 1111 = all on)
maxxir 16:a84185b72bae 104 button_new_value = 0;
maxxir 16:a84185b72bae 105 button_new_value |= (button1.read() != 1); button_new_value <<= 1;
maxxir 16:a84185b72bae 106 button_new_value |= (button2.read() != 1); button_new_value <<= 1;
maxxir 16:a84185b72bae 107 //Should not used for WaveShare BLE400
maxxir 16:a84185b72bae 108 /*
maxxir 16:a84185b72bae 109 button_new_value |= (button3.read() != 1); button_new_value <<= 1;
maxxir 16:a84185b72bae 110 button_new_value |= (button4.read() != 1);
maxxir 16:a84185b72bae 111 */
maxxir 16:a84185b72bae 112 // set the updated value of the characteristic if data has changed
maxxir 16:a84185b72bae 113 if (button_new_value != button_old_value)
maxxir 16:a84185b72bae 114 {
maxxir 16:a84185b72bae 115 ble.updateCharacteristicValue(
maxxir 16:a84185b72bae 116 gatt_characteristics[CHARACTERISTIC_BUTTON] -> getValueHandle(),
maxxir 16:a84185b72bae 117 &button_new_value, sizeof(button_new_value));
maxxir 16:a84185b72bae 118 button_old_value = button_new_value;
maxxir 16:a84185b72bae 119
maxxir 16:a84185b72bae 120 INFO_NL(" button state: [0x%02x]", button_new_value);
maxxir 16:a84185b72bae 121 }
maxxir 16:a84185b72bae 122 }
maxxir 16:a84185b72bae 123
maxxir 16:a84185b72bae 124 //-------------------------------------------------------------------------
maxxir 16:a84185b72bae 125 // LED handling
maxxir 16:a84185b72bae 126 //-------------------------------------------------------------------------
maxxir 16:a84185b72bae 127 //WaveShare BLE400 edited
maxxir 16:a84185b72bae 128 DigitalOut led1(P0_18);
maxxir 16:a84185b72bae 129 DigitalOut led2(P0_19);
maxxir 16:a84185b72bae 130 DigitalOut led3(P0_20);
maxxir 16:a84185b72bae 131 DigitalOut led4(P0_21);
maxxir 16:a84185b72bae 132 DigitalOut led5(P0_22); //Actually not used here
maxxir 16:a84185b72bae 133
maxxir 16:a84185b72bae 134 uint8_t led_value = 0;
maxxir 16:a84185b72bae 135
maxxir 16:a84185b72bae 136 /*
maxxir 16:a84185b72bae 137 void onLedDataWritten(const uint8_t* value, uint8_t length)
maxxir 16:a84185b72bae 138 {
maxxir 16:a84185b72bae 139 // we only care about a single byte
maxxir 16:a84185b72bae 140 led_value = value[0];
mbedAustin 0:5375be4301ed 141
maxxir 16:a84185b72bae 142 // depending on the value coming through; set/unset LED's
maxxir 16:a84185b72bae 143 if ((led_value & 0x01) != 0) led1.write(0); else led1.write(1);
maxxir 16:a84185b72bae 144 if ((led_value & 0x02) != 0) led2.write(0); else led2.write(1);
maxxir 16:a84185b72bae 145 if ((led_value & 0x04) != 0) led3.write(0); else led3.write(1);
maxxir 16:a84185b72bae 146 if ((led_value & 0x08) != 0) led4.write(0); else led4.write(1);
maxxir 16:a84185b72bae 147
maxxir 16:a84185b72bae 148 INFO_NL(" led state: [0x%02x]", led_value);
maxxir 16:a84185b72bae 149 }
maxxir 16:a84185b72bae 150 */
maxxir 16:a84185b72bae 151 //Adapted for WaveShare BLE400, LED_ON = HIGH (NRF51822-DK vice versa LED_ON = LOW)
maxxir 16:a84185b72bae 152 void onLedDataWritten(const uint8_t* value, uint8_t length)
maxxir 16:a84185b72bae 153 {
maxxir 16:a84185b72bae 154 // we only care about a single byte
maxxir 16:a84185b72bae 155 led_value = value[0];
maxxir 16:a84185b72bae 156
maxxir 16:a84185b72bae 157 // depending on the value coming through; set/unset LED's
maxxir 16:a84185b72bae 158 if ((led_value & 0x01) != 0) led1.write(1); else led1.write(0);
maxxir 16:a84185b72bae 159 if ((led_value & 0x02) != 0) led2.write(1); else led2.write(0);
maxxir 16:a84185b72bae 160 if ((led_value & 0x04) != 0) led3.write(1); else led3.write(0);
maxxir 16:a84185b72bae 161 if ((led_value & 0x08) != 0) led4.write(1); else led4.write(0);
maxxir 16:a84185b72bae 162
maxxir 16:a84185b72bae 163 INFO_NL(" led state: [0x%02x]", led_value);
maxxir 16:a84185b72bae 164 }
maxxir 16:a84185b72bae 165
maxxir 16:a84185b72bae 166 //-------------------------------------------------------------------------
maxxir 16:a84185b72bae 167
maxxir 16:a84185b72bae 168 void onConnection(const Gap::ConnectionCallbackParams_t *params)
maxxir 16:a84185b72bae 169 {
maxxir 16:a84185b72bae 170 INFO_NL(">> connected");
maxxir 16:a84185b72bae 171
maxxir 16:a84185b72bae 172 // set the initial values of the characteristics (for every session)
maxxir 16:a84185b72bae 173 //led_value = 0;
maxxir 16:a84185b72bae 174 onLedDataWritten(&led_value, 1); // force LED's to be in off state
maxxir 16:a84185b72bae 175 //LED5=ON on connection (for BLE400)
maxxir 16:a84185b72bae 176 led5.write(1);
maxxir 16:a84185b72bae 177 }
maxxir 16:a84185b72bae 178
maxxir 16:a84185b72bae 179 void onDataWritten(const GattWriteCallbackParams *context)
maxxir 16:a84185b72bae 180 {
maxxir 16:a84185b72bae 181 // was the characteristic being written to nRF51_GATT_CHAR_LED?
maxxir 16:a84185b72bae 182 if (context -> handle ==
maxxir 16:a84185b72bae 183 gatt_characteristics[CHARACTERISTIC_LED] -> getValueHandle())
maxxir 16:a84185b72bae 184 {
maxxir 16:a84185b72bae 185 onLedDataWritten(context -> data, context -> len);
maxxir 16:a84185b72bae 186 }
maxxir 16:a84185b72bae 187 }
maxxir 16:a84185b72bae 188
andresag 14:1c15d473b42f 189 void disconnectionCallback(const Gap::DisconnectionCallbackParams_t *params)
andresag 14:1c15d473b42f 190 {
maxxir 16:a84185b72bae 191 INFO_NL(">> disconnected");
maxxir 16:a84185b72bae 192 ble.gap().startAdvertising(); // restart advertising
maxxir 16:a84185b72bae 193 INFO_NL(">> device advertising");
maxxir 16:a84185b72bae 194 //LED5=OFF on connection (for BLE400)
maxxir 16:a84185b72bae 195 led5.write(0);
mbedAustin 8:5442739198ec 196 }
mbedAustin 8:5442739198ec 197
maxxir 16:a84185b72bae 198
maxxir 16:a84185b72bae 199 int main()
mbedAustin 0:5375be4301ed 200 {
maxxir 16:a84185b72bae 201 #ifdef CONSOLE_LOG
maxxir 16:a84185b72bae 202 // wait a second before trying to write something to console
maxxir 16:a84185b72bae 203 wait(1);
maxxir 16:a84185b72bae 204 #endif
maxxir 16:a84185b72bae 205 INFO_NL(">> nRF51-BLE400 start");
maxxir 16:a84185b72bae 206
maxxir 16:a84185b72bae 207 // create our button characteristic (read, notify)
maxxir 16:a84185b72bae 208 gatt_characteristics[CHARACTERISTIC_BUTTON] =
maxxir 16:a84185b72bae 209 new GattCharacteristic(
maxxir 16:a84185b72bae 210 nRF51_GATT_CHAR_BUTTON,
maxxir 16:a84185b72bae 211 &gatt_char_value[CHARACTERISTIC_BUTTON], 1, 1,
maxxir 16:a84185b72bae 212 GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_READ |
maxxir 16:a84185b72bae 213 GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY);
maxxir 16:a84185b72bae 214
maxxir 16:a84185b72bae 215 // create our LED characteristic (read, write)
maxxir 16:a84185b72bae 216 gatt_characteristics[CHARACTERISTIC_LED] =
maxxir 16:a84185b72bae 217 new GattCharacteristic(
maxxir 16:a84185b72bae 218 nRF51_GATT_CHAR_LED,
maxxir 16:a84185b72bae 219 &gatt_char_value[CHARACTERISTIC_LED], 1, 1,
maxxir 16:a84185b72bae 220 GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_READ |
maxxir 16:a84185b72bae 221 GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_WRITE |
maxxir 16:a84185b72bae 222 GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_WRITE_WITHOUT_RESPONSE);
maxxir 16:a84185b72bae 223
maxxir 16:a84185b72bae 224 // create our service, with both characteristics
maxxir 16:a84185b72bae 225 gatt_service =
maxxir 16:a84185b72bae 226 new GattService(nRF51_GATT_SERVICE,
maxxir 16:a84185b72bae 227 gatt_characteristics, CHARACTERISTIC_COUNT);
maxxir 16:a84185b72bae 228
maxxir 16:a84185b72bae 229 // initialize our ble device
maxxir 16:a84185b72bae 230 ble.init();
maxxir 16:a84185b72bae 231 ble.gap().setDeviceName((uint8_t *)DEVICE_NAME);
maxxir 16:a84185b72bae 232 INFO_NL(">> initialized device '%s'", DEVICE_NAME);
mbedAustin 1:0692bee84264 233
maxxir 16:a84185b72bae 234 // configure our advertising type, payload and interval
maxxir 16:a84185b72bae 235 ble.gap().accumulateAdvertisingPayload(
maxxir 16:a84185b72bae 236 GapAdvertisingData::BREDR_NOT_SUPPORTED |
maxxir 16:a84185b72bae 237 GapAdvertisingData::LE_GENERAL_DISCOVERABLE);
maxxir 16:a84185b72bae 238 ble.gap().accumulateAdvertisingPayload(
maxxir 16:a84185b72bae 239 GapAdvertisingData::COMPLETE_LOCAL_NAME,
maxxir 16:a84185b72bae 240 (uint8_t *)DEVICE_NAME, sizeof(DEVICE_NAME));
maxxir 16:a84185b72bae 241 ble.gap().setAdvertisingType(GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED);
maxxir 16:a84185b72bae 242 ble.gap().setAdvertisingInterval(160); // 100ms
maxxir 16:a84185b72bae 243 INFO_NL(">> configured advertising type, payload and interval");
maxxir 16:a84185b72bae 244
maxxir 16:a84185b72bae 245 // configure our callbacks
maxxir 16:a84185b72bae 246 ble.gap().onDisconnection(disconnectionCallback);
maxxir 16:a84185b72bae 247 ble.gap().onConnection(onConnection);
maxxir 16:a84185b72bae 248 ble.onDataWritten(onDataWritten);
maxxir 16:a84185b72bae 249 INFO_NL(">> registered for callbacks");
maxxir 16:a84185b72bae 250
maxxir 16:a84185b72bae 251 // add our gatt service with two characteristics
maxxir 16:a84185b72bae 252 ble.addService(*gatt_service);
maxxir 16:a84185b72bae 253 INFO_NL(">> added GATT service with two characteristics");
maxxir 16:a84185b72bae 254
maxxir 16:a84185b72bae 255 // show some debugging information about service/characteristics
maxxir 16:a84185b72bae 256 INFO_UUID(" ", nRF51_GATT_SERVICE);
maxxir 16:a84185b72bae 257 INFO_UUID(" :", nRF51_GATT_CHAR_BUTTON);
maxxir 16:a84185b72bae 258 INFO_UUID(" :", nRF51_GATT_CHAR_LED);
maxxir 16:a84185b72bae 259
maxxir 16:a84185b72bae 260 // start advertising
maxxir 16:a84185b72bae 261 ble.gap().startAdvertising();
maxxir 16:a84185b72bae 262 INFO_NL(">> device advertising");
maxxir 16:a84185b72bae 263
maxxir 16:a84185b72bae 264 // start monitoring the buttons and posting new values
maxxir 16:a84185b72bae 265 Ticker ticker;
maxxir 16:a84185b72bae 266 ticker.attach(monitorButtons, 0.1); // every 10th of a second
maxxir 16:a84185b72bae 267 INFO_NL(">> monitoring button state");
maxxir 16:a84185b72bae 268
maxxir 16:a84185b72bae 269 // let the device do its thing
maxxir 16:a84185b72bae 270 INFO_NL(">> waiting for events ");
maxxir 16:a84185b72bae 271 for (;;)
maxxir 16:a84185b72bae 272 {
maxxir 16:a84185b72bae 273 ble.waitForEvent();
mbedAustin 1:0692bee84264 274 }
mbedAustin 1:0692bee84264 275 }
maxxir 16:a84185b72bae 276
maxxir 16:a84185b72bae 277 //-------------------------------------------------------------------------