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
Android Evothings application sources
Happy coding!
maxxir 02/03/19
main.cpp@18:0cbeb28ce4f6, 2019-03-03 (annotated)
- Committer:
- maxxir
- Date:
- Sun Mar 03 15:14:13 2019 +0000
- Revision:
- 18:0cbeb28ce4f6
- Parent:
- 17:9071edee0b13
Fixed typos
Who changed what in which revision?
User | Revision | Line number | New 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 | 18:0cbeb28ce4f6 | 92 | //WaveShare BLE400 digital inputs as Button inputs |
maxxir | 18:0cbeb28ce4f6 | 93 | DigitalIn button1(P0_16); //KEY1 |
maxxir | 18:0cbeb28ce4f6 | 94 | DigitalIn button2(P0_17); //KEY2 |
maxxir | 18:0cbeb28ce4f6 | 95 | //DigitalIn button3(P0_14); //Should not used for WaveShare BLE400 |
maxxir | 18:0cbeb28ce4f6 | 96 | //DigitalIn button4(P0_15); //Should not used for 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 | 18:0cbeb28ce4f6 | 127 | //WaveShare BLE400 digital outputs as LED outputs |
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 | 18:0cbeb28ce4f6 | 132 | DigitalOut led5(P0_22); //Used here to view BLE connect/disconnect |
maxxir | 16:a84185b72bae | 133 | |
maxxir | 16:a84185b72bae | 134 | uint8_t led_value = 0; |
maxxir | 16:a84185b72bae | 135 | |
maxxir | 16:a84185b72bae | 136 | //Adapted for WaveShare BLE400, LED_ON = HIGH (NRF51822-DK vice versa LED_ON = LOW) |
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]; |
maxxir | 16:a84185b72bae | 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(1); else led1.write(0); |
maxxir | 16:a84185b72bae | 144 | if ((led_value & 0x02) != 0) led2.write(1); else led2.write(0); |
maxxir | 16:a84185b72bae | 145 | if ((led_value & 0x04) != 0) led3.write(1); else led3.write(0); |
maxxir | 16:a84185b72bae | 146 | if ((led_value & 0x08) != 0) led4.write(1); else led4.write(0); |
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 | //------------------------------------------------------------------------- |
maxxir | 16:a84185b72bae | 152 | |
maxxir | 16:a84185b72bae | 153 | void onConnection(const Gap::ConnectionCallbackParams_t *params) |
maxxir | 16:a84185b72bae | 154 | { |
maxxir | 16:a84185b72bae | 155 | INFO_NL(">> connected"); |
maxxir | 16:a84185b72bae | 156 | |
maxxir | 16:a84185b72bae | 157 | // set the initial values of the characteristics (for every session) |
maxxir | 16:a84185b72bae | 158 | //led_value = 0; |
maxxir | 16:a84185b72bae | 159 | onLedDataWritten(&led_value, 1); // force LED's to be in off state |
maxxir | 16:a84185b72bae | 160 | //LED5=ON on connection (for BLE400) |
maxxir | 16:a84185b72bae | 161 | led5.write(1); |
maxxir | 16:a84185b72bae | 162 | } |
maxxir | 16:a84185b72bae | 163 | |
maxxir | 16:a84185b72bae | 164 | void onDataWritten(const GattWriteCallbackParams *context) |
maxxir | 16:a84185b72bae | 165 | { |
maxxir | 16:a84185b72bae | 166 | // was the characteristic being written to nRF51_GATT_CHAR_LED? |
maxxir | 16:a84185b72bae | 167 | if (context -> handle == |
maxxir | 16:a84185b72bae | 168 | gatt_characteristics[CHARACTERISTIC_LED] -> getValueHandle()) |
maxxir | 16:a84185b72bae | 169 | { |
maxxir | 16:a84185b72bae | 170 | onLedDataWritten(context -> data, context -> len); |
maxxir | 16:a84185b72bae | 171 | } |
maxxir | 16:a84185b72bae | 172 | } |
maxxir | 16:a84185b72bae | 173 | |
andresag | 14:1c15d473b42f | 174 | void disconnectionCallback(const Gap::DisconnectionCallbackParams_t *params) |
andresag | 14:1c15d473b42f | 175 | { |
maxxir | 16:a84185b72bae | 176 | INFO_NL(">> disconnected"); |
maxxir | 16:a84185b72bae | 177 | ble.gap().startAdvertising(); // restart advertising |
maxxir | 16:a84185b72bae | 178 | INFO_NL(">> device advertising"); |
maxxir | 18:0cbeb28ce4f6 | 179 | //LED5=OFF on diconnection (for BLE400) |
maxxir | 16:a84185b72bae | 180 | led5.write(0); |
mbedAustin | 8:5442739198ec | 181 | } |
mbedAustin | 8:5442739198ec | 182 | |
maxxir | 16:a84185b72bae | 183 | |
maxxir | 16:a84185b72bae | 184 | int main() |
mbedAustin | 0:5375be4301ed | 185 | { |
maxxir | 16:a84185b72bae | 186 | #ifdef CONSOLE_LOG |
maxxir | 16:a84185b72bae | 187 | // wait a second before trying to write something to console |
maxxir | 16:a84185b72bae | 188 | wait(1); |
maxxir | 16:a84185b72bae | 189 | #endif |
maxxir | 16:a84185b72bae | 190 | INFO_NL(">> nRF51-BLE400 start"); |
maxxir | 16:a84185b72bae | 191 | |
maxxir | 16:a84185b72bae | 192 | // create our button characteristic (read, notify) |
maxxir | 16:a84185b72bae | 193 | gatt_characteristics[CHARACTERISTIC_BUTTON] = |
maxxir | 16:a84185b72bae | 194 | new GattCharacteristic( |
maxxir | 16:a84185b72bae | 195 | nRF51_GATT_CHAR_BUTTON, |
maxxir | 16:a84185b72bae | 196 | &gatt_char_value[CHARACTERISTIC_BUTTON], 1, 1, |
maxxir | 16:a84185b72bae | 197 | GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_READ | |
maxxir | 16:a84185b72bae | 198 | GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY); |
maxxir | 16:a84185b72bae | 199 | |
maxxir | 16:a84185b72bae | 200 | // create our LED characteristic (read, write) |
maxxir | 16:a84185b72bae | 201 | gatt_characteristics[CHARACTERISTIC_LED] = |
maxxir | 16:a84185b72bae | 202 | new GattCharacteristic( |
maxxir | 16:a84185b72bae | 203 | nRF51_GATT_CHAR_LED, |
maxxir | 16:a84185b72bae | 204 | &gatt_char_value[CHARACTERISTIC_LED], 1, 1, |
maxxir | 16:a84185b72bae | 205 | GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_READ | |
maxxir | 16:a84185b72bae | 206 | GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_WRITE | |
maxxir | 16:a84185b72bae | 207 | GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_WRITE_WITHOUT_RESPONSE); |
maxxir | 16:a84185b72bae | 208 | |
maxxir | 16:a84185b72bae | 209 | // create our service, with both characteristics |
maxxir | 16:a84185b72bae | 210 | gatt_service = |
maxxir | 16:a84185b72bae | 211 | new GattService(nRF51_GATT_SERVICE, |
maxxir | 16:a84185b72bae | 212 | gatt_characteristics, CHARACTERISTIC_COUNT); |
maxxir | 16:a84185b72bae | 213 | |
maxxir | 16:a84185b72bae | 214 | // initialize our ble device |
maxxir | 16:a84185b72bae | 215 | ble.init(); |
maxxir | 16:a84185b72bae | 216 | ble.gap().setDeviceName((uint8_t *)DEVICE_NAME); |
maxxir | 16:a84185b72bae | 217 | INFO_NL(">> initialized device '%s'", DEVICE_NAME); |
mbedAustin | 1:0692bee84264 | 218 | |
maxxir | 16:a84185b72bae | 219 | // configure our advertising type, payload and interval |
maxxir | 16:a84185b72bae | 220 | ble.gap().accumulateAdvertisingPayload( |
maxxir | 16:a84185b72bae | 221 | GapAdvertisingData::BREDR_NOT_SUPPORTED | |
maxxir | 16:a84185b72bae | 222 | GapAdvertisingData::LE_GENERAL_DISCOVERABLE); |
maxxir | 16:a84185b72bae | 223 | ble.gap().accumulateAdvertisingPayload( |
maxxir | 16:a84185b72bae | 224 | GapAdvertisingData::COMPLETE_LOCAL_NAME, |
maxxir | 16:a84185b72bae | 225 | (uint8_t *)DEVICE_NAME, sizeof(DEVICE_NAME)); |
maxxir | 16:a84185b72bae | 226 | ble.gap().setAdvertisingType(GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED); |
maxxir | 16:a84185b72bae | 227 | ble.gap().setAdvertisingInterval(160); // 100ms |
maxxir | 16:a84185b72bae | 228 | INFO_NL(">> configured advertising type, payload and interval"); |
maxxir | 16:a84185b72bae | 229 | |
maxxir | 16:a84185b72bae | 230 | // configure our callbacks |
maxxir | 16:a84185b72bae | 231 | ble.gap().onDisconnection(disconnectionCallback); |
maxxir | 16:a84185b72bae | 232 | ble.gap().onConnection(onConnection); |
maxxir | 16:a84185b72bae | 233 | ble.onDataWritten(onDataWritten); |
maxxir | 16:a84185b72bae | 234 | INFO_NL(">> registered for callbacks"); |
maxxir | 16:a84185b72bae | 235 | |
maxxir | 16:a84185b72bae | 236 | // add our gatt service with two characteristics |
maxxir | 16:a84185b72bae | 237 | ble.addService(*gatt_service); |
maxxir | 16:a84185b72bae | 238 | INFO_NL(">> added GATT service with two characteristics"); |
maxxir | 16:a84185b72bae | 239 | |
maxxir | 16:a84185b72bae | 240 | // show some debugging information about service/characteristics |
maxxir | 16:a84185b72bae | 241 | INFO_UUID(" ", nRF51_GATT_SERVICE); |
maxxir | 16:a84185b72bae | 242 | INFO_UUID(" :", nRF51_GATT_CHAR_BUTTON); |
maxxir | 16:a84185b72bae | 243 | INFO_UUID(" :", nRF51_GATT_CHAR_LED); |
maxxir | 16:a84185b72bae | 244 | |
maxxir | 16:a84185b72bae | 245 | // start advertising |
maxxir | 16:a84185b72bae | 246 | ble.gap().startAdvertising(); |
maxxir | 16:a84185b72bae | 247 | INFO_NL(">> device advertising"); |
maxxir | 16:a84185b72bae | 248 | |
maxxir | 16:a84185b72bae | 249 | // start monitoring the buttons and posting new values |
maxxir | 16:a84185b72bae | 250 | Ticker ticker; |
maxxir | 16:a84185b72bae | 251 | ticker.attach(monitorButtons, 0.1); // every 10th of a second |
maxxir | 16:a84185b72bae | 252 | INFO_NL(">> monitoring button state"); |
maxxir | 16:a84185b72bae | 253 | |
maxxir | 16:a84185b72bae | 254 | // let the device do its thing |
maxxir | 16:a84185b72bae | 255 | INFO_NL(">> waiting for events "); |
maxxir | 16:a84185b72bae | 256 | for (;;) |
maxxir | 16:a84185b72bae | 257 | { |
maxxir | 16:a84185b72bae | 258 | ble.waitForEvent(); |
mbedAustin | 1:0692bee84264 | 259 | } |
mbedAustin | 1:0692bee84264 | 260 | } |
maxxir | 16:a84185b72bae | 261 | |
maxxir | 16:a84185b72bae | 262 | //------------------------------------------------------------------------- |