PSoC4 BLE Central Custom Profile w/LED & CapSense

Summary

Last week I got a nice email from a Cypress customer in Italy (I think).  He asked about implementing a PSoC4 BLE Central.  I replied that it was pretty easy.  Over the weekend I thought about it a little bit more and realized that I had never implemented the Central a.k.a. the “other” side of a BLE connection in a PSoC.  I had always built the Central side in an iPhone application written in Swift or Android application written in Java.  So it seemed like a good thing to do to implement it in C.  It turned out to not be quite as easy I had hoped because of some problems in the Cypress documentation.  In the next several articles I am going to show you how to implement a PSoC4 BLE Central.

I am going to use the project from the video series called “capsenseled” as the GAP Peripheral and then I am going to show you how to write the GAP Central code.  You can learn about the GAP Peripherals in the video series called “PSoC® 4 BLE 101 Video Tutorial Series: How To Create Products Using PSoC 4 BLE“.  Here is the first video from YouTube.

In that series of videos I showed you how to build a custom GATT profile for Capsense and an LED.  The GAP Peripheral has an LED that you can control from the GAP Central, and it has a Capsense slider that you can read its value from the GAP Central.  You can “git” all of the source for this project from the IoTExpert Github website or git@github.com:iotexpert/PSoC4BLE-Central.git

In this article I will show you:

  • The GAP Peripheral and GATT Database
  • How to build the schematic for the GAP Central
  • How to configure the BLE component for the GAP Central functionality
  • The steps required in the firmware to read and write the GAP Peripheral

The GAP Peripheral and GATT Database

To start the process I will “git” the source code for this GAP Peripheral from the IOT Expert Github site.  Then, I open the project called “capsenseled” in PSoC Creator.  The schematic has:

  • The Capsense component which controls the slider
  • A PWM that drives the blue LED to serve as a notification of the state of the BLE (blinking means advertising)
  • A red LED which can be turned on/off from the GAP Central Side
  • The BLE Component

PSoC4 BLE CapSense LED Peripheral

The BLE Component is configured to be:

  • A GAP Peripheral
  • with a GATT Server

PSoC4 BLE Peripheral Configuration

The GATT Database is setup to have:

  • A custom service called “ledcapsense”
  • A custom characteristic called “led” (a uint8)
  • A custom characteristic called “capsense” (a uint16)

PSoC4 BLE Peripheral GATT Configuration

The advertising packet is setup to advertise

  • The name of the device “capled”
  • The fact that it has a GATT Service called “ledcapsense”

PSoC4 BLE Peripheral Advertising Packet

When you program this project you will get a blinking blue LED (that says the BLE is advertising).  When I run “lightblue” I can see the “capled” advertising:
LightBlue BLE Explorer

After I connect the device I can see the UUID of the custom service & the two characteristics:

LightBlue BLE Explorer

Finally I can read/write the led characteristic.

LightBlue BLE Explorer

PSoC4 BLE Central Schematic

To make my PSoC4 BLE Central I build a project for the CY8CKIT-042-BLE  (you can see all of the source code in the project called “centralled”

CY8CKIT-042-BLE

Start by building a schematic with

  • A debug UART (I will print to the terminal program)
  • The red/blue/green led pins
  • The mechanical button pin (called SW1)
  • A PWM to drive the green LED (it will vary the brightness of the LED based on the capsense value on the GAP Peripheral)
  • The BLE Component

PSoC4 BLE Central Schematic

Configure the PWM (to vary between 0 and 100% brightness) with inverted logic (because the LED on the board is active low)

PSoC4 BLE Central PWM

Assign the Pins:

PSoC4 BLE Central Pin Assignment

You will need to configure the BLE to be a:

  • A GATT Client
  • A GAP Central

PSoC4 BLE Central BLE Configuration

If you tell the BLE Component what the GATT Server configuration looks like (on the GAP Peripheral side) it will make the service discovery firmware much simpler.  To do this, go to the GAP Peripheral project and export the “ledcapsense” service from the Peripheral into an xml file (see the Save Selected Service…)

PSoC4 BLE Central GATT Database

Then go back to your PSoC4 BLE Central project and add a new service “From file” (see at the bottom of the menu)

PSoC4 BLE Central - Load Service

After all that you will end up with something that looks like this.  You can see the “ledcapsense” service is listed under the “client” section of the GATT configuration.

PSoC4 BLE Central GATT Database

PSoC4 BLE Central Firmware

The firmware for the PSoC4 BLE Central needs to:

  1. Initialize the PSoC
  2. Scan for GAP Peripherals that are advertising the “ledcapsense” service
  3. Connect to the GAP Peripheral & Discover its services
  4. Turn on notifications for the Capsense characteristic
  5. Loop
    1. If the users changes the state of the button then send over a LED on/off
    2. If you receive a notification of a change in capsense then update the PWM Compare value (to change the intensity)

Most of the Cypress BLE APIs will create an “event” that you will need to process in the BLE loop.  The interesting events are:

Event Description
CYBLE_EVT_STACK_ON The BLE Stack has turned on and you can start advertising
CYBLE_EVT_GAP_DEVICE_DISCONNECTED The GAP Peripheral you were attached to has disconnected.  Start scanning for another GAP Peripheral to attach to
CYBLE_EVT_GAP_DEVICE_CONNECTED You have successfully completed a connection to a GAP Peripheral
CYBLE_EVT_GAPC_SCAN_PROGRESS_RESULT You received an advertising packet from a GAP Peripheral
CYBLE_EVT_GAPC_SCAN_START_STOP You either stopped or started scanning for advertising packets from GAP Peripherals
CYBLE_EVT_GATT_CONNECT_IND The GATT Connection is complete.  This event occurs before the CYBLE_EVT_GAP_DEVICE_CONNECTED EVENT so you don't need to do anything
CYBLE_EVT_GATTC_DISCOVERY_COMPLETE The service discovery is complete.  You can now set the CCCD and turn on the PWM
CYBLE_EVT_GATTC_HANDLE_VALUE_NTF You received a notification of a change in the Capsense from the GAP Peripheral.
CYBLE_EVT_GATTC_WRITE_RSP: Your write succeeded.  For this application there is nothing to do

To make all of this work, I created a state machine using an enumerated datatype.

1. Initialize the PSoC4 BLE Central

The project starts with the normal turn on the PSoC components and stuff.

2. Scan for Peripherals that are advertising the “ledcapsense” service

Most everything that happens in the BLE sub-system triggers a callback to your “AppCallback” which you registered when you started up the BLE component.  The AppCallback has two parameters, which event and a generic void* style argument which can be one of a bunch of things.

(Lines 73-79)  After you turn on the power to your central and the BLE subsystem you will need to start scanning for peripherals that are advertising.  To do this you call “CyBle_GapcStartScan”.  The “Gapc” part of the API name means GAP Central.  The other time you need to start scanning is when you have been disconnected.

(Lines 81-93)  When you receive an advertising packet you can look in the packet and figure out if it is a GAP Peripheral that you want to attach too.  In this case I:

  • Only look at packets that are 29 bytes long (which I looked up in the BLE GAP Peripheral project)
  • And.. if the packet has the UUID of the capsenseled service
  • Then I save the Bluetooth Device Address (BD address) and stop scanning.  When the scanning is stopped the BLE subsystem will issue and event called “CYBLE_EVT_GAPC_SCAN_START_STOP” (the next section)

 

3. Connect to the Peripheral & Discover the Services

(lines 97-100) When the BLE either starts or stops scanning it issues the “CYBLE_EVT_GAPC_SCAN_START_STOP” event.  I use the state machine to determine what to do.  Basically if the mode of my system is “SM_CONNECTING” then I attempt to make a connection to the remote device.

(lines 102-105)  Once the device is connected you need to do a service discovery to find out what services are on the GAP Peripheral and more importantly what are the handles of the characteristics.  The CyBle_GattcStartDiscovery issues requests to the GAP Peripheral to tell the services and characteristics on the peripheral, to which it responds with events.  Cypress provides code in BLE_custom.h and BLE_custom.c to process those responses.  Once the discovery is complete you are then ready to talk to the device.

4. Turn on notifications for the Capsense characteristic

We are interested in getting notified when the Capsense characteristic on the GAP Peripheral changes.  To enable getting a notification you need to write a “0x01” into the Client Characteristic Configuration Descriptor or CCCD.  In order to accomplish this you need to know the handle of that descriptor.  The handle is discovered automatically by the BLE_custom.c functions.  If you look in BLE_custom.h you will find #define(s) that are the indexes of the things you need to know from the service discovery array.

To set the CCCD you create a “CYBLE_GATTC_WRITE_REQ_T” and fill it in with the information required.  Specifically, the value and the handle which you find on line 57.  Then you write it to the GAP Peripheral.

5. Main Loop

The main look is simple.  Basically if you are in the SM_CONNECTED state, then call the function which updates the state of the Remote LED.

 

5. Main Loop (Write the state of the LED)

This function looks at the state of the switch, then if it has changed, sends the updates state to the Peripheral.  The switch is active low (a 0 means that it is pressed) but we want a “1” to mean turn on the LED.

Just like the updateCapsenseNotification() function, you look in the cycle_customCServ array to find the handle of the LED characteristic.

5. Main Loop (Capsense Notifications)

The last bit of code updates the state of the PWM driving the LED when you get a notification from the GAP Peripheral that it has been updated.

In the next Article(s) I will show you how to use the CySmart dongle.  I am also planning on showing you the firmware to create a GATT Browser.