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
- Committer:
- maxxir
- Date:
- 2019-03-03
- Revision:
- 18:0cbeb28ce4f6
- Parent:
- 17:9071edee0b13
File content as of revision 18:0cbeb28ce4f6:
/* Port for WaveShare BLE400 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). This example original: https://os.mbed.com/users/jensstruemper/code/Evothings-Updated/ Android application: http://evothings.com/2.2/doc/examples/nordic-nRF51-ble.html This application explanation: How to turn a Nordic Semiconductor nRF51-DK into a discoverable beacon using mbed https://evothings.com/how-to-turn-a-nordic-semiconductor-nrf51-dk-into-a-discoverable-beacon-using-mbed/ Author porting: Ibragimov Maksim aka maxxir Russia Togliatty 01/03/2019 */ /* PS. My Win7 CMD script string example to flash BLE400 via STLINK-V2 && OpenOCD content from flash_ble400.bat: 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; Flash example via console: >flash_ble400.bat BLE_Evothings_NRF51822-BLE400.NRF51822.hex */ /* * nRF51-DK BLEDevice service/characteristic (read/write) using mbed.org */ // uncomment if not interested in a console log #define CONSOLE_LOG #include "mbed.h" #include "ble/BLE.h" //------------------------------------------------------------------------- #ifdef CONSOLE_LOG #define INFO(x, ...) printf(x, ##__VA_ARGS__); #define INFO_NL(x, ...) printf(x "\r\n", ##__VA_ARGS__); #else #define INFO(x, ...) #define INFO_NL(x, ...) #endif // a little routine to print a 128-bit UUID nicely void INFO_UUID(const char *prefix, UUID uuid) { uint8_t *p = (uint8_t *)uuid.getBaseUUID(); INFO("%s: ", prefix); for (int i=0; i<16; i++) { INFO("%02x", p[i]); if ((i == 3) || (i == 5) || (i == 7) || (i == 9)) INFO("-"); } INFO_NL(""); } //------------------------------------------------------------------------- // name of the device 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 // GATT service and characteristic UUIDs const UUID nRF51_GATT_SERVICE = UUID((uint8_t *)"nRF51-DK "); //Decided not edit it too 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.. 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.. #define CHARACTERISTIC_BUTTON 0 #define CHARACTERISTIC_LED 1 #define CHARACTERISTIC_COUNT 2 // our bluetooth smart objects BLE ble; GattService *gatt_service; GattCharacteristic *gatt_characteristics[CHARACTERISTIC_COUNT]; uint8_t gatt_char_value[CHARACTERISTIC_COUNT]; #ifdef CONSOLE_LOG Serial pc(USBTX,USBRX); #endif //------------------------------------------------------------------------- // button handling //------------------------------------------------------------------------- // define our digital in values we will be using for the characteristic //WaveShare BLE400 digital inputs as Button inputs DigitalIn button1(P0_16); //KEY1 DigitalIn button2(P0_17); //KEY2 //DigitalIn button3(P0_14); //Should not used for WaveShare BLE400 //DigitalIn button4(P0_15); //Should not used for WaveShare BLE400 uint8_t button_new_value = 0; uint8_t button_old_value = button_new_value; void monitorButtons() { // read in the buttons, mapped into nibble (0000 = all off, 1111 = all on) button_new_value = 0; button_new_value |= (button1.read() != 1); button_new_value <<= 1; button_new_value |= (button2.read() != 1); button_new_value <<= 1; //Should not used for WaveShare BLE400 /* button_new_value |= (button3.read() != 1); button_new_value <<= 1; button_new_value |= (button4.read() != 1); */ // set the updated value of the characteristic if data has changed if (button_new_value != button_old_value) { ble.updateCharacteristicValue( gatt_characteristics[CHARACTERISTIC_BUTTON] -> getValueHandle(), &button_new_value, sizeof(button_new_value)); button_old_value = button_new_value; INFO_NL(" button state: [0x%02x]", button_new_value); } } //------------------------------------------------------------------------- // LED handling //------------------------------------------------------------------------- //WaveShare BLE400 digital outputs as LED outputs DigitalOut led1(P0_18); DigitalOut led2(P0_19); DigitalOut led3(P0_20); DigitalOut led4(P0_21); DigitalOut led5(P0_22); //Used here to view BLE connect/disconnect uint8_t led_value = 0; //Adapted for WaveShare BLE400, LED_ON = HIGH (NRF51822-DK vice versa LED_ON = LOW) void onLedDataWritten(const uint8_t* value, uint8_t length) { // we only care about a single byte led_value = value[0]; // depending on the value coming through; set/unset LED's if ((led_value & 0x01) != 0) led1.write(1); else led1.write(0); if ((led_value & 0x02) != 0) led2.write(1); else led2.write(0); if ((led_value & 0x04) != 0) led3.write(1); else led3.write(0); if ((led_value & 0x08) != 0) led4.write(1); else led4.write(0); INFO_NL(" led state: [0x%02x]", led_value); } //------------------------------------------------------------------------- void onConnection(const Gap::ConnectionCallbackParams_t *params) { INFO_NL(">> connected"); // set the initial values of the characteristics (for every session) //led_value = 0; onLedDataWritten(&led_value, 1); // force LED's to be in off state //LED5=ON on connection (for BLE400) led5.write(1); } void onDataWritten(const GattWriteCallbackParams *context) { // was the characteristic being written to nRF51_GATT_CHAR_LED? if (context -> handle == gatt_characteristics[CHARACTERISTIC_LED] -> getValueHandle()) { onLedDataWritten(context -> data, context -> len); } } void disconnectionCallback(const Gap::DisconnectionCallbackParams_t *params) { INFO_NL(">> disconnected"); ble.gap().startAdvertising(); // restart advertising INFO_NL(">> device advertising"); //LED5=OFF on diconnection (for BLE400) led5.write(0); } int main() { #ifdef CONSOLE_LOG // wait a second before trying to write something to console wait(1); #endif INFO_NL(">> nRF51-BLE400 start"); // create our button characteristic (read, notify) gatt_characteristics[CHARACTERISTIC_BUTTON] = new GattCharacteristic( nRF51_GATT_CHAR_BUTTON, &gatt_char_value[CHARACTERISTIC_BUTTON], 1, 1, GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_READ | GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY); // create our LED characteristic (read, write) gatt_characteristics[CHARACTERISTIC_LED] = new GattCharacteristic( nRF51_GATT_CHAR_LED, &gatt_char_value[CHARACTERISTIC_LED], 1, 1, GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_READ | GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_WRITE | GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_WRITE_WITHOUT_RESPONSE); // create our service, with both characteristics gatt_service = new GattService(nRF51_GATT_SERVICE, gatt_characteristics, CHARACTERISTIC_COUNT); // initialize our ble device ble.init(); ble.gap().setDeviceName((uint8_t *)DEVICE_NAME); INFO_NL(">> initialized device '%s'", DEVICE_NAME); // configure our advertising type, payload and interval ble.gap().accumulateAdvertisingPayload( GapAdvertisingData::BREDR_NOT_SUPPORTED | GapAdvertisingData::LE_GENERAL_DISCOVERABLE); ble.gap().accumulateAdvertisingPayload( GapAdvertisingData::COMPLETE_LOCAL_NAME, (uint8_t *)DEVICE_NAME, sizeof(DEVICE_NAME)); ble.gap().setAdvertisingType(GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED); ble.gap().setAdvertisingInterval(160); // 100ms INFO_NL(">> configured advertising type, payload and interval"); // configure our callbacks ble.gap().onDisconnection(disconnectionCallback); ble.gap().onConnection(onConnection); ble.onDataWritten(onDataWritten); INFO_NL(">> registered for callbacks"); // add our gatt service with two characteristics ble.addService(*gatt_service); INFO_NL(">> added GATT service with two characteristics"); // show some debugging information about service/characteristics INFO_UUID(" ", nRF51_GATT_SERVICE); INFO_UUID(" :", nRF51_GATT_CHAR_BUTTON); INFO_UUID(" :", nRF51_GATT_CHAR_LED); // start advertising ble.gap().startAdvertising(); INFO_NL(">> device advertising"); // start monitoring the buttons and posting new values Ticker ticker; ticker.attach(monitorButtons, 0.1); // every 10th of a second INFO_NL(">> monitoring button state"); // let the device do its thing INFO_NL(">> waiting for events "); for (;;) { ble.waitForEvent(); } } //-------------------------------------------------------------------------