Implementing Bluetooth® LE Beacons on the KW40Z Wireless Microcontroller

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Implementing Bluetooth® LE Beacons on the KW40Z Wireless Microcontroller

Implementing Bluetooth® LE Beacons on the KW40Z Wireless Microcontroller

Overview

Bluetooth Low Energy offers the ability to broadcast data in format of non-connectable advertising packets while not being in a connection. This GAP Advertisement is widely known as a beacon and is used in today’s IoT applications in different forms. This article will present the current beacon format in our demo application from the KW40Z software package and how to create the most popular beacon formats on the market.

The advertising packet format and payload are declared in the gAppAdvertisingData structure from app_config.c. This structure points to an array of AD elements, advScanStruct:

static const gapAdStructure_t advScanStruct[] = {

  {

    .length = NumberOfElements(adData0) + 1,

    .adType = gAdFlags_c,

    .aData = (void *)adData0

  }, 

  {

    .length = NumberOfElements(adData1) + 1,

    .adType = gAdManufacturerSpecificData_c,

    .aData = (void *)adData1

  }

};

Due to the fact that all beacons use the advertising flags structure and that the advertising PDU is 31 bytes in length (Bluetooth Low Energy v4.1), the maximum payload length is 28 bytes, including length and type for the AD elements.

The AD Flags element is declared as it follows:

static const uint8_t adData0[1] =  { (gapAdTypeFlags_t)(gLeGeneralDiscoverableMode_c | gBrEdrNotSupported_c) };

The demo application uses a hash function to generate a random UUID for the KW40Z default beacon. This is done in BleApp_Init:

void BleApp_Init(void)

{

    sha1Context_t ctx;

   

    /* Initialize sha buffer with values from SIM_UID */

    FLib_MemCopy32Unaligned(&ctx.buffer[0], SIM_UIDL);

    FLib_MemCopy32Unaligned(&ctx.buffer[4], SIM_UIDML);

    FLib_MemCopy32Unaligned(&ctx.buffer[8], SIM_UIDMH);

    FLib_MemCopy32Unaligned(&ctx.buffer[12], 0);

    

    SHA1_Hash(&ctx, ctx.buffer, 16);

   

    /* Updated UUID value from advertising data with the hashed value */

    FLib_MemCpy(&gAppAdvertisingData.aAdStructures[1].aData[3], ctx.hash, 16);

}

When implementing a constant beacon payload, please bear in mind to disable this code section.

KW40Z Default Beacon

The KW40Z software implements a proprietary beacon with the maximum ADV payload and uses the following Manufacturer Specific Advertising Data structure of 26 bytes.

pastedImage_18.png

This is the default implementation of the beacon demo example from the KW40Z Connectivity Software package.

static uint8_t adData1[26] = {

    /* Company Identifier*/     0xFF, 0x01

    /* Beacon Identifier */     0xBC,

    /* UUID */                  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,                              

    /* A */                     0x00, 0x00,

    /* B */                     0x00, 0x00,

    /* C */                     0x00, 0x00,

    /* RSSI at 1m */            0x1E};

iBeacon

iBeacon is a protocol designed by Apple. It uses a 20 byte payload that consists of the following identifying information [1] :

pastedImage_22.png

To advertise an iBeacon packet, the user needs to change the second AD element, adData1, like below:

static uint8_t adData1[25] = {

                               0x4C, 0x00,   

                               0x02, 0x15,

        /* UUID */             0xD9, 0xB9, 0xEC, 0x1F, 0x39, 0x25, 0x43, 0xD0, 0x80, 0xA9, 0x1E, 0x39, 0xD4, 0xCE, 0xA9, 0x5C,

        /* Major Version */    0x00, 0x01

        /* Minor Version */    0x00, 0x0A,

                               0xC5};


AltBeacon

AltBeacon is an open specification designed for proximity beacon advertisements [2]. It also uses a Manufacturer Specific Advertising Data structure:

pastedImage_20.png

To advertise an AltBeacon packet, the user needs to change the second AD element, like below:

static uint8_t adData1[26] = {

    /* MFG ID*/         0xFF, 0x01,

    /* Beacon Code */   0xBE, 0xAC,

    /* Beacon ID */     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04,

    /* Ref RSSI*/       0xC5,

    /* MFG RSVD*/       0x00};

Eddystone

Eddystone™ is an open Bluetooth® Smart beacon format from Google [3]. It offers three data type packets:

  • Eddystone™-UID
  • Eddystone™-URL
  • Eddystone™-TLM

Eddystone™ uses two advertising structures:

  • Complete List of 16-bit Service UUIDs structure, which contains the Eddystone Service UUID (0xFEAA).
  • Service Data structure, which also contains the Eddystone™ Service UUID (0xFEAA).

