Note
As of 2021, this document follows the Appropriate Language nomenclature directive from Bluetooth SIG. The SDK project names, APIs and code are not yet ported and use the old nomenclature. For details on how to correlate between the two, please open the PDF document Appropriate Language Mapping Tables.
Introduction
This workshop is an introduction to the SimpleLink™ Bluetooth® Low Energy CC2640R2 software development kit (SDK) The 4 tasks in this lab session are targeted to be completed within a 2 hour time frame. There should be an intermediate level of knowledge of the C programming language as well experience with embedded software development to be able to complete the tasks.
This lab session uses the SimpleLink Bluetooth Low Energy CC2640R2F wireless MCU LaunchPad development kit to demonstrate the tasks in this module. The first task shows how to download a project to the device and run it, and the subsequent tasks will explore the wireless BLE interface and make some small changes to the BLE application.
For the latter tasks, either a Bluetooth Low Energy enabled cell-phone or an
evaluation kit running the TI host_test
Sample Application is required. The
advantage of using host_test
is that the TI tools, such as BTool
, can be used.
It is recommended to read the TI BLE-Stack User's Guide {When reading older TI documentation, you may see references to the TI BLE Software Developer's Guide. This was renamed to the TI BLE-Stack User's Guide in conjunction with the added support of BLE 5} alongside this lab for details and further information. Some references will also be made to this document.
Prerequisites
Hardware
For this lab, you need one or two CC2640R2 Bluetooth-enabled development boards:
For testing:
- Additional BLE-capable LaunchPad to run
host_test
OR - Mobile device for testing
Software
- CCS 9 or IAR 8.32.2 installed with support for CC13xx/CC26xx devices.
- SimpleLink™ CC2640R2 SDK 4.40
For testing, a Bluetooth client application is required:
- BTool (located in the
tools\ble5stack
directory of the SimpleLink™ SDK installation) OR - Bluetooth mobile apps:
- Android: BLE Scanner by Bluepixel Technology LLP - available on the Google Play store
- iOS: LightBlue Explorer - Bluetooth Low Energy by Punch Through - available on the App Store
Compiler Support
See SimpleLink CC2640R2 SDK Release notes for supported TI ARM Compiler versions. Compatibility with other TI ARM Compiler versions in CCS has not been tested and use of other compiler versions may result in undefined behavior. Refer to the "Installing a Specific TI ARM Compiler" section of the TI BLE-Stack User's Guide chapter of the TI BLE-Stack User's Guide for the procedure to install other compiler versions.
Recommended reading
- Getting Started Chapter of the TI BLE-Stack User's Guide
- The CC2640R2F Platform Chapter of the TI BLE-Stack User's Guide
Getting started – Desktop
Install the Software
Run the SimpleLink CC2640R2 SDK installer: simplelink_cc2640r2_sdk_x_xx_xx_xx.exe
.
These instructions assume you have installed to the default directory: C:\ti\
This gives you:
- The SimpleLink CC2640R2 SDK at
C:\ti\simplelink_cc2640r2_sdk_x_xx_xx_xx
- BTool accessible via the
\tools\blestack\btool
directory of the SimpleLink CC2640R2 SDK install directory.
Task 1 – Run ProjectZero Project
The first task is to simply run the Project Zero example project on the LaunchPad and verify that the project runs as intended.
Import in CCS Desktop
Open Code Composer Studio and import the Project Zero app and stack library projects:
- Open TI Resource Explorer (View → Resource Explorer) or go to https://dev.ti.com/tirex/#/
In the navigation panel on the left side, expand to find Project Zero in the SimpleLink CC2640R2 SDK.
- Software → SimpleLink CC2640R2 SDK - v:x.xx.xx.xx → Examples → Development Tools → CC2640R2 LaunchPad → blestack → project_zero → TI-RTOS → CCS Compiler → project_zero_app
Click the project folder marked above. Import the project into your workspace by clicking the Import button in the top right of the Resource Explorer view.
- Using CCS Desktop, the button shows as:
- Using CCS Cloud, the button shows as:
- Alternatively, you can hover the mouse over the right of the project name until three vertical dots show up. Clicking on the dots exposes a context menu that allows importing the project.
The projects will appear in your Project Explorer window as shown below.
Connect the LaunchPad
Start by making sure your kit is assembled, turned on, and connected to the PC via the USB cable.
When the Launchpad is connected, the Windows Device Manager (Start → Control Panel → Device Manager, or Win+X, M on Windows 10) will show you the following devices connected:
The Application/User UART
serial port is used for application output in this
example.
Connect a Terminal Program
To see the serial output from the kit it is necessary to use a terminal emulator. Start this up now. There are several options:
- PuTTY
- Tera Term
- RealTerm
- Windows PowerShell
- Or even just going to the command prompt and typing for example
type COM4:
.- Type
help mode
to learn how to set the port parameters.
- Type
- Start your terminal program
- Choose 115200 baud as the speed, 8 bit data, 1 stop bit, no parity, no flow control.
- Open the serial port
Build the Projects and Flash the Device
- Build the Project Zero stack library project by clicking the hammer icon or Ctrl + B
- Debug the Project Zero App project by clicking the green bug icon or F11
- Flash the device, and run the application one of two ways:
- Option 1 (Flash the device and terminate the debug session): Terminate the ProjectZeroApp project (Ctrl + F2 or red square icon)
- Option 2 (Flash the device and continue debugging application): Press F8 or the Play/Pause button to stay in debug mode, but let the program run.
After the application runs you should observe something like the following in your terminal application:
This shows the user application initializing the three services LED, Button and Data, and set initial values for the characteristics in those services. Finally, callbacks are received from the stack that the device is ready and has started advertising its presence.
Take a note of your device address for later use.
In the case that the terminal output is not working correctly, you can use SmartRF Flash Programmer v2 to find your device address.
Task 2 – Connect and Navigate Exposed Services
In order to interact with the Bluetooth Low Energy device you will need to use something to act as a Central device towards it.
There are many mobile applications that can serve this purpose. We will show instructions using BLE Scanner by Bluepixel Technology LLP (Available on the Google Play Store) and LightBlue Explorer - Bluetooth Low Energy by Punch Through (Available on the iOS App Store).
In addition to these mobile apps, Texas Instruments provides a couple of PC tools for this, which in turn communicate over a serial port with special firmware loaded onto a separate CC26xx device. The serial commands conform to the HCI standard as defined by the Bluetooth SIG, and allows control of the Host layers such as GATT, GAP and Security Manager in addition to the bare-metal Link Layer commands required by the HCI specification. Tools like BTool.
Select your preferred method of connecting to Project Zero by expanding the boxes below.
First, you will program a second board with the host_test
project. The host_test
project allows a user to call most of the GAP, GATT and ATT functions of the BLE
stack via a serial interface.
Please refer to the host_test
project information
for how to import, build and flash the host_test
application.
1. Start BTool
BTool is a PC Tool that uses the HCI Vendor Specific commands to act as a
Bluetooth Low Energy device. BTool can be found in the tools -> blestack -> btool
folder of your SimpleLink CC2640R2 SDK installation.
In the SimpleLink CC2640R2 SDK, there are two instantiations of BTool to handle
both the BLE-Stack and the BLE5-Stack. This Project Zero is built using the
BLE-Stack and you will need to start the instantiation that works with the
BLE-Stack. To do that, go to the SDK and go to tools/blestack/btool
and launch
BTool by double clicking Run_BTool.bat
.
When BTool opens the first time, it will prompt you to select the Serial Port
your host_test
device is connected to as show in the picture below.
If you have several COM ports, use Windows Device Manager to figure out which
one is connected to the Application/User COM port of the kit with host_test
running. This is described above.
2. Scan for BLE devices
After the device has finished initializing, the tabbed sections on the left
side of the GUI can be used to perform BLE functions. We will use these actions
to scan for and connect to our Project Zero
device.
In the Discover Connect tab, select
Scan
. The log will keep you updated about the devices that are found.In the Slave BDA drop-down menu, select the address of your device (from the terminal output earlier)
Click Establish to connect
After connecting, your serial window will look something like this:
Note the Peer address
is the address of the kit you used as the Central device.
You will also notice a new Connection Info section on the left side of the BTool window:
3. Navigate the Attribute table
Now that we are connected, we will want to perform a discovery to find all the
characteristics and services on our Project Zero device so that we can interact
with those attributes. A UUID
tells the peer device how the value of an
attribute should be interpreted. You can learn more about attributes and UUIDs
in the Custom Profile
SimpleLink Academy module.
- Right-click on Handle under Connection Info.
- Select Discover UUIDs
You will notice that the section under the log is populated with information about the services and characteristics available on the device.
Jumping directly into the deep end of the pool, what you see in BTool under the log after the discovery is complete is a visualization of what is accessible to any connected GATT Client device via the Bluetooth Attribute Protocol.
The only things reported over the air are Handle
, which is a dynamic
short-form way of addressing an attribute and Type
which tells you how to
interpret the Value
, which is also available. Together, these three values
comprise an Attribute
.
Each row in the image below is an Attribute
. You will notice that some lines
are different colors. The reason for the difference colors is that the Type
imposes a hierarchy in the GATT protocol like this (simplified):
- reddish color – 0x2800 – Service declaration – Value is the Service UUID.
- yellowish color – 0x2803 – Characteristic declaration – Value describes characteristic value attribute
- white – 0xXXXX(-XXX...) – Characteristic value attribute – Value is actual data; all else is metadata.
- white – 0x29xx – Characteristic descriptors – Value is info about characteristic value attribute.
4. Interact
You may notice that some of the attributes do not have an associated value. In order to populate that field for all attributes, you must manually read the values.
- Right-click on Handle under Connection Info.
- Select Read Values
Alternatively, you can single-click on a field in the Value column to read the value for a single item.
Now that our GATT table is populated, we can start to interact with our Project Zero device. The comments in the Value Description field instruct you on what actions are allowed.
To write to a characteristic, double-click on the Value field and a new window appears. By editing the Value in the and selecting Write Value, you can send a Write Request.
For example, to turn on LED0 double click on the Value field that corresponds to
LED0 State
. Writing one byte with a value higher than 00 will turn on the red
LED on the Project Zero LaunchPad.
You can similarly interact with the Button and Data services.
1. Start LightBlue Explorer
Using your iOS device, find the LightBlue Explorer app and open it.
2. Scan for BLE devices
The app should begin scanning for BLE devices automatically but you can refresh the list by pulling down.
You should see Project Zero advertising as "Project Zero R2". Connect to the device by clicking on the name.
After connecting, your serial window will look something like this:
Note the Peer address
is the address of your mobile device. In LightBlue, you
should see the advertisement data (it is hidden by default, click show to view)
and the Device Information
Service.
3. Navigate the Attribute table
Now that we are connected, we will want to understand the different features of
Project Zero and how we can interact with them. Scroll past the Device
Information
service and you will notice rows of long strings of numbers and
properties.
Jumping directly into the deep end of the pool, what you are looking at is a visualization of what is accessible to any connected GATT Client device via the Bluetooth Attribute Protocol.
The only things reported over the air are Handle
, which is a dynamic
short-form way of addressing an attribute and Type
which tells you how to
interpret the Value
, which is also available. Together, these three values
comprise an Attribute
.
LightBlue uses the Attribute
information and displays it in a more usable way.
LightBlue uses the Type
that is sent to arrange the Attributes in a hierarchy
of characteristics and services as shown below:
- Thick, blue box – Service UUID
- Thin, red box – Characteristic UUID
- Properties – show what actions are available for a given characteristic
4. Interact
Use the Custom Identifier list for Project Zero
expandable box below for
description and usage information for Project Zero's services and characteristics.
To interact with a characteristic using LightBlue, click on the Characteristic UUID. Depending on which characteristic you clicked on, you will see something similar to below:
The characteristic shown above has Write properties. To write a new value to a characteristic with Write properties, click "Write new value". In the new window, edit the value using the keyboard given as shown.
When you are finished, click "Done" and you will be taken back to the Characteristic view. A new value will be shown in the "Read Values" section as seen below:
When you are in the Characteristic view, you can click "Read again" to update the value shown. You can also change the format of the value displayed by clicking "Hex" in the upper right corner.
This is particularly useful for the first characteristic in the last service (UUID starts with F0001131). Try changing the display type of the data to UTF-8 string. The long string of data should turn into English text!
1. Start BLE Scanner
Using your Android device, find the BLE Scanner app and open it. Please note that on Android devices enabling Location Tracking is required to use Bluetooth. If you get a pop-up asking you to enable it, please go into your device settings and enable location tracking.
2. Scan for BLE devices
The app should begin scanning for BLE devices automatically but you can toggle scanning on and off by clicking on the magnifying glass in the top right corner of the app. A "Scanning stop" message will appear.
You should see Project Zero advertising as "Project Zero R2". Connect to the device by clicking "Connect".
After connecting, your serial window will look something like this:
Note the Peer address
is the address of your mobile device. In BLE Scanner, you
should see 6 Primary Services. Three have unique names and three are named
"Custom Service".
3. Navigate the Attribute table
Now that we are connected, we will want to understand the different features of Project Zero and how we can interact with them. If you examine the primary services displayed, you will notice that between the Name (for example, "Device Information") and "Primary Service", there are a set of numbers. Furthermore, if you click on a service, it will expand and show you the characteristics that belong to that service. Each one has a UUID followed by another long string of numbers.
Jumping directly into the deep end of the pool, what you are looking at is a visualization of what is accessible to any connected GATT Client device via the Bluetooth Attribute Protocol.
The only things reported over the air are Handle
, which is a dynamic
short-form way of addressing an attribute and Type
which tells you how to
interpret the Value
, which is also available. Together, these three values
comprise an Attribute
.
BLE Scanner uses the Attribute
information and displays it in a more usable way.
BLE Scanner uses the Type
that is sent to arrange the Attributes in a hierarchy
of characteristics and services as shown below:
- Blue box – Service UUID
- Red star – Characteristic UUID
- Properties – show what actions are available for a given characteristic
4. Interact
Use the Custom Identifier list for Project Zero
expandable box below for
description and usage information for Project Zero's services and characteristics.
To interact with a characteristic using BLE Scanner, expand the service that the UUID is a part of and use the circled letters on the right side of the screen.
- R - Read the characteristic
- W - Write to the characteristic
- N - Notify BLE Scanner if value changes
The characteristic shown above has Write properties. To write a new value to a characteristic with Write properties, click the "W" next to the desired characteristic.
From the Custom Identifier list below, we see that for the Characteristic whose UUID starts with F00001111, the usage is to write 01 or 00, so we will change from "Text" to "Byte Array". To change type, tap Text then tap Byte Array. Then write "01".
When you are finished, click "OK" and you will be taken back to the Characteristic view. A new hex value will be shown under "Value:" as seen below:
You can click "R" to update the value shown if the value can be changed without input from the mobile device.
If you read the first characteristic in the last service (UUID starts with F0001131), you will see both a text value and a hex value. This characteristic allows you to send long strings of data.
In case the tool you use to view the Attribute Table on the device running Project Zero does not have the meta-data to interpret the UUIDs to show you descriptions and mnemonics, use this list to identify each service and characteristic:
Keep in mind that some tools will show Value
and Type
fields in the
byte-order received over the air, which means for UUIDs that F0001110-0451-4000-B000-000000000000
becomes 00:00:00:00:00:00:00:B0:00:40:51:04:10:11:00:F0
.
UUID | ATT Field | Description | Usage |
---|---|---|---|
F0001110-0451-4000-B000-000000000000 | Value | LED Service | Service declaration |
F0001111-0451-4000-B000-000000000000 | Type/Value | LED0 State | Read state or write 01 or 00. |
F0001112-0451-4000-B000-000000000000 | Type/Value | LED1 State | Read state or write 01 or 00. |
F0001120-0451-4000-B000-000000000000 | Value | Button Service | Service declaration |
F0001121-0451-4000-B000-000000000000 | Type/Value | BUTTON0 State | Read state or subscribe to notifications |
F0001122-0451-4000-B000-000000000000 | Type/Value | BUTTON1 State | Read state or subscribe to notifications |
F0001130-0451-4000-B000-000000000000 | Value | Data Service | Service declaration |
F0001131-0451-4000-B000-000000000000 | Type/Value | String char | Read/Write a long string |
F0001132-0451-4000-B000-000000000000 | Type/Value | Stream char | Send or receive WriteNoRsp/Notification |
Quiz-time
Use this GATT table from the Connecting using BTool section to answer the following questions (You can enlarge the GATT table by clicking on it).
What is the Handle
of the LED 1 Characteristic Declaration in the GATT
Table pictured above?
Where can you find a Service UUID?
What does the Value
of a Characteristic Declaration tell you? Multiple correct answers.
How many Attributes
does the LED Service consist of in total?
Profiles and Discovery
When a device connects to your device, it has no idea what you have to offer in terms of Services and Characteristics it can interact with.
Emulation tools like BTool will discover and display everything available for
you to manipulate, but typically for most applications there will be a Profile
.
This is a document that describes what interactions can be done via Bluetooth
Low Energy, which services are needed to accomplish various objectives, and how
value reads and writes must be formatted and sequenced for this to be done.
If you didn't know already, GATT imposes a meta-layer on top of ATT. Meaning that an Attribute is an ATT thing, whereas a Service is a GATT thing that uses Attributes.
Using an emulation tool, it is up to you to figure out which attributes
should
be written or read in accordance with a Profile
and manually act like a GATT
enabled application would have done.
Services and Characteristics are discovered after a connection is established
and before GATT interaction can start. This is done because the handle
of an
attribute
is what's used over the air on the ATT level to read/write, but
handles are dynamically assigned. The only thing a remote device knows before it
connects is the UUID of the services and characteristics it wants to use on the
peer.
Health Thermometer Example
For example, you are a Health Thermometer Collector device and want to connect
to and use a health thermometer that follows the Bluetooth SIG adopted Profile
for Health Thermometer.
By reading the Bluetooth SIG specs (looking at GATT services and GATT characteristics) you know that the UUID of the Health Thermometer Service is 0x1809, and the UUID of the Temperature Measurement Characteristic is 0x2A1C.
You then discover the handles for these via defined procedures in order to configure/read/write.
Task 3 – Get Notified
If you are using a mobile device
This task is demonstrated using BTool because it provides the most thorough GATT Table. Instructions on enabling notifications on your mobile device are provided at the end of this task but you are strongly encouraged to go through the BTool instructions for a better understanding of Bluetooth notifications.
You have connected. You have read and written values to control a Bluetooth device and turned on and off LEDs. How about getting some data back from a sensor on your device, like the state of the buttons?
Reading things that change
Read the value of, let's say, BUTTON0 State
. How is the value you read
correlated with the actual state of the button? How often would you have to read
the value out to make a reliable doorbell for example?
In this task you will learn how instead of polling the value you are interested
in, which could waste a lot of energy, you can configure the device to transmit
Notifications
to you when the value changes.
When you are connected to a Peripheral device conforming to the
Project Zero Profile
, this is possible to
do for the button states because of three things:
- The
properties
for each BUTTONx State Characteristic includes theGATT_PROP_NOTIFY
flag. - The BUTTONx State Characteristics include a
Client Characteristic Configuration Descriptor
orCCCD
attribute. Writing to this allows aGATT Client
to enable or disableNotifications
. - The application cares about the value of the
CCCD Attribute
and also tries to send aNotification
when the state changes.
If we have a look at the Button Service
in BTool things may become clearer:
In the figure above, the Access Properties
of each Characteristic Declaration
can be seen in the right column. This is also signified by the "12" in leading byte
of the Characteristic Declaration
Value. You will also notice there is a
Client Characteristic Configuration
attribute that the LED service did not have.
Access Properties
Each characteristic has properties, which are made known in its declaration via a bit-map. The list below is an excerpt from the definitions in the SimpleLink CC2640R2 SDK.
/** @defgroup GATT_PROP_BITMAPS_DEFINES GATT Characteristic Properties Bit Fields
* @{
*/
#define GATT_PROP_BCAST 0x01 //!< Permits broadcasts of the Characteristic Value
#define GATT_PROP_READ 0x02 //!< Permits reads of the Characteristic Value
#define GATT_PROP_WRITE_NO_RSP 0x04 //!< Permits writes of the Characteristic Value without response
#define GATT_PROP_WRITE 0x08 //!< Permits writes of the Characteristic Value with response
#define GATT_PROP_NOTIFY 0x10 //!< Permits notifications of a Characteristic Value without acknowledgement
#define GATT_PROP_INDICATE 0x20 //!< Permits indications of a Characteristic Value with acknowledgement
#define GATT_PROP_AUTHEN 0x40 //!< Permits signed writes to the Characteristic Value
#define GATT_PROP_EXTENDED 0x80 //!< Additional characteristic properties are defined in the Characteristic Extended Properties Descriptor
/** @} End GATT_PROP_BITMAPS_DEFINES */
Snippet from gattservapp.h
What are the properties?
Consider the properties field (hexadecimal) of the two Button State characteristics and the flag list above. Multiple properties are logic-OR'ed together.
What are the access properties of the Button State characteristics?
Client Characteristic Configuration
The behavior and usage of attributes with the type 0x2902
is defined by the
Bluetooth Specification. Luckily, it's not very complicated.
The Value
of the attribute is a 16-bit wide field. Writing 01:00
, which can
be translated to 0x0001
, will tell the device that it's allowed to send
Notifications
of value changes to you. If you write 00:00
you disable
transmissions. If you write 02:00
you allow Indications
instead. That is not
permitted for the button characteristics.
Notifications are enabled a little bit differently in the mobile devices.
For LightBlue Explorer, in the characteristic view, click "Listen for notifications". The text will change to "Stop listening" when notifications are enabled.
For BLE Scanner, tap the circled "N". It will turn green when notifications are enabled:
Quiz!
Looking at this table from Task 3 – Get Notified, what is the Handle
of the CCCD
attribute for BUTTON1 State
characteristic?
What is the configuration of each Button state? Two correct answers.
Action!
- Enable notifications for both BUTTON0 and BUTTON1.
- Try to press the buttons.
- Observe serial output and the value apparent in the BTool GUI. Can you follow the sequence of events in the code?
Task 4 – Customize the Application
This task teaches you to customize how the device appears to the outside, to make it more personal.
There are three main ways you can set your mark on the device:
- The
GAP_ADVTYPE_LOCALNAME_(SHORT|COMPLETE)
field in either AdvData or Scan Response. - The
Device Name
Characteristic in theGeneric Access Service
, and - Various strings in the
Device Information Service
The GAP_ADVTYPE_LOCALNAME
is the field that is displayed by most end-equipment
when scanning for Bluetooth Devices, and it's that field we'll change now. After
a connection is established, and the Service Discovery is complete, many types
of end-equipment will then use the value from Device Name
for display.
Read the Device Name
Using your BTool, find the service called Generic Access Service
(UUID 0x2800)
, expand it to find Device Name (UUID 0x2A00)
, and then read
this value, if not done already.
Change the Advertisement Data
The two variables advertData
and scanRspData
contain the data the device
will transmit while advertising its existence. This data is available to any
interested parties so they can see the device and connect to it.
Change LOCAL_NAME
In project_zero.c
, find the array called advertData
(search via Ctrl+F) and modify the nugget LOCAL_NAME_COMPLETE
of
advertData
to broadcast a name you like better than the original.
static uint8_t advertData[] =
{
/* ... */
// Complete name
10, // length of this nugget including flag byte.
GAP_ADTYPE_LOCAL_NAME_COMPLETE, // identifier for this nugget
'S', 'p', 'i', 'd', 'e', 'r', 'P', 'i', 'g',
/* ... */
}
Example LOCAL_NAME modification. Note length field.
When you have done this, right-click on the Project Zero App project and select
Build Project
. When this is completed, download to the target, run the changed
code and observe that when you scan for Bluetooth Devices, the name has changed.
The change will also show up in the serial output.
Note that some mobile devices have a tendency to cache previously known device names and may not update yours. In order to see your new device name, look up how to clear the Bluetooth cache on your mobile device
That's it!
Very well done! For adventure's sake, you can also change the Device Name
value.
Find the function call GGS_SetParameter(GGS_DEVICE_NAME_ATT, ...)
in the
function project_zero.c::ProjectZero_init()
and modify the contents of the
array being pointed to.
References
This work is licensed under a Creative Commons Attribution-NonCommercial-NoDerivatives 4.0 International License.