This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

nRF5 SDK 15.3.0 initial guidance

Hello,

I’ve developed a BLE peripheral product using Simblee (nRF51822 revision 3), now discontinued. We’ve decided to switch to Laird’s BL651 module and implement the app using nRF5 SDK 15.3.0. I’m new to nRF5 SDK and low-level access to BLE. I would appreciate some initial guidance.

Simblee allowed BLE peripheral development using the Arduino IDE and insulated developers from a lot of the complexities of BLE. I wrote code like this:

Setup …

SimbleeBLE.customUUID = "2220";
SimbleeBLE.txPowerLevel = +4;
SimbleeBLE.deviceName = peripheralName;
SimbleeBLE.advertisementData = advData;
SimbleeBLE.advertisementInterval = 500;
SimbleeBLE.begin();

To send data to the connected iOS app (BLE central):

SimbleeBLE.send(message, sizeof(message));

Interrupt routine for receiving data from the iOS app:

void SimbleeBLE_onReceive(char *data, int len)
{
  ...
}

The peripheral monitors a single GPIO pin and uses GPIOTE, PPI and timers for timing-critical code, which the Simblee library exposed. And we use OTA DFU to push out BLE peripheral app updates via our iOS app.

Simblee has a single service (0x2220) with a send (write) characteristic (0x2222), a receive (read, notify) characteristic (0x2221) and a disconnect (write) characteristic (0x2223). Seems pretty simple.