Thus, advScanStruct will now have 3 elements:

static const gapAdStructure_t advScanStruct[] = {

  {

    .length = NumberOfElements(adData0) + 1,

    .adType = gAdFlags_c,

    .aData = (void *)adData0

  }, 

  {

    .length = NumberOfElements(adData1) + 1,

    .adType = gAdComplete16bitServiceList_c,

    .aData = (void *)adData1

  },

  {

    .length = NumberOfElements(adData2) + 1,

    .adType = gAdServiceData16bit_c,

    .aData = (void *)adData2

  }

};

The complete List of 16-bit Service UUIDs element will look like:

static const uint8_t adData1[2] =  { 0xAA, 0xFE };

Eddystone™-UID

Eddystone™-UID broadcasts a unique 16-bit Beacon ID to identify a particular device in a group. The Service Data block has the following structure:

pastedImage_22.png

To implement this, the user needs to add a third AD element, as follows:

static uint8_t adData2[22] = {

    /* ID */ 0xAA, 0xFE,

    /* Frame Type */    0x00,

    /* Ranging Data */  0xEE,

    /* Namespace */     0x8B, 0x0C, 0xA7, 0x50, 0x09, 0x54, 0x77, 0xCB, 0x3E, 0x77,

    /* Instance */      0x00, 0x00, 0x00, 0x00, 0x00, 0x01,

    /* RFU */           0x00, 0x00};

Eddystone™-URL

Eddystone™-URL broadcasts a compressed URL. The Service Data block has the following structure:

pastedImage_29.png

In this example, we will implement a beacon which will advertise NXP’s webpage, http://www.nxp.com.

To implement this, the user needs to add a third AD element, as follows:

static const uint8_t adData2[9] = {

    /* ID */ 0xAA, 0xFE,

    /* Frame Type */    0x10,

    /* TX Power */      0xEE,

    /* URL scheme */    0x00,

    /* Encode URL */    'n', 'x, 'p', 0x07};

Eddystone™-TLM

Eddystone™-TLM broadcasts telemetry data about the beacon device operation. The Service Data block has the following structure:

pastedImage_30.png

To implement this, the user needs to add a third AD element, as follows:

static uint8_t adData2[16] = {

    /* ID */ 0xAA, 0xFE,

    /* Frame Type */    0x20,

    /* TLM Version */   0x00,

    /* VBATT */        0x00, 0x00,

    /* TEMP */         0x00, 0x00,

    /* ADV_CNT */      0x00, 0x00, 0x00, 0x00,

    /* SEC_CNT */      0x00, 0x00, 0x00, 0x00};

Labels (2)
Comments

Thanks alexandruandreescu, Great tutorial.

in case of iBeacon, We need to have different major/minor for different KW40 module. In this example, we have to compile every time for different beacons/KW40  by changing the adData1 parameters.

Is there anyway to read the iBeacon parameters (uint8_t adData1[25]) from a config file?   In that case, we can use the same binary with different config files for different KW40.

Thanks.

The eddystone beacon is not being detected by Chrome (v51) or the Physical Web Android app. I commented out BleApp_Init(), and also tried using a https url in addition to the nxp example provided.

static const uint8_t adData2[19] = {  

    /* ID */ 0xAA, 0xFE, 

    /* Frame Type */    0x10, 

    /* TX Power */      0xEE, 

    /* URL scheme */    0x03, /* https:// */ 

    /* Encode URL */    'c','o','m','m','u','n','i','t','y','.','n','x','p', 0x07}; 

Can confirm that the default "beacon" example in the KW40Z_1.0.1 ConnSw is detected by the Kinetis BLE toolbox.

This was resolved on Android side.

Dear sir,

I tried to implement ibeacon feature on KW41z.

I used the beacon example in MKW41Z_ConnSw_1.0.2.

pastedImage_1.png

The default packet is NXP beacon format.

I tried to change it to ibeacon packet format like you mentioned below.

pastedImage_5.png

I used the beacon app "Locate" from App store. But I can't get my KW41 device.

Could you help me how I could implement the ibeacon feature on KW41 successfully.

pastedImage_4.pngpastedImage_2.png

Thanks.

BR,

Sean Wu

Weikeng Inc.

Dear Sir,

In the actual application can not only run a mode (ibeacon / EddyStone ...).

How to modify the software can achieve two modes (iBeacon and EddyStone) can run at the same time?

Thanks,

Daniel Tseng

@Alexandru Andreescu Thanks for the article; it was really helpful.
I am a student and was trying to convert KW41 to Alt Beacon. It was successful the only thing I would like to mention is "When implementing a constant beacon payload, please bear in mind to disable this code section." this line is really important.

No ratings
Version history
Last update:
‎09-10-2020 03:37 AM
Updated by: