WICED Bluetooth Using the CYW20719
Source code:
- git@github.com:iotexpert/wiced_bt_intro.git
- https://github.com/iotexpert/wiced_bt_intro
Summary
In this lesson we are going to build the simplest project that I could think of… turning an LED on/off with Bluetooth Low Energy.
The important BLE concepts are
- What is a Central / Peripheral
- What is Advertising
- What is a GATT Database
The important WICED Bluetooth Concepts are:
- How do you run WICED Bluetooth Designer
- What is the structure of a WICED Bluetooth Project
- What is a Callback
- How is the GATT Database Implemented
- How to run CySmart
The steps that we will follow are:
- Run BT Designer
- Create a project called L5_BluetoothLED
- Go to the characteristics page
- Add a vendor specific service
- Name the Service L5Service
- Add an optional characteristic that is vendor specific
- Name it RED
- Make it 1 byte with an initial value of 01
- Set it up for host write
- Add a user description to the characteristic
- Generate the code
- Move the folder to the wiced_bt_class folder
- Fix the three include problems
- Reset the debug UART to PUART
- When there is a write, change the value of the WICED_LED_1 GPIO
- Test
BLE Concepts
In the world of BLE there are two sides of every connection
- The Central – typically a cellphone
- The Peripheral – your WICED device
Centrals listen for Peripherals that are Advertising. Advertising is a periodic packet of up to 31 bytes of information that a Peripheral will send out to make it presence known. When a Central hears the Advertising packets of a Peripheral that is “interesting” it can initiate a connection.
Once a connection is made, how do you exchange information? The answer is that a Peripheral has a database running inside of it. The database is called a “GATT database”. A Central can perform “Service Discovery” to find all of the legal stuff in the database. The GATT database is organized into one or more “Services” that have one or more “Characteristics”. For instance a Heart Rate Monitor might have a “Heart Rate Service” with two characteristics, one for heart rate and one for battery level.
There are two types of Services. Ones that are specified by the Bluetooth SIG, like heartrate. And vendor specific custom services.
Run Bluetooth Designer
The Bluetooth Designer is a GUI tool that we built into Eclipse. It allows you to configure some of the fundamental Bluetooth feature (like the GATT Database) and then automatically generate the code. Start Bluetooth Designer by running File->New->WICED Bluetooth Designer.
Since this is Lesson 5 and we are going to write and LED… call the project “L5_BluetoothLED”
Once you start BT Designer, you screen should look like this. The project is going to be a BLE only project.
The Characteristics button lets you setup the GATT database.
Add a service by selecting vendor specific service and then hitting the “+”
I’ll call the service “L5Service”
Next add a characteristic by selecting “vendor specific characteristic” and pressing “+”
Change the name to “RED”, Make the device role “Host write to or reads from service”. Make the size 1 byte and set the initial value to 01 (it must be 01 not 1 or 001)
When we are looking at this remotely you would like to be able to see the user description. So click that tab and give it a description.
Press Generate Code button. You will end up with a folder in the top level apps directory. I don’t like this, so lets move it into our class projects folder. You can do this by dragging the folder to the wiced_bt_class folder. Now it should look like this:
Unfortunately, there are three little issues that this creates which need to be fixed. First, you need to fix L5_BluetoothLED.c as this include is wrong.
#include "../wiced_bt_class/L5_BluetoothLED/L5_BluetoothLED_db.h"
And change it to:
#include "L5_BluetoothLED_db.h"
Next edit L5_BluetoothLED_db.h and add the #include “wiced.h”
#include "wiced.h"
Finally edit the L5_BluetoothLED_db.c to fix the same include problem.
#include "../wiced_bt_class/L5_BluetoothLED/L5_BluetoothLED_db.h"
It should be like this.
#include "L5_BluetoothLED_db.h"
Now edit the make target that was created by the BT Designer and change it to:
Remember in the earlier lesson I showed you about the WICED HCI UART and the WICED PUART. Well by default the WICED_BT_TRACE is setup to go to the HCI UART. So, lets fix the output of BT_TRACE to go to the PUART by changing the file “L5_BluetoothLED.c”
#if ((defined WICED_BT_TRACE_ENABLE) || (defined HCI_TRACE_OVER_TRANSPORT))
/* Set the Debug UART as WICED_ROUTE_DEBUG_NONE to get rid of prints */
// wiced_set_debug_uart( WICED_ROUTE_DEBUG_NONE );
/* Set Debug UART as WICED_ROUTE_DEBUG_TO_PUART to see debug traces on Peripheral UART (PUART) */
wiced_set_debug_uart( WICED_ROUTE_DEBUG_TO_PUART );
/* Set the Debug UART as WICED_ROUTE_DEBUG_TO_WICED_UART to send debug strings over the WICED debug interface */
//wiced_set_debug_uart( WICED_ROUTE_DEBUG_TO_WICED_UART );
#endif
The last thing that we want to do is fix it so that when the Central writes a new value into the RED LED characteristic we should write the GPIO to the new value. In L5_BluetoothLED.c make this change.
case HDLC_L5SERVICE_RED_VALUE:
WICED_BT_TRACE("LED = %d\n",l5_bluetoothled_l5service_red[0]);
wiced_hal_gpio_set_pin_output(WICED_GPIO_PIN_LED_2,l5_bluetoothled_l5service_red[0]);
break;
Now build the project and see what happens. The first testing step will be to open CySmart. You can see that a device called “L5_BluetoothLED” is advertising.
When I click it, you can see that there is a GattDB.
When I click on the database, I can see that there is only one service (which makes sense as we setup only one)
Click on the Service and you can see that there is only one characteristic in the service… and its value is 01.
When you click the descriptor button you can see that there is a Characteristic User Description
And finally the value is “Red LED Value”. That is what we setup.
When you click back … then click on the write it will bring up this window where I can send a new value.
Now the value is 0x00 and the RED LED is on (remember from earlier that it is active low so that makes sense)
And when I look at the terminal I can see two writes (I wrote again before I took this screen shot)
A Tour of the Source Code
The GATT Database is in the file L5_BluetoothLED_db.c
const uint8_t gatt_database[] = // Define GATT database
{
/* Primary Service 'Generic Attribute' */
PRIMARY_SERVICE_UUID16 (HDLS_GENERIC_ATTRIBUTE, UUID_SERVICE_GATT),
/* Primary Service 'Generic Access' */
PRIMARY_SERVICE_UUID16 (HDLS_GENERIC_ACCESS, UUID_SERVICE_GAP),
/* Characteristic 'Device Name' */
CHARACTERISTIC_UUID16 (HDLC_GENERIC_ACCESS_DEVICE_NAME, HDLC_GENERIC_ACCESS_DEVICE_NAME_VALUE,
UUID_CHARACTERISTIC_DEVICE_NAME, LEGATTDB_CHAR_PROP_READ,
LEGATTDB_PERM_READABLE),
/* Characteristic 'Appearance' */
CHARACTERISTIC_UUID16 (HDLC_GENERIC_ACCESS_APPEARANCE, HDLC_GENERIC_ACCESS_APPEARANCE_VALUE,
UUID_CHARACTERISTIC_APPEARANCE, LEGATTDB_CHAR_PROP_READ,
LEGATTDB_PERM_READABLE),
/* Primary Service 'L5Service' */
PRIMARY_SERVICE_UUID128 (HDLS_L5SERVICE, __UUID_L5SERVICE),
/* Characteristic 'RED' */
CHARACTERISTIC_UUID128_WRITABLE (HDLC_L5SERVICE_RED, HDLC_L5SERVICE_RED_VALUE,
__UUID_L5SERVICE_RED, LEGATTDB_CHAR_PROP_READ | LEGATTDB_CHAR_PROP_WRITE,
LEGATTDB_PERM_READABLE | LEGATTDB_PERM_WRITE_REQ),
/* Descriptor 'Characteristic User Description' */
CHAR_DESCRIPTOR_UUID16 (HDLD_L5SERVICE_RED_USER_DESCRIPTION,
UUID_DESCRIPTOR_CHARACTERISTIC_USER_DESCRIPTION, LEGATTDB_PERM_READABLE),
};
Each row in the Database table has a unique “Handle” that is defined in the L5_BluetoothLED_db.h
#define __UUID_L5SERVICE 0x30, 0x9d, 0x7f, 0x29, 0x73, 0xca, 0x4f, 0xfd, 0xa5, 0x68, 0x17, 0xd8, 0x90, 0x67, 0x7f, 0x35
#define __UUID_L5SERVICE_RED 0x29, 0xbf, 0x86, 0xa6, 0xc8, 0x6c, 0x4e, 0xa5, 0xaa, 0x56, 0xbd, 0xac, 0x72, 0x80, 0x93, 0xa9
// ***** Primary Service 'Generic Attribute'
#define HDLS_GENERIC_ATTRIBUTE 0x0001
// ***** Primary Service 'Generic Access'
#define HDLS_GENERIC_ACCESS 0x0014
// ----- Characteristic 'Device Name'
#define HDLC_GENERIC_ACCESS_DEVICE_NAME 0x0015
#define HDLC_GENERIC_ACCESS_DEVICE_NAME_VALUE 0x0016
// ----- Characteristic 'Appearance'
#define HDLC_GENERIC_ACCESS_APPEARANCE 0x0017
#define HDLC_GENERIC_ACCESS_APPEARANCE_VALUE 0x0018
// ***** Primary Service 'L5Service'
#define HDLS_L5SERVICE 0x0028
// ----- Characteristic 'RED'
#define HDLC_L5SERVICE_RED 0x0029
#define HDLC_L5SERVICE_RED_VALUE 0x002A
// ===== Descriptor 'User Description'
#define HDLD_L5SERVICE_RED_USER_DESCRIPTION 0x002B
Each characteristic value is held in one of the uint8_t arrays found in “L5_BluetoothLED.c”
/*******************************************************************
* GATT Initial Value Arrays
******************************************************************/
uint8_t l5_bluetoothled_generic_access_device_name[] = {'L','5','_','B','l','u','e','t','o','o','t','h','L','E','D'};
uint8_t l5_bluetoothled_generic_access_appearance[] = {0x00,0x00};
uint8_t l5_bluetoothled_l5service_red[] = {0x01};
uint8_t l5_bluetoothled_l5service_red_user_description[] = {'R','E','D',' ','L','e','d',' ','V','a','l','u','e'};
/*******************************************************************
* GATT Lookup Table
******************************************************************/
/* GATT attribute lookup table */
/* (attributes externally referenced by GATT server database) */
gatt_db_lookup_table l5_bluetoothled_gatt_db_ext_attr_tbl[] =
{
/* { attribute handle, maxlen, curlen, attribute data } */
{HDLC_GENERIC_ACCESS_DEVICE_NAME_VALUE, 15, 15, l5_bluetoothled_generic_access_device_name},
{HDLC_GENERIC_ACCESS_APPEARANCE_VALUE, 2, 2, l5_bluetoothled_generic_access_appearance},
{HDLC_L5SERVICE_RED_VALUE, 1, 1, l5_bluetoothled_l5service_red},
{HDLD_L5SERVICE_RED_USER_DESCRIPTION, sizeof(l5_bluetoothled_l5service_red_user_description), sizeof(l5_bluetoothled_l5service_red_user_description), l5_bluetoothled_l5service_red_user_description},
};