I have the nRF52 dev kit (which has an nRF52832, but can emulate the nRF52810, which is on Laird's BL651) and I have some of the Nordic examples working (using Segger Embedded Studio on macOS).

I would appreciate some initial guidance. Is the Nordic UART Service appropriate? Would the ble_peripheral/ble_app_uart SDK example be a reasonable starting point? What to focus my learning on? Security is not important, nor is power efficiency (we run on AA batteries and the product is used, on average, 20 hours per month). I would like the app to use the same service and characteristic UUIDs so that it will function with our current BLE central iOS app.

I appreciate any guidance. Many thanks,

Tim

  • Thanks Torbjørn. You make it clear that we are to use a vendor-specific UUID, or register on with the Bluetooth SIG. I took a quick look and see that we would need to become SIG members, then apply for a UUID ($2,500 each). Our product is a very niche product, likely to sell only into the 1,000s (currently just under 700 in the field). My sense is we'd be okay to generate our own vendor-specific UUID, but would appreciate your thoughts on this. Any pros/cons of registering a UUID with the SIG versus generating/using our own vendor-specific ID?

    About manufacture ID, our Simblee code sets the advertisement data to 0x00007274696D6572.

    SimbleeBLE.advertisementData = advData;

    I noticed that LightBlue shows this value as the Manufacture Data. Maybe for Simblee. the above statement sets both?

    We do this so that when our central (iOS app) scans for peripherals and a peripheral with service UUID 0x2220 is discovered, we check the advertisement data and if it matches, we assume it's one of our devices that has been discovered, and not another RFduino-based device. Objective C code snippet below:

    - (void)centralManager:(CBCentralManager *)central didDiscoverPeripheral:(CBPeripheral *)peripheral advertisementData:(NSDictionary *)advertisementData RSSI:(NSNumber *)RSSI
    {
    
        // Respond only to RFduinos with manufacture data self.manufactureData.
        
        NSData *manufactureDataOfRFduino = [advertisementData valueForKey:CBAdvertisementDataManufacturerDataKey];
        
        if ([manufactureDataOfRFduino isEqual:self.manufactureData]) {
            // It's our device, carry on ...
            .
            .
            .

    I will need to learn about manufacture ID versus advertising data and set them appropriately. Is there a process for choosing a manufacture ID or will the Laird module we use (BL651) have its manufacture ID set appropriately?

    Many thanks ...

  • Hi Tim

    The only drawback of using a 128-bit vendor specific UUID over a registered 16-bit UUID is that you have to reserve a much larger part of the advertise packet to include the longer 128-bit UUID. 

    You will use 18 bytes total for advertising the full UUID (16 byte for the UUID and 2 byte for the advertising field header), leaving you only 13 bytes left of the total 31 byte advertising payload. A 16-bit UUID can be advertised in only 4 bytes. 

    A way to alleviate this issue is to put the 128-bit UUID in the scan response packet. Essentially this allows you to split all your advertise data into two 31 byte packets, giving you twice the amount of data available.
    That said I don't know if the SimbleeBLE API allows you to configure the scan response packet, or if you can only use advertise packet?

    Tim said:

    About manufacture ID, our Simblee code sets the advertisement data to 0x00007274696D6572.

    SimbleeBLE.advertisementData = advData;

    I noticed that LightBlue shows this value as the Manufacture Data. Maybe for Simblee. the above statement sets both?

    Again it seems the SimbleeBLE API is not properly following spec conventions and terminology. 

    The term 'advertisement data' implies that you are talking about the entire advertising payload, consisting of multiple fields such as service UUID, TX power level and local name. 

    In their case this refers to the manufacturer specific data field specifically, which is just a subfield within the entire advertisement packet. 

    The manufacturer specific data field is a nice way to add custom data to the advertise packet, since there is no limit on the size or type of data you can include here, but the first two bytes should reflect the company used. Laird is using company ID 0x0077, so you should probably be able to use that, but I would check with them first to be sure ;)

    The full list of company ID's can be found here:
    https://www.bluetooth.com/specifications/assigned-numbers/company-identifiers/

    I doubt the BL651 will enforce any specific company ID in the manufacturer field. While Laird provide their own API for programming the modules I believe they also support flashing any code into the Nordic device, to avoid restricting the capabilities of the modules. 

    Best regards
    Torbjørn

  • Thanks Torbjørn. About manufacture ID, my sense is we should either

    1) Use Laird's ID since we are embedding their BL651 module in our product, or

    2) Become a Bluetooth SIG member and use the ID they assign us.

    Yes, it appears that SimbleeBLE.advertisementData is setting the entire advertising payload. We are leaving Simblee behind, so will implement new code to properly set the advertising data.

    I'm now working on sending/receiving data. Simple question. I think I'm now understanding the BLE UART example to basically implement a relay of sorts to relay data received via UART on certain pin (RX_PIN_NUMBER) to BLE for sending to the connected BLE central, and to relay any data received over BLE from the central to, again, UART on specified pin (TX_PIN_NUMBER).

    For my application, we're simply watching the digital state of a particular GPIO pin and sending binary data to the connected BLE central. The central can also send binary data to the peripheral which often causes the peripheral to send data back to the central. Quite simple.

    Does this mean that I can remove the UART capability altogether? Am I seeing this correctly? If yes, and if reasonable, could you please summarize the changes to code I'd need to look at? I'm speculating the following changes:

    - remove the code in nus_data_handler() in main.c that writes the data received over BLE to UART

    - remove the uart_init() call in the main loop and the corresponding routine in main.c

    - remove the uart_event_handle() routine from main.c

    Am I on the right track? Many thanks.

  • Hi Tim

    I would say 2) is the best option if you can, otherwise you might run into other people also using Laird modules and mistake these devices for your own. 

    Your understanding of the ble_app_uart is correct. It acts as a two way bridge passing BLE NUS data to the physical UART and vice versa.

    I agree that you can just remove the UART functionality if you are using the ble_app_uart example as a basis for your own application. 

    A simple technique to figure out what you need to remove is to comment or delete the #include "app_uart.h" line at the top of the main.c file, then you will get compile errors whenever the UART library is referenced in the code and you just have to remove these parts. 

    Best regards
    Torbjørn

  • Thank you Torbjørn, for confirming things.

    I will remove UART functionality.

    We are assembling some prototype boards of our product and will start developing/testing with them. I understand we can connect via P19 (debug output) on the nRF52 dev kit to do so. It would be helpful to see a summary of how I adjust code originally written to run on the dev kit, so that it will run on an external custom board that contains an nRF52810 (Laird BL651). I presume I would remove all references to custom I/O (e.g. buttons, LEDs) on the dev kit (starting with the "bsp_btn_ble.h" include), perhaps update "board.h", maybe remove "BOARD_PCA10040" from the c_preprocessor_definitions, maybe create a custom replacement of pca10040.h, etc?

    Are there online resources that would guide me in this regard? I can probably figure it out on my own, but some guidance would be helpful.

    Many thanks. -Tim

Related