Bluetooth 5 introduces a number of useful new features. This article discusses those features that the Silicon Labs Bluetooth SDK version 2.3.0 supports. These include multiple advertising sets and support for the new 2M PHY.
Multiple Advertising Sets
It is now possible to have multiple advertising sets without having to stop and restart advertising. All of the parameters including the advertising interval, advertising data, discoverability, connectability and number of advertisements to send before stopping can be configured independently for each advertising set.
The APIs used to control advertising are similar to those used in Bluetooth 4.x, with a few additions.
To set the advertising data, we have the API gecko_cmd_le_gap_bt5_set_adv_data() which takes 3 parameters
handle - the number of the advertising set to use
scan_rsp – a flag to indicate whether the whether the data is intended for advertising or scan responses
adv_data – the data to send
To control the advertising parameters, we have gecko_cmd_le_gap_bt5_set_adv_parameters() which takes 5 parameters
handle - the number of the advertising set to use
interval_min – the minimum connection interval in increments of 0.625 ms
interval_max – the maximum interval to use in increments of 0.625 ms
channel_map – flags to indicate which channel(s) to advertise on
report_scan – a flag to indicate whether to report scan requests as events
To control the mode of the advertising set we have gecko_cmd_le_gap_bt5_set_mode() which takes 5 parameters
handle - the number of the advertising set to use
discover - the discoverability mode (see API guide for options)
connect - the connectability mode (see API guide for options)
max_events – the maximum number of times to send this advertisement before stopping
address_type – the type of address to use (public, static, resolvable or non-resolvable)
Two new events are also introduced with Bluetooth 5.
gecko_evt_le_connection_bt5_opened_id
This event is passed only when a connection is established with a BT5 command and comes with the following parameters
address - the remote device address
address_type – the remote device address type (see previous section)
master - device role : slave or master
connection – the connection handle
bonding - the bonding handle
advertiser – the advertisement set that this connection was opened to
gecko_evt_le_gap_scan_request_id
This event is triggered when scan requests are enabled in a call to gecko_cmd_le_gap_bt5_set_adv_parameters(). The following parameters are sent with this event
address - the address of the scanning device
address_type – indicates whether the address is public or random
bonding - the bonding handle
Please see the API reference guide for more information
Support for new PHYs
Bluetooth 5 also adds support for longer range and a higher data rate.
At this time, our EFR32Bg12 SoCs and modules support the 2 MBPS PHY. The longer range will be supported in the future. For selecting the PHY to use, we have the following API function
gecko_cmd_le_connection_set_phy()
connection - connection handle to use
phy - 1 : 1 MBPS PHY, 2 : 2 MBPS PHY
This API should be called on a per connection basis, meaning that the connection should be established first. Calling this API results in the following event being triggered by the stack
gecko_evt_le_connection_phy_status_id
This event comes with the following parameters
connection - handle of the connection associated with this event
phy - integer to indicate the current active PHY
Current Consumption
One of the advantages of using the 2 M phy is lower current consumption. The example uses a connection interval of 875 – 950 ms . when using the 1 M phy, the average is current is 13.5 uA , with the 2M phy the average current is 10.5 uA. It is necessary to turn off the LEDs to achieve these numbers.
Example
At the time of writing, most mobile devices do not support BT5 so examples of both client and server are provided to make it easier to establish a BT5 connection.
The example accompanying this article demonstrates all of these features. When the server application’s stack has been initialized, it starts advertising with a connectable BT5 advertising set as well as a non-connectable iBeacon. At this time, the application also prints a message on the serial port indicating the functions of the LEDs. Upon establishing a connection, the server requests a 2 MPHY connection from the client. An event is triggered by the stack which indicates the PHY which is actually used. LED0 is turned on when any connection is established and LED1 is turned on when a 2 MPHY connection is used.
In parallel, this application starts an iBeacon which operates independently. The iBeacon advertisements are sent out at 100 ms intervals a total of 2000 times before stopping. An event is triggered when the 2000 advertisements have been sent out which facilitates restarting the advertisements.
The client application starts up an immediately begins passive scanning for devices that advertise a service with a specific UUID. Upon finding a connectable device with this UUID, the client connects to it.
Once the connection is made, the following message is displayed
BT connection opened. Requesting 2 MPHY
and LED0 is turned on to indicate an active connection
Once the server has responded that it can support the 2M PHY, the client displays the following message
now using the 2MPHY
and LED1 is turned on to indicate that the 2M PHY is in use.
On the server side, the serial console will display the following
BT connection opened. Requesting 2 MPHY
now using the 2MPHY
While this connection is active, it is possible to see the iBeacon being broadcast with our Bluegecko mobile app.
If the connection is disconnected, all LEDs will shut off.
Conclusion
The Bluetooth 5 features supported at this time are the multiple advertising sets and the higher data rate. More Bluetooth 5 features are coming soon.
This article introduces a demo project about Apple Notification Center Service (ANCS). The demo project is able to receive ANCS notifications like phone calls, calendar events, etc.
What is ANCS?
The information below can be found on the Apple specification linked below, but for the convenience we summarize it here.
The purpose of the Apple Notification Center Service (ANCS) is to give Bluetooth accessories (that connect to iOS devices through a Bluetooth Low Energy link) a simple and convenient way to access many kinds of notifications that are generated on iOS devices.
Terminology
The Apple Notification Center Service is referred to as the ANCS.
The publisher of the ANCS service (the iOS device) is referred to as Notification Provider (NP).
Any client of the ANCS service (an accessory) is referred to as a Notification Consumer (NC).
A notification displayed on an iOS device in the iOS Notification Center is referred to as iOS notification.
A notification sent by a GATT characteristic as an asynchronous message is referred to as a GATT notification.
The Apple Notifications Center Service
In its basic form, the ANCS exposes three characteristics:
Control Point: UUID: 69D1D8F3-45E1-49A8-9821-9BBDFDAAD9D9 (writable with response)
Data Source: UUID: 22EAC6E9-24D6-4BB5-BE44-B36ACE7C7BFB (notifiable)
All these characteristics require authorization for access.
Support for the Notification Source characteristic is mandatory, whereas support for the Control Point characteristic and Data Source characteristic is optional.
Note: In this demo project we use the Notification Source characteristic only .
A GATT notification delivered through the Notification Source characteristic contains the following information:
EventID: This field informs the accessory whether the given iOS notification was added, modified, or removed. The enumerated values for this field are defined in EventID Values.
EventFlags: A bitmask whose set bits inform an NC of specificities with the iOS notification. For example, if an iOS notification is considered “important”, the NC may want to display a more aggressive user interface (UI) to make sure the user is properly alerted. The enumerated bits for this field are defined in EventFlags.
CategoryID: A numerical value providing a category in which the iOS notification can be classified. The NP will make a best effort to provide an accurate category for each iOS notification. The enumerated values for this field are defined in CategoryID Values.
CategoryCount: The current number of active iOS notifications in the given category. For example, if two unread emails are sitting in a user’s email inbox, and a new email is pushed to the user’s iOS device, the value of CategoryCount is 3.
NotificationUID: A 32-bit numerical value that is the unique identifier (UID) for the iOS notification. This value can be used as a handle in commands sent to the Control Point characteristic to interact with the iOS notification.
For more information about ANCS, please check specification linked below.
Demo Implementation
The demo project is able to receive ANCS notifications like phone calls, calendar events, etc. and prints them out to the VCOM. The software flow goes as follows:
At first the software initialize the peripherals, the Bluetooth stack and logging to the virtual COM port.
After the gecko_evt_system_boot_id event arrived it sets up the security manager in order to able to bond with iOS device. Then it starts advertising.
Once gecko_evt_gatt_mtu_exchanged_id event received the device connected and the connection parameters negotiated. Then the device starts to search for the ANCS service in the remote GATT with the gecko_cmd_gatt_discover_primary_services_by_uuidAPI.
If it finds the ANCS service, it will start searching for the notification source characteristic in the remote GATT with the gecko_cmd_gatt_discover_characteristics_by_uuid API.
If the notification source characteristic is found in the remote GATT, the device tries to subscribe to characteristic notification with the gecko_cmd_gatt_set_characteristic_notification API. If the iOS device and the BGM module are not bonded, it is not possible. First the pairing and bonding process have to be completed. Once the bonding is completed, we have to enable the characteristic notification again. This time it will work.
Receiving a gecko_evt_gatt_characteristic_value_id event with the att_opcode == gatt_handle_value_notification means the we got a GATT notification from the remote device. In this case, we determine the notification type based on the notification UID and print it out with the ancCharValueReceivedCallback function.
The activity diagram below shows the described flow.
Running the Demo
Get an iOS device and switch on the Bluetooth in it. Enable application notifications.
Create a new SoC-Empty project for your device (tested with EFR32BG13) in Simplicity Studio.
Copy the attached files into the project:
app.c
anc.c and anc.h
anc-callback.c and anc-callback.h
connection.c and connection.h
Change the "Device Name" characteristic value to "ANCS Example" to better recognize the device in Bluetooth browsers.
Change DEBUG_LEVEL to 1 in app.h.
Build and flash the project to your device.
Start a terminal like TeraTerm and open the virtual COM port of the J-Link CDC device.
Connect to the BG13 "ANCS Example" with a Bluetooth browser app like the Blue Gecko and accept the pairing request.
Now you should get ANCS notifications like below when you get email, for example.
Q: Why can't I see my BLE devices on iOS Bluetooth Settings page
A: According to Apple support it is not possible to see BLE devices listed on the Bluetooth Settings page. Only Bluetooth 2.1/3.0 devices are listed such as keyboards and headsets (source). For BLE devices you must use the device's own app or any other 3rd party app which uses CoreBluetooth.
However, it seems that iOS does list BLE devices when they advertise some of the adopted services such as the Heart Rate service. By advertising this service you can get your device visible in the Bluetooth Settings page. To test this by following these simple steps:
- Create an soc-empty project
- Add the Heart Rate service in the Visual GATT Editor
- Tick "Advertise" and click "Generate"
- Build and flash the project
(Disclaimer: We could not find any information source to verify that iOS does indeed list BLE devices when certain adopted services are advertised)
The attached example is an adaptation of the standard 'SOC - Thermometer' example which instead of accessing the Si7021 Temperature and Relative Humidity sensor through I2C uses the EFR32's own internal temperature sensor. This sensor is measured during production test and the temperature readout from the ADC at production temperature as well as the Celsius value are given in the device information page. Using these and the millivolts per degrees slope found in the sensor datasheet the current temperature can be calculated according to formula:
(For more information, see ADC section of the reference manual of your chosen hardware, e.g. EFR32xG13)
Setting up the project
Start by creating an SoC - Empty sample app for your chosen hardware.
In the project menu select new | Silicon Labs appBuilder project.
Select Bluetooth SDK and click next
Select the latest Bluetooth SDK and click next
Select SOC – Empty and click next
Enter a name for the project and click next
Replace existing app.c with the app.c attached to this article
Copy em_adc.c and em_adc.h from the SDK to the project folder if they aren't already in the platform->emlib->inc/src folders.
Import the attached gatt.xml file in the GATT Configurator sidebar (.isc file, "Import GATT from .bgproj file"). This will add the Health Thermometer service and Temperature Measurement characteristic and change Device Name to "IntTemp".
Press Save and Generate
Build and flash
Using the Blue Gecko app you can now read the temperature sampled from the internal temperature sensor.
Implementation
There are a couple of changes to the basic SoC-Thermometer example:
init_adc function to initialize ADC with correct voltage reference and prescaler etc. This is called after boot event.
read_adc function to get single sample readout from ADC. This has a bit of a busy-wait-loop for simplicity.
convert_to_millicelsius function takes the sample and uses the calibration values in the above formula to get the result as degrees Celsius. Returned value is given as millicelsius.
measure_temperature function is nearly identical to the one in the Thermometer example except for this line that uses the above functions:
Bluetooth ensures reliable data transfer when devices are connected. A connection is required for secure data transfer. This article describes the various states that a Bluetooth device can be in and how to move between these states.
Bluetooth States
Upon starting the Bluetooth stack, the device will be in an idle state, that is to say it will be non-discoverable and non-connectable. Through a call to either of the API functions le_gap_set_mode() or le_gap_bt5_set_mode(), the device can be made discoverable and non-connectable or discoverable and connectable. It is also possible to return the device to the idle, non-discoverable and non-connectable state.
Non-connectable Beacons
A device which is discoverable, but non-connectable is known as a beacon. The advertising data can be seen by any device within range but it is not possible to establish a connection. This means that the advertising device’s data cannot be written. Examples of beacons are the iBeacon and Eddystone standards. If a remote master attempts to connect to a non-connectable slave, the slave’s stack responds to the master with a connection refused error. No interaction is required by the user application.
Connectable Advertisers
A device which is discoverable and connectable advertises and accepts connections from any device within range. When a connection has been established, the stack sends the event le_connection_opened or le_connection_bt5_opened to the application. This event contains the address of the remote device, the type of address, a connection handle, the role of the device in the connection and a bond handle to indicate whether the device is bonded or not. In the case of a Bluetooth 5 connection, the event also includes a handle to indicate which advertising set the connection is associated with. If multiple connections are required, advertising can be restarted from this event.
Closing Connections
If a connection is closed, the event le_connection_closed will be sent to the application. This event includes the connection handle and the reason for disconnection. The reasons for disconnections are documented in the Bluetooth errors section of the API guide.
Connections – Secure and Unsecure
When a connection event is received(evt_le_connection_opened or evt_le_connection_bt5_opened), the application can determine whether or not there is a bond with the remote device by examining the bond_handle parameter. A value of 0xFF indicates no bond, any other value indicates a valid bond. If the local and remote devices are not bonded, the communication between them will be unencrypted and visible to any Bluetooth device within range. It is strongly recommended to secure any sensitive data.
After the connection event, there will be at least one connection parameters event (gecko_evt_le_connection_parameters_id). This event is sent when a connection is opened and any time the connection parameters are updated. The connection parameters event includes information about the connection parameters (connection interval, latency, timeout) as well as the security mode and maximum PDU size. The security mode is one of the following
No security
No authentication, but encrypted
Authenticated and encrypted
A secure connection can be requested either by the stack or the user application. The stack will request a secure connection if the remote device attempts to access a protected characteristic. The user application can request a secure connection by making a call to cmd_sm_increase_security(). In either case, an event will be sent by the stack to the user application to indicate whether the bonding/pairing was successful (evt_sm_bonded) or unsuccessful (evt_bonding_failed).
Bonding vs Pairing
The security manager contains events and commands for controlling the security features included in the Bluetooth stack. One of these features is the ability to form new bonds (bondable mode). As shown in the diagram below, when a connection is secured it will either be bonded and assigned a long term key (LTK) which can be used in subsequent connections or paired and assigned a short term key (STK) which will discarded when the connection is terminated. Upon successful bonding/pairing the stack sends the event evt_sm_bonded to the application with a bond_handle as a parameter. As with the bond_handle passed to the evt_le_connection_opened any value other than 0xFF indicates that the devices are bonded while a value 0xFF in this case means that the devices are paired for the current connection.
Maximum Transmission Unit (MTU)
In addition to the connection opened event and the connection parameters event, there will always be a GATT MTU exchanged event for each connection. This event tells you the size of the maximum transmission unit (MTU). This is the maximum size of any packet that can be sent between the client and server. The only special handling that may be required for this event is to use the MTU to determine whether an entire characteristic can be sent in a single read/write or if multiple writes are required. A single read/write can be MTU – 3 bytes in length.
Bluetooth 5 Connections
Whether a connection is secured or not, Bluetooth 5 allows the choice of 1 Mbps or 2 Mbps PHY on a per connection basis. The PHY can be selected with a call to le_connection_set_phy(). A call to this API results in the stack sending the event evt_le_connection_phy_status to indicate which PHY is actually in use for the connection. The diagram below shows that the flow of the connected state is similar to that of Bluetooth 4.x with the addition of the possibility of selecting the 2M Phy.
Multiple Connections and Dual Mode Topology
It is possible to allow up to 8 simultaneous connections. The max_connections parameter in the Bluetooth configuration struct can be used to limit the number of connections to less than 8 if desired. In order to allow multiple connections it is necessary to restart advertising once a connection is made. This can be done from the connection opened event.
One of the additions made in Bluetooth 4.2 is the so-called dual mode topology which allows a device to be a master and a slave simultaneously. Previously it was necessary to disconnect in order to switch roles between master and client.
Conclusion
Connections are Bluetooth’s way of ensuring reliable and, optionally, secure data transfer. Connections also make it possible for devices to negotiate the PHY that they use to communicate.
This article demonstrates how you can use EM3 and EM4S to enhance energy savings on periodic beaconing applications (non-connectable advertising packets).
The example applications are for the BGM111 module and they are based on SDK 2.3.1 with GCC toolchain.
All the measurements taken for the study detailed in this article were done at a 3V input and +3dBm transmit power. The screenshots shown here are also inside the attached measurements.zip file, including the ones taken for the experimental verification.
Standard Stack Usage - EM2
In the standard stack usage the device will be in EM2 in between advertisement packets as the LFXO is required for timekeeping. The typical value for sleep current in EM2 is 2.5uA as shown in the below figure.
Advertising a non-connectable beacon takes 2.23ms at an average current of 10.14mA as shown below.
These values can be verified with any of the SDK examples, the simplest being the ibeacon example. To get easier readings of the sleep current it is recommended to increase the advertisement interval.
Clocking RTCC from ULFRCO – EM3
In EM3 the LFXO/LFRCO is not running so we need to use some other clock source for the RTCC in which the stack timing is based on. The ULFRCO can be used and it is an extremely low power oscillator which is always running and its frequency can vary from 0.95kHz to 1.07kHz, but for this particular usage the higher inaccuracy is not problematic. This will change the stack timebase from 32768Hz to the ULFRCO frequency of ~1kHz and it will affect the soft-timers where the time parameter will now be in 1kHz ticks.
Using the ULFRCO to clock the RTCC allows reducing the sleep current from 2.5uA in EM2 to just below 2.1uA in EM3 as shown in the figure below.
Clocking the RTCC from a source other than the LFXO will require the advertisements to be timed and sent individually at the application level. This is done by setting the advertisement timeout to 1 occurrence with the command gecko_cmd_le_gap_set_adv_timeout(1) and timing the advertisements with a soft-timer.
The need for timing the beacons at the application level leads to a small overhead in the overall advertisement time as shown below. The advertisement time rises to 2.83ms from the initial 2.23ms at an average current of 9.18mA.
This beaconing scheme is demonstrated in the EM3_beaconing project attached to this article. The following code snippet shows how the advertisement is being managed by the application.
/* Handle events */
switch (BGLIB_MSG_ID(evt->header)) {
/* This boot event is generated when the system boots up after reset.
* Here the system is set to start advertising immediately after boot procedure. */
case gecko_evt_system_boot_id:
/* Change TX power to +3dBm */
gecko_cmd_system_set_tx_power(30);
/* Send only one advertisement packet */
gecko_cmd_le_gap_set_adv_timeout(1);
/* Send one advertisement in non-connectable mode */
gecko_cmd_le_gap_set_mode(le_gap_general_discoverable, le_gap_non_connectable);
/* Start timer */
gecko_cmd_hardware_set_soft_timer(ADVERTISE_TIMEOUT, ADVERTISE_TIMEOUT_HANDLE, 0);
break;
case gecko_evt_hardware_soft_timer_id:
/* Send one advertisement in non-connectable mode */
gecko_cmd_le_gap_set_mode(le_gap_general_discoverable, le_gap_non_connectable);
break;
default:
break;
}
Clocking CRYOTIMER from ULFRCO – EM4S (Shutdown)
Going deeper into the energy modes brings more substantial energy savings in sleep mode which can be beneficial above certain sleep periods. In EM4S there is very little functionality, RAM and register retention is lost and wake up requires a system reset to return back to EM0.
One of the peripherals supported in EM4S is the CRYOTIMER which can be clocked from the ULFRCO to generate periodic wake-ups. These wake-ups will effectively reset the device but as we are again not activating the LFXO, which takes the longest to stabilize, it is possible to have very a short wake-up time.
In EM4S the current drops by a factor of 40 compared to EM2 to 60nA as shown below.
The wake-up time increases as the stack needs to be re-initialize before sending out the beacon. Then the same approach is used as in EM3, setting advertisement timeout to 1 and putting the device back into EM4S when the advertisement has been confirmed through the event gecko_evt_le_gap_adv_timeout.
This beaconing scheme is demonstrated in the EM4_beaconing project attached to this article. The following code snippet shows how the advertisement is being managed by the application.
/* Handle events */
switch (BGLIB_MSG_ID(evt->header)) {
/* This boot event is generated when the system boots up after reset.
* Here the system is set to start advertising immediately after boot procedure. */
case gecko_evt_system_boot_id:
/* Change TX power to +3dBm */
gecko_cmd_system_set_tx_power(30);
/* Send only one advertisement packet */
gecko_cmd_le_gap_set_adv_timeout(1);
/* Send one advertisement in non-connectable mode */
gecko_cmd_le_gap_set_mode(le_gap_general_discoverable, le_gap_non_connectable);
break;
case gecko_evt_le_gap_adv_timeout_id:
/* Start CRYOTIMER and go to EM4S */
CRYOTIMER_Enable(true);
enterIntoEM4S();
break;
default:
break;
}
Summary and Conclusions
Neither of these alternative beaconing methods using EM3 and EM4S bring benefits with short beaconing intervals but the tipping point can be approximately calculated. The following table summarizes the data from the previous sections and adds the energy for both sleep and advertisement periods taking into account a 3V power supply (VDD) as mentioned in the introduction.
The “Sleep energy (per second)” is calculated as "Sleep current" x VDD
The "Advertisement energy" is calculated as "Advertisement current" x "Advertisement duration" x VDD
Energy Mode
Sleep current
Sleep energy (per second)
Advertisement current
Advertisement duration
Advertisement energy
EM2
2.53uA
7.59uJ
10.14mA
2.23ms
68uJ
EM3
2.06uA
6.18uJ
9.17mA
2.83ms
78uJ
EM4S
60nA
180nJ
4.74mA
19.25ms
274uJ
The tipping point is where the energy savings in sleep mode equal the energy overhead taken by the longer advertisement periods.
Calculating the Tipping Points
The tipping point (in seconds) can then be calculated as savingsInEMX x seconds = advertisingOverhead.
EM2 vs EM3
For EM3 vs EM2 the energy saving in sleep mode is 7.59 – 6.18 = 1.41uJ and the advertising overhead is 78 – 68 = 10uJ. Using these figures we can calculate that the tipping point comes at 7.1 seconds.
For any beaconing period above 10.24s the stack cannot be used to automatically send the advertisements because 10.24s is the maximum advertisement interval allowed by the API command le_gap_set_adv_parameters. Therefore comparing EM2 vs EM4S is not needed because using EM3 already brings benefits even before reaching the maximum advertisement interval allowed by the stack.
EM3 vs EM4S
For EM3 vs EM4S the energy saving in sleep mode is 6.18 – 0.180 = 6uJ and the advertising overhead is 274 – 78 = 196uJ. With these figures we can calculate a tipping point of 32.7s.
To verify that the tipping point calculation is correct we measured the average current for different intervals using the different energy modes.
Verifying EM2 vs EM3 Tipping Point
The EM2 vs EM3 tipping point was calculated at 7.1 seconds. To verify this result we took the average current (sleep period + 1 beacon) at 7 seconds and at 8 seconds with both EM2 and EM3 and compared the results.
Average current at 7 seconds advertisement interval
EM2: 5.75uA
EM3: 5.81uA
Average current at 8 seconds advertisement interval
EM2: 5.34uA
EM3: 5.32uA
The experimental results are aligned with the theoretical calculations and at 8 seconds we start seeing that using EM3 provides a lower average current consumption compared to using EM2.
Verifying EM3 vs EM4S Tipping Point and Beyond
The EM3 vs EM4S tipping point was calculated at 32.7 seconds. In EM4S the wake-up period is programmed into the CRYOTIMER in “number of clock cycles” which comes from the ULFRCO (at about 1kHz frequency as mentioned earlier). This number is programmed as 2x where x ranges from 0 (wake after every clock cycle or every ~1ms) to 32 (wake up after 232 clock cycles, or every ~49.7 days).
For the purpose of verifying the EM3 vs EM4S tipping point we took measurements of the average sleep current at 16 seconds, 32 as well as 64 seconds beaconing intervals to see how the average evolves into longer periods.
Average current at 16 seconds advertisement interval
EM3: 3.70uA
EM4S: 5.55uA
Average current at 32 seconds advertisement interval
EM3: 2.91uA
EM4S: 2.82uA
Average current at 64 seconds advertisement interval
EM3: 2.45uA
EM4S: 1.44uA
The experimental results are aligned with the theoretical calculations and at 32 seconds we start seeing that using EM4S provides a lower average current consumption compared to using EM3. Looking into even longer beaconing intervals the average currents will tend to the sleep current of each mode so the benefits of using EM4S are even more pronounced.
How can I save a value of type float in Persistent Storage?
(the answer below applies to floats as well as other data types and even for more complex data structures)
Answer
PS store allows you to save byte arrays in flash. Any variables (integers, floats, structs ..) are stored in memory as byte arrays. In case of float, four bytes are required to store the value.
The following code snippets implements a pair of helper functions that allow you to store basically any data in a PS key.
uint16_t ps_save_object(uint16_t key, void *pValue, uint8_t size)
{
struct gecko_msg_flash_ps_save_rsp_t *pResp;
pResp = gecko_cmd_flash_ps_save(key, size, pValue);
return(pResp->result);
}
uint16_t ps_load_object(uint16_t key, void *pValue, uint8_t size)
{
struct gecko_msg_flash_ps_load_rsp_t *pResp;
pResp = gecko_cmd_flash_ps_load(key);
if(pResp->result == 0)
{
memcpy(pValue, pResp->value.data, pResp->value.len);
// sanity check: length of data stored in PS key must match the expected value
if(size != pResp->value.len)
{
return(bg_err_unspecified);
}
}
return(pResp->result);
}
First parameter is the PS key (from range 0x4000...0x407F). The second parameter is a pointer to the data object. The pointer is of type void so that the same code can be applied to any type of variables easily. Last parameter defines the size of the object. You can use the sizeof() operator when calling these which makes it really easy to use this solution your code.
Here's an example how to store and load a float variable in a PS key:
float F;
// store the value:
ps_save_object(0x4000, &F, sizeof(F));
// load the value of F from PS:
if(ps_load_object(0x4000, &F, sizeof(F)) == 0)
{
// value was loaded OK
}
else
{
// value not OK (either not stored in PS or length of the data does not match the expected value)
}
The same functions can be used for storing and loading other fixed side objects, too. Let's assume you have defined a struct that bundles the Bluetooth address and name of a remote device into one variable and you want to save the whole struct in a PS key:
typedef struct
{
bd_addr addr;
char name[16];
}remote_device;
...
remote_device last_dev;
// save the whole struct in PS, using key 0x4001:
ps_save_object(0x4001, &last_dev, sizeof(last_dev));
Notes:
* maximum size of one PS key is 56 bytes (SDK v2.3.1)
* total capacity of PS storage is 2kB and part of this space is required to store bonding information
Bluetooth Knowledge Base
KBA_BT_0105: Bluetooth 5 Features
Bluetooth 5 Features
Introduction
Bluetooth 5 introduces a number of useful new features. This article discusses those features that the Silicon Labs Bluetooth SDK version 2.3.0 supports. These include multiple advertising sets and support for the new 2M PHY.
Multiple Advertising Sets
It is now possible to have multiple advertising sets without having to stop and restart advertising. All of the parameters including the advertising interval, advertising data, discoverability, connectability and number of advertisements to send before stopping can be configured independently for each advertising set.
The APIs used to control advertising are similar to those used in Bluetooth 4.x, with a few additions.
To set the advertising data, we have the API gecko_cmd_le_gap_bt5_set_adv_data() which takes 3 parameters
To control the advertising parameters, we have gecko_cmd_le_gap_bt5_set_adv_parameters() which takes 5 parameters
To control the mode of the advertising set we have gecko_cmd_le_gap_bt5_set_mode() which takes 5 parameters
Two new events are also introduced with Bluetooth 5.
This event is passed only when a connection is established with a BT5 command and comes with the following parameters
This event is triggered when scan requests are enabled in a call to gecko_cmd_le_gap_bt5_set_adv_parameters(). The following parameters are sent with this event
Please see the API reference guide for more information
Support for new PHYs
Bluetooth 5 also adds support for longer range and a higher data rate.
At this time, our EFR32Bg12 SoCs and modules support the 2 MBPS PHY. The longer range will be supported in the future. For selecting the PHY to use, we have the following API function
gecko_cmd_le_connection_set_phy()
This API should be called on a per connection basis, meaning that the connection should be established first. Calling this API results in the following event being triggered by the stack
gecko_evt_le_connection_phy_status_id
This event comes with the following parameters
Current Consumption
One of the advantages of using the 2 M phy is lower current consumption. The example uses a connection interval of 875 – 950 ms . when using the 1 M phy, the average is current is 13.5 uA , with the 2M phy the average current is 10.5 uA. It is necessary to turn off the LEDs to achieve these numbers.
Example
At the time of writing, most mobile devices do not support BT5 so examples of both client and server are provided to make it easier to establish a BT5 connection.
The example accompanying this article demonstrates all of these features. When the server application’s stack has been initialized, it starts advertising with a connectable BT5 advertising set as well as a non-connectable iBeacon. At this time, the application also prints a message on the serial port indicating the functions of the LEDs. Upon establishing a connection, the server requests a 2 MPHY connection from the client. An event is triggered by the stack which indicates the PHY which is actually used. LED0 is turned on when any connection is established and LED1 is turned on when a 2 MPHY connection is used.
In parallel, this application starts an iBeacon which operates independently. The iBeacon advertisements are sent out at 100 ms intervals a total of 2000 times before stopping. An event is triggered when the 2000 advertisements have been sent out which facilitates restarting the advertisements.
The client application starts up an immediately begins passive scanning for devices that advertise a service with a specific UUID. Upon finding a connectable device with this UUID, the client connects to it.
Once the connection is made, the following message is displayed
BT connection opened. Requesting 2 MPHY
and LED0 is turned on to indicate an active connection
Once the server has responded that it can support the 2M PHY, the client displays the following message
now using the 2MPHY
and LED1 is turned on to indicate that the 2M PHY is in use.
On the server side, the serial console will display the following
BT connection opened. Requesting 2 MPHY
now using the 2MPHY
While this connection is active, it is possible to see the iBeacon being broadcast with our Bluegecko mobile app.
If the connection is disconnected, all LEDs will shut off.
Conclusion
The Bluetooth 5 features supported at this time are the multiple advertising sets and the higher data rate. More Bluetooth 5 features are coming soon.
KBA_BT_0914: ANCS
Introduction
This article introduces a demo project about Apple Notification Center Service (ANCS). The demo project is able to receive ANCS notifications like phone calls, calendar events, etc.
What is ANCS?
The information below can be found on the Apple specification linked below, but for the convenience we summarize it here.
The purpose of the Apple Notification Center Service (ANCS) is to give Bluetooth accessories (that connect to iOS devices through a Bluetooth Low Energy link) a simple and convenient way to access many kinds of notifications that are generated on iOS devices.
Terminology
The Apple Notification Center Service is referred to as the ANCS.
The publisher of the ANCS service (the iOS device) is referred to as Notification Provider (NP).
Any client of the ANCS service (an accessory) is referred to as a Notification Consumer (NC).
A notification displayed on an iOS device in the iOS Notification Center is referred to as iOS notification.
A notification sent by a GATT characteristic as an asynchronous message is referred to as a GATT notification.
The Apple Notifications Center Service
In its basic form, the ANCS exposes three characteristics:
Notification Source: UUID: 9FBF120D-6301-42D9-8C58-25E699A21DBD (notifiable)
Control Point: UUID: 69D1D8F3-45E1-49A8-9821-9BBDFDAAD9D9 (writable with response)
Data Source: UUID: 22EAC6E9-24D6-4BB5-BE44-B36ACE7C7BFB (notifiable)
All these characteristics require authorization for access.
Support for the Notification Source characteristic is mandatory, whereas support for the Control Point characteristic and Data Source characteristic is optional.
Note: In this demo project we use the Notification Source characteristic only .
A GATT notification delivered through the Notification Source characteristic contains the following information:
EventID: This field informs the accessory whether the given iOS notification was added, modified, or removed. The enumerated values for this field are defined in EventID Values.
EventFlags: A bitmask whose set bits inform an NC of specificities with the iOS notification. For example, if an iOS notification is considered “important”, the NC may want to display a more aggressive user interface (UI) to make sure the user is properly alerted. The enumerated bits for this field are defined in EventFlags.
CategoryID: A numerical value providing a category in which the iOS notification can be classified. The NP will make a best effort to provide an accurate category for each iOS notification. The enumerated values for this field are defined in CategoryID Values.
CategoryCount: The current number of active iOS notifications in the given category. For example, if two unread emails are sitting in a user’s email inbox, and a new email is pushed to the user’s iOS device, the value of CategoryCount is 3.
NotificationUID: A 32-bit numerical value that is the unique identifier (UID) for the iOS notification. This value can be used as a handle in commands sent to the Control Point characteristic to interact with the iOS notification.
For more information about ANCS, please check specification linked below.
Demo Implementation
The demo project is able to receive ANCS notifications like phone calls, calendar events, etc. and prints them out to the VCOM. The software flow goes as follows:
At first the software initialize the peripherals, the Bluetooth stack and logging to the virtual COM port.
After the gecko_evt_system_boot_id event arrived it sets up the security manager in order to able to bond with iOS device. Then it starts advertising.
Once gecko_evt_gatt_mtu_exchanged_id event received the device connected and the connection parameters negotiated. Then the device starts to search for the ANCS service in the remote GATT with the gecko_cmd_gatt_discover_primary_services_by_uuidAPI.
If it finds the ANCS service, it will start searching for the notification source characteristic in the remote GATT with the gecko_cmd_gatt_discover_characteristics_by_uuid API.
If the notification source characteristic is found in the remote GATT, the device tries to subscribe to characteristic notification with the gecko_cmd_gatt_set_characteristic_notification API. If the iOS device and the BGM module are not bonded, it is not possible. First the pairing and bonding process have to be completed. Once the bonding is completed, we have to enable the characteristic notification again. This time it will work.
Receiving a gecko_evt_gatt_characteristic_value_id event with the att_opcode == gatt_handle_value_notification means the we got a GATT notification from the remote device. In this case, we determine the notification type based on the notification UID and print it out with the ancCharValueReceivedCallback function.
The activity diagram below shows the described flow.
Running the Demo
Get an iOS device and switch on the Bluetooth in it. Enable application notifications.
Create a new SoC-Empty project for your device (tested with EFR32BG13) in Simplicity Studio.
Copy the attached files into the project:
Change the "Device Name" characteristic value to "ANCS Example" to better recognize the device in Bluetooth browsers.
Change DEBUG_LEVEL to 1 in app.h.
Build and flash the project to your device.
Start a terminal like TeraTerm and open the virtual COM port of the J-Link CDC device.
Connect to the BG13 "ANCS Example" with a Bluetooth browser app like the Blue Gecko and accept the pairing request.
Now you should get ANCS notifications like below when you get email, for example.
Further Reading
Apple Notification Center Service (ANCS) Specification
Bluetooth Software API Reference
Blue Gecko iOS app
[Deprecated] KBA_BT_1501: BLE devices on iOS Bluetooth Settings page
Note: This KBA has been marked as deprecated. A more updated KBA can be found here:
BLE devices on iOS Bluetooth Settings Page
Q: Why can't I see my BLE devices on iOS Bluetooth Settings page
A: According to Apple support it is not possible to see BLE devices listed on the Bluetooth Settings page. Only Bluetooth 2.1/3.0 devices are listed such as keyboards and headsets (source). For BLE devices you must use the device's own app or any other 3rd party app which uses CoreBluetooth.
However, it seems that iOS does list BLE devices when they advertise some of the adopted services such as the Heart Rate service. By advertising this service you can get your device visible in the Bluetooth Settings page. To test this by following these simple steps:
- Create an soc-empty project
- Add the Heart Rate service in the Visual GATT Editor
- Tick "Advertise" and click "Generate"
- Build and flash the project
(Disclaimer: We could not find any information source to verify that iOS does indeed list BLE devices when certain adopted services are advertised)
[Deprecated] KBA_BT_1006: Thermometer example with EFR32 internal temperature sensor
Note: This KBA has been marked as deprecated. A more updated KBA can be found here: Thermometer Example with EFR32 Internal Temperature Sensor
Introduction
The attached example is an adaptation of the standard 'SOC - Thermometer' example which instead of accessing the Si7021 Temperature and Relative Humidity sensor through I2C uses the EFR32's own internal temperature sensor. This sensor is measured during production test and the temperature readout from the ADC at production temperature as well as the Celsius value are given in the device information page. Using these and the millivolts per degrees slope found in the sensor datasheet the current temperature can be calculated according to formula:
(For more information, see ADC section of the reference manual of your chosen hardware, e.g. EFR32xG13)
Setting up the project
Start by creating an SoC - Empty sample app for your chosen hardware.
Using the Blue Gecko app you can now read the temperature sampled from the internal temperature sensor.
Implementation
There are a couple of changes to the basic SoC-Thermometer example:
KBA_BT_0103: Understanding the Bluetooth Connection Process
Introduction
Bluetooth ensures reliable data transfer when devices are connected. A connection is required for secure data transfer. This article describes the various states that a Bluetooth device can be in and how to move between these states.
Bluetooth States
Upon starting the Bluetooth stack, the device will be in an idle state, that is to say it will be non-discoverable and non-connectable. Through a call to either of the API functions le_gap_set_mode() or le_gap_bt5_set_mode(), the device can be made discoverable and non-connectable or discoverable and connectable. It is also possible to return the device to the idle, non-discoverable and non-connectable state.
Non-connectable Beacons
A device which is discoverable, but non-connectable is known as a beacon. The advertising data can be seen by any device within range but it is not possible to establish a connection. This means that the advertising device’s data cannot be written. Examples of beacons are the iBeacon and Eddystone standards. If a remote master attempts to connect to a non-connectable slave, the slave’s stack responds to the master with a connection refused error. No interaction is required by the user application.
Connectable Advertisers
A device which is discoverable and connectable advertises and accepts connections from any device within range. When a connection has been established, the stack sends the event le_connection_opened or le_connection_bt5_opened to the application. This event contains the address of the remote device, the type of address, a connection handle, the role of the device in the connection and a bond handle to indicate whether the device is bonded or not. In the case of a Bluetooth 5 connection, the event also includes a handle to indicate which advertising set the connection is associated with. If multiple connections are required, advertising can be restarted from this event.
Closing Connections
If a connection is closed, the event le_connection_closed will be sent to the application. This event includes the connection handle and the reason for disconnection. The reasons for disconnections are documented in the Bluetooth errors section of the API guide.
Connections – Secure and Unsecure
When a connection event is received(evt_le_connection_opened or evt_le_connection_bt5_opened), the application can determine whether or not there is a bond with the remote device by examining the bond_handle parameter. A value of 0xFF indicates no bond, any other value indicates a valid bond. If the local and remote devices are not bonded, the communication between them will be unencrypted and visible to any Bluetooth device within range. It is strongly recommended to secure any sensitive data.
After the connection event, there will be at least one connection parameters event (gecko_evt_le_connection_parameters_id). This event is sent when a connection is opened and any time the connection parameters are updated. The connection parameters event includes information about the connection parameters (connection interval, latency, timeout) as well as the security mode and maximum PDU size. The security mode is one of the following
A secure connection can be requested either by the stack or the user application. The stack will request a secure connection if the remote device attempts to access a protected characteristic. The user application can request a secure connection by making a call to cmd_sm_increase_security(). In either case, an event will be sent by the stack to the user application to indicate whether the bonding/pairing was successful (evt_sm_bonded) or unsuccessful (evt_bonding_failed).
Bonding vs Pairing
The security manager contains events and commands for controlling the security features included in the Bluetooth stack. One of these features is the ability to form new bonds (bondable mode). As shown in the diagram below, when a connection is secured it will either be bonded and assigned a long term key (LTK) which can be used in subsequent connections or paired and assigned a short term key (STK) which will discarded when the connection is terminated. Upon successful bonding/pairing the stack sends the event evt_sm_bonded to the application with a bond_handle as a parameter. As with the bond_handle passed to the evt_le_connection_opened any value other than 0xFF indicates that the devices are bonded while a value 0xFF in this case means that the devices are paired for the current connection.
Maximum Transmission Unit (MTU)
In addition to the connection opened event and the connection parameters event, there will always be a GATT MTU exchanged event for each connection. This event tells you the size of the maximum transmission unit (MTU). This is the maximum size of any packet that can be sent between the client and server. The only special handling that may be required for this event is to use the MTU to determine whether an entire characteristic can be sent in a single read/write or if multiple writes are required. A single read/write can be MTU – 3 bytes in length.
Bluetooth 5 Connections
Whether a connection is secured or not, Bluetooth 5 allows the choice of 1 Mbps or 2 Mbps PHY on a per connection basis. The PHY can be selected with a call to le_connection_set_phy(). A call to this API results in the stack sending the event evt_le_connection_phy_status to indicate which PHY is actually in use for the connection. The diagram below shows that the flow of the connected state is similar to that of Bluetooth 4.x with the addition of the possibility of selecting the 2M Phy.
Multiple Connections and Dual Mode Topology
It is possible to allow up to 8 simultaneous connections. The max_connections parameter in the Bluetooth configuration struct can be used to limit the number of connections to less than 8 if desired. In order to allow multiple connections it is necessary to restart advertising once a connection is made. This can be done from the connection opened event.
One of the additions made in Bluetooth 4.2 is the so-called dual mode topology which allows a device to be a master and a slave simultaneously. Previously it was necessary to disconnect in order to switch roles between master and client.
Conclusion
Connections are Bluetooth’s way of ensuring reliable and, optionally, secure data transfer. Connections also make it possible for devices to negotiate the PHY that they use to communicate.
KBA_BT_0402: EM3 and EM4S for non-connectable advertising
Introduction
This article demonstrates how you can use EM3 and EM4S to enhance energy savings on periodic beaconing applications (non-connectable advertising packets).
The example applications are for the BGM111 module and they are based on SDK 2.3.1 with GCC toolchain.
For generic guidance on energy modes usage with the BLE stack please refer to http://community.silabs.com/t5/Bluetooth-Wi-Fi-Knowledge-Base/Using-Energy-Modes-with-Bluetooth-Stack/ta-p/190173
All the measurements taken for the study detailed in this article were done at a 3V input and +3dBm transmit power. The screenshots shown here are also inside the attached measurements.zip file, including the ones taken for the experimental verification.
Standard Stack Usage - EM2
In the standard stack usage the device will be in EM2 in between advertisement packets as the LFXO is required for timekeeping. The typical value for sleep current in EM2 is 2.5uA as shown in the below figure.
Advertising a non-connectable beacon takes 2.23ms at an average current of 10.14mA as shown below.
These values can be verified with any of the SDK examples, the simplest being the ibeacon example. To get easier readings of the sleep current it is recommended to increase the advertisement interval.
Clocking RTCC from ULFRCO – EM3
In EM3 the LFXO/LFRCO is not running so we need to use some other clock source for the RTCC in which the stack timing is based on. The ULFRCO can be used and it is an extremely low power oscillator which is always running and its frequency can vary from 0.95kHz to 1.07kHz, but for this particular usage the higher inaccuracy is not problematic. This will change the stack timebase from 32768Hz to the ULFRCO frequency of ~1kHz and it will affect the soft-timers where the time parameter will now be in 1kHz ticks.
Using the ULFRCO to clock the RTCC allows reducing the sleep current from 2.5uA in EM2 to just below 2.1uA in EM3 as shown in the figure below.
Clocking the RTCC from a source other than the LFXO will require the advertisements to be timed and sent individually at the application level. This is done by setting the advertisement timeout to 1 occurrence with the command gecko_cmd_le_gap_set_adv_timeout(1) and timing the advertisements with a soft-timer.
The need for timing the beacons at the application level leads to a small overhead in the overall advertisement time as shown below. The advertisement time rises to 2.83ms from the initial 2.23ms at an average current of 9.18mA.
This beaconing scheme is demonstrated in the EM3_beaconing project attached to this article. The following code snippet shows how the advertisement is being managed by the application.
Clocking CRYOTIMER from ULFRCO – EM4S (Shutdown)
Going deeper into the energy modes brings more substantial energy savings in sleep mode which can be beneficial above certain sleep periods. In EM4S there is very little functionality, RAM and register retention is lost and wake up requires a system reset to return back to EM0.
One of the peripherals supported in EM4S is the CRYOTIMER which can be clocked from the ULFRCO to generate periodic wake-ups. These wake-ups will effectively reset the device but as we are again not activating the LFXO, which takes the longest to stabilize, it is possible to have very a short wake-up time.
In EM4S the current drops by a factor of 40 compared to EM2 to 60nA as shown below.
The wake-up time increases as the stack needs to be re-initialize before sending out the beacon. Then the same approach is used as in EM3, setting advertisement timeout to 1 and putting the device back into EM4S when the advertisement has been confirmed through the event gecko_evt_le_gap_adv_timeout.
This beaconing scheme is demonstrated in the EM4_beaconing project attached to this article. The following code snippet shows how the advertisement is being managed by the application.
Summary and Conclusions
Neither of these alternative beaconing methods using EM3 and EM4S bring benefits with short beaconing intervals but the tipping point can be approximately calculated. The following table summarizes the data from the previous sections and adds the energy for both sleep and advertisement periods taking into account a 3V power supply (VDD) as mentioned in the introduction.
The “Sleep energy (per second)” is calculated as "Sleep current" x VDD
The "Advertisement energy" is calculated as "Advertisement current" x "Advertisement duration" x VDD
The tipping point is where the energy savings in sleep mode equal the energy overhead taken by the longer advertisement periods.
Calculating the Tipping Points
The tipping point (in seconds) can then be calculated as savingsInEMX x seconds = advertisingOverhead.
EM2 vs EM3
For EM3 vs EM2 the energy saving in sleep mode is 7.59 – 6.18 = 1.41uJ and the advertising overhead is 78 – 68 = 10uJ. Using these figures we can calculate that the tipping point comes at 7.1 seconds.
EM2 vs EM3
For any beaconing period above 10.24s the stack cannot be used to automatically send the advertisements because 10.24s is the maximum advertisement interval allowed by the API command le_gap_set_adv_parameters. Therefore comparing EM2 vs EM4S is not needed because using EM3 already brings benefits even before reaching the maximum advertisement interval allowed by the stack.
EM3 vs EM4S
For EM3 vs EM4S the energy saving in sleep mode is 6.18 – 0.180 = 6uJ and the advertising overhead is 274 – 78 = 196uJ. With these figures we can calculate a tipping point of 32.7s.
Experimental Verification
To verify that the tipping point calculation is correct we measured the average current for different intervals using the different energy modes.
Verifying EM2 vs EM3 Tipping Point
The EM2 vs EM3 tipping point was calculated at 7.1 seconds. To verify this result we took the average current (sleep period + 1 beacon) at 7 seconds and at 8 seconds with both EM2 and EM3 and compared the results.
The experimental results are aligned with the theoretical calculations and at 8 seconds we start seeing that using EM3 provides a lower average current consumption compared to using EM2.
Verifying EM3 vs EM4S Tipping Point and Beyond
The EM3 vs EM4S tipping point was calculated at 32.7 seconds. In EM4S the wake-up period is programmed into the CRYOTIMER in “number of clock cycles” which comes from the ULFRCO (at about 1kHz frequency as mentioned earlier). This number is programmed as 2x where x ranges from 0 (wake after every clock cycle or every ~1ms) to 32 (wake up after 232 clock cycles, or every ~49.7 days).
For the purpose of verifying the EM3 vs EM4S tipping point we took measurements of the average sleep current at 16 seconds, 32 as well as 64 seconds beaconing intervals to see how the average evolves into longer periods.
The experimental results are aligned with the theoretical calculations and at 32 seconds we start seeing that using EM4S provides a lower average current consumption compared to using EM3. Looking into even longer beaconing intervals the average currents will tend to the sleep current of each mode so the benefits of using EM4S are even more pronounced.
KBA_BT_0309: How to save float values (or any arbitrary data) in PS keys
Question
How can I save a value of type float in Persistent Storage?
(the answer below applies to floats as well as other data types and even for more complex data structures)
Answer
PS store allows you to save byte arrays in flash. Any variables (integers, floats, structs ..) are stored in memory as byte arrays. In case of float, four bytes are required to store the value.
The following code snippets implements a pair of helper functions that allow you to store basically any data in a PS key.
First parameter is the PS key (from range 0x4000...0x407F). The second parameter is a pointer to the data object. The pointer is of type void so that the same code can be applied to any type of variables easily. Last parameter defines the size of the object. You can use the sizeof() operator when calling these which makes it really easy to use this solution your code.
Here's an example how to store and load a float variable in a PS key:
The same functions can be used for storing and loading other fixed side objects, too. Let's assume you have defined a struct that bundles the Bluetooth address and name of a remote device into one variable and you want to save the whole struct in a PS key:
Notes:
* maximum size of one PS key is 56 bytes (SDK v2.3.1)
* total capacity of PS storage is 2kB and part of this space is required to store bonding information