You are here

Sending Custom Data from server to client PSoC 4 BLE devices | Cypress Semiconductor

Sending Custom Data from server to client PSoC 4 BLE devices

Summary: 16 Replies, Latest post by Rohit R on 01 Apr 2016 12:22 AM PDT
Verified Answers: 2
Last post
Log in to post new comments.
samsiek's picture
12 posts


Essentially, I am working on a project whose scope is to have a PSoC 4 BLE device communicate via I2C to an accelerometer device. This device will output 3 16 bit x, y, z data chunks. I would then like to take this data, and send it via Bluetooth to another PSoC 4 BLE device. At this point, I am struggling with understanding how the best way to send this data is. 

I have been working primarily with the Running Speed and Candence program that Cypress provides. My main question is, how do I get data from the server, to the client. At this point, my initial thoughts are to create a custom characterisitc within either the Custom Service or the Running Speed and Cadence Service. I would name this custom characterisic something like "accelData" and within it, have 3 fields, such as "x_data", "y_data" and "z_data". Then I would write values to these fields. 

I don't know if this is the correct way to go about sending custom data from the server to the client. I have not been able to figure out a way to change the values yet. 

Should I create multiple custom characteristics? Should I make custom descriptors? How do I change the values of these as the accelerometer data comes in? Which API's will be needed here? I assume I will use CYBLE_RscssSetCharacteristicValue(...);

I am hoping there may be someone who has encountered a similar situation to this and would be able to guide my thinking in this matter.

Thanks in advance for the help. I can upload screenshots of code, add more information or clarify questions if need be. 


VAVC's picture
Cypress Employee
506 posts



In the picture only READ is enabled.


If READ is enabled then client has to read the data from the server.You have to use CyBle_GattcReadCharacteristicValue() in client to read this value.


Better to enable the notify.Write the I2C data to the characterisitcs and send the notification to client when there is new data from I2C.

CyBle_GattsNotification() to send the notifications from the server to client.


you can do it in both ways.




roit's picture
Cypress Employee
221 posts


If data transfer over custom services/characteristics is what you want to do (and not Running Speed and Cadence), then why not start with the custom example project on the CY8CKIT-042-BLE Pioneer kit? The example projects and its respective User Guide can be installed from the kit's website ( ) -> CY8CKIT-042-BLE KIT ONLY PACKAGE (Kit Design Files, Documentation, Examples). The CapSense Slider and LED project supports three type of data access viz. read, write and notify, which you can use for your project.

Going over your project requirements, I would (personally) suggest to go for one custom service (Accelerometer) with three custom characteristics (X, Y, Z direction).

Also, as this project requires updated Accelerometer data to be sent from server to the client whenever such data is available, I would suggest you to support Notify in each of the custom Characteristics. This way, once the Client (your phone) enables the notification on the Server (your kit with accelerometer), then the server can send the new data whenever it has and Client does not need to worry about reading a new value everytime.

Client enables the notification on a characteristic by writing 0x0001 on a defined descriptor called Client Characteristic Configuration descriptor (CCCD). Each characteristic that supports notification should also have this descriptor

For your project, you need to handle two things (use the CapSense_Slider_LED project from Kit as reference):

1) Handle the Notification enabled write request on CCCD from Client device: Whenever such request comes from the client device, in PSoC, the BLE Stack generates event 'CYBLE_EVT_GATTS_WRITE_REQ'. Inside this event, extract the notification enable status (either enable 0x01 or Disable 0x00)

2) Send notification whenever the data is available: use 'CyBle_GattsNotification()' API to send the notification data. Ensure that you have the check on point (1) above before sending notification.

I hope this helps. 


samsiek's picture
12 posts

 Thanks very much for the response, I have a few follow up questions now that I have done some of the things you recommended. 

First, in the GATT profile tab, I have created a custom service calle accelerometer with 3 custom characteristics (xData, yData, and zData). Within each of these characteristics, I have enabled the Notfiy checkbox. I have not clicked on any other checkboxes. My first question is whether I should check another box, such as read or write.

The next question is about CYBLE_EVT_GATTS_WRITE_REQ case. I have gone to this and found some if statements that are for the CapSense and the RGB Led services. I have added my own if statemet that resembles the CapSense if statement. I have added a screenshot of that code. Does this look correct to you and is this code necessary for my application.

The final question I have is about the sending of data. It seems as though the RGBLED and CapSense services have a function called SendDataOverRGBledNotification or SendDataOverCapSenseNotification. I found these functions in the BLEApplications.c file. Will I need a similar function? Or can I just use the CYBLE_GattsNotification API? 

Thanks again for your help.



BMAH's picture
Cypress Employee
189 posts


In your application, I understand you just need to send the data of x,y and z postions. The server can send this data via notifications. So you just need to Select the "Notify" option. You can follow Capsense Slider Characterisitcs for more details. For RGB LED Service, we enabled Wrie so that the client can write new set of data which in turn can control the LED brightness. I dont think this is needed for your application.

I think you missed to add the screesnhot of your code. But you can refer the same format as given in the project. The main API would be CyBle_GattsNotification(). 

Yes. You need a similar function to send the x,y and z positions. Declare an object of type CYBLE_GATTS_HANDLE_VALUE_NTF_T and send the data using its members as notifications.

samsiek's picture
12 posts

 Hello again,

We have done a lot of development and have made some good progress. At this point, we are able to send a byte of accelerometer data to the Cysmart App using the BLE dongle. We still are running into a few limitations in this regard and have a couple remaining questions. 

The data that we have been able to send made use of the the CapSense functions. We found an if statement in main.c that we could use to generate notifications that sent data to the client from the server. The if statement is the following:

if(sendCapSenseSliderNotifications & CCCD_NTF_BIT_MASK){//code}

We made a similar if statement that did not seem to execute. It looks like this:

if(sendAccelxDataMSBNotifications & CCCD_NTF_BIT_MASK){//code}. We made every intention to define and declare the variables in this if statement idential to the cap sense statement. 

Because of this, we have done our testing of our code by placing it in the CapSense if statement in order to get it to execute.  The code we have written is a function that we call called HandleAccel(). From this function, another function is called that does the I2C code to retreive 6 bytes of accelerometer data. Then HandelAccel() calls the sendDataOverNotification functions() that we have written. When we just send one byte, and only call one sendOverDataNotification() function, it works. But when we try to send all six bytes of accel data, nothing works, not even the capSense. We are wondering if maybe calling all the functions to get the accelerometer data and to send it using notifications is timing out or running into some other issue. 

I have attached a picture that has code snippets from the two if statements, the upper if statement executes and the lower does not. 

The second code snippet is the sendxMSBOverNotifications() function. We have copies of this function to handle xMSB, xLSB, yMSB, yLSB, zMSB, and zLSB.

Thanks for the continued support, we feel like we are on the verge of getting this working. 


roit's picture
Cypress Employee
221 posts



I have following question:


1) What is the size of the data that your custom characteristics support? If you are using 3 different characteristics for each of the X, Y and Z, then the data size should be 2 bytes. It can be set from the BLE component GUI -> Profiles tab -> Your custom characteristics setting.

If you are using single characteristic for all three values, then you should have a size of 6 bytes.


2) I see from the second part of the PNG you attached that the .value.len is set to CAPSENSE_SLIDER_NTF_DATA_LEN, which is set to 1 in default project. Did you change this to 2 or 6, depending on your implementation above?

Please note that if you have three separate characteristic, then you have to have three different functions to send notifications to each of the characteristic, as the attribute handle for each characteristic is different. Also, in this case, the .vale.len should be equal to 2.

If you have a single characteristic for sending all 6 bytes, then current method should work, expcet that you should put the .value.len equal to 6.


3) Where are you updating the sendAccelxDataMSBNotification flag? This should be ideally updated under the 'CYBLE_EVT_GATTS_WRITE_REQ' event of the event stack handler in BLEApplications.c. Also, when this event comes, do check that the attribute hanlde of the write request is equal to the attribute handle of the CCCD of the intended characteristic.


Can you share your project here with us? It will be easier for us to debug if we have the code. :)



samsiek's picture
12 posts

 Thanks for the feedback.

We are using an accelerometer to read in data over I2C. The way the data comes from the accelerometer is 6 bytes of data. These bytes are xmsb, xlsb, ymsb, ylsb, zmsb, zlsb. We have written six sendOverNotification() functions that handle this data and send it. These functions are currently working well and will send data to the Cysmart dongle and we see this data update live. 

The issues we currently face are:

1. The z lsb does not get correct data in this program. We know the sendOverNotification() function works and we have tested the accelerometer on other computers running the same accelerometer i2c code. We aren't sure why there would be an issue with just this byte in our program. 

We also are consistently getting issues with our i2c block. There are clock issues if we set the data rate to anything higher than 100kbps. What can we do to make the i2c block work even at higher data rates? Would deleting some of the RGB LED code and and prism blocks help?

I have attached the project in a zip file to this comment.



roit's picture
Cypress Employee
221 posts



After a quick look over the project, here are my comments:


1) The project employs Low power mode, where the system is put in low power (either sleep or deep sleep) whenever possible. The related code is in HandleLowPower.c. The issue I see here is that you are using I2C block but you are not handling its respective sleep and wakeup procedure during CPU Deep Sleep (no need to handle these when CPU is only in sleep). You need to call Com_Sleep() and Com_WakeUp() APIs inside 'if(shut_down_led)', just like that for PrISM_1/_2. This way, during Deep Sleep, the I2C block will be prepared correctly for next wakeup.

For now, I would advise you to disable the Low Power mode feature. This way, your code will be simpler and we can be sure whether the I2C issue is because of unhandled Low Power mode procedure for I2C or not. To disable lowpower mode, comment the #define ENABLE_LOW_POWER_MODE from the BLEApplications.h file and rebuild.


2) It completely depends on how you want to implement your application, but I would advise you to keep number of characteristics less. With lesser number of characteristics, you have less Attribute updates to handle and so less events. In your application, I see that we can do same application with changing the characteristics to something like shown in attached figure 'modified_custom_attributes.png'. Rather than 6 characteristics sending one byte each, change to 3 characteristics sending 2 bytes each.


3) If you go for above change, then you notification function will become something like this and you will have only three of these (X, Y, Z)

void sendxOverNotification(uint8 * xData, uint8 len)


/* 'xataNotificationHandle' stores X-axis notification data parameters */

CYBLE_GATTS_HANDLE_VALUE_NTF_T xataNotificationHandle;

/* If stack is not busy, then send the notification */

if(busyStatus == CYBLE_STACK_STATE_FREE)


/* Update notification handle with CapSense slider data*/

xataNotificationHandle.attrHandle = CYBLE_ACCELEROMETER_XDATA_CHAR_HANDLE;

xataNotificationHandle.value.val = xData;

xataNotificationHandle.value.len = len; //length of 2 byte

/* Send the updated handle as part of attribute for notifications */





Your data collection function in main.c will be something like this:

xData[0] = Com_I2CMasterReadByte(Com_I2C_ACK_DATA);

xData[1] = Com_I2CMasterReadByte(Com_I2C_ACK_DATA);



sendxOverNotification(xData, sizeof(xData));




4) If you have time, you should remove the RGB LED and CapSense slider code and its respective service/characteristic from the BLE component. This will reduce much of the complexity and processing that is currently happening in the firmware.



user_78878863's picture
2551 posts

I would even go so far and create a characteristic that has 3 fields, each of the 'sint16' type (since that matches the results from your sensor). This also matches the actual meaning - all three values belong together.

And since you then need only a single notification, only a single data packet needs to be send, saving power.

samsiek's picture
12 posts

 Thanks again for all of the really helpful feedback.

We are now at a point where the accelerometer is sending all of its data over notifications successfully and accurately. 

We have also removed much of the portion of the code that we are not using such as the PRISM blocks and all of the RGB LED functions and code. Because of this, we have put in some of our own custom LED handling code. We did not see a significant decrease in size of the project when compiling; it still uses lots of the SRAM and FLASH. 

At this point we still have the strange if() statement that is not executing. The CapSense if statement looks like this: 

if(sendCapSenseSliderNotifications & CCCD_NTF_BIT_MASK){}  We have written a similar line but it doesn't execute. As a result, we have placed our HandleAccel() function call within the above if statement. This is not ideal becuase we would rather not have any reference to the CapSense code so that this project can be completely customized to our project and not have any extra and unecessary code. 

Overall, we feel like the peripheral side is pretty close to being complete. This means that we are hoping to begin writing the central role that will eventually handle all of the accelerometer data that is being sent. Where is a good place to start this? We have been using the CySmart PC app to do all of the central role so far but eventually want to be able to simply use two PSoC 4 BLE chips as client and server. 

It seems as though the central device needs to 1) Connect to the peripheral device, 2) Read its attributes and/or discover its services 3) enable notifications, and then process the data as it comes in. We have opened up the central_ias example project but it appears to be pretty different than what we will eventually need. Any initial thoughts on this would be much appreciated. 

I will attach the current version of our project so you can look at the if statements that aren't executing in main.c. 

Thanks again for the helpful responses. 


Log in to post new comments.