PSoC 4 BLE Some hints needed to read out data

Tip / Sign in to post questions, reply, level up, and achieve exciting badges. Know more

cross mob
lock attach
Attachments are accessible only for community members.
Anonymous
Not applicable

Hello together,

   

I would appreciate some advice from you. I'm trying to program the chip on the board to function as a central device. The goal is to automatically connect with certain devices and read out the data they send (e.g. beurer M85 blood pressure device). I was able to connect to the device but I don't have any idea on how to go on from here. Also when I use the CySmart app with the USB dongle all information I get is the name and type (see screenshot). Does this come from my incompetence in using the software or ist the device just sending this data.

   

I hope you can help me. 

   

 

   

Thanks a lot beforehand 

   

 

   

with kind regards

   

 

   

Lars

0 Likes
1 Solution
Anonymous
Not applicable

@Lars,

   

As Matt suggested, use the CySmart PC Tool to Discover All Attributes of the M85 peripheral device and observe the list. This will give you the following information:

   

1) Number of Services/Characteristics supported by the M85 device

   

2) Attribute Handles of all those Services/characteristics

   

3) The Characteristic for Blood pressure data transfer. Assuming they follow the standard BLE SIG definition, the Characteristics should be as defined at https://developer.bluetooth.org/gatt/services/Pages/ServiceViewer.aspx?u=org.bluetooth.service.blood... 

   

4) Note the Attribute handle and type of Data transfer mechanism it supports (it should be Indicate).

   

5) If by chance they support a custom characteristic to send the Blood Pressure data, then you can find the attribute handle, type of data transfer and size of data transfer from the same list.

   

Now once you have got the information for the device you want to connect to, then it is simple from there. Use the following project for reference:

   

https://github.com/cypresssemiconductorco/PSoC-4-BLE/tree/master/100_Projects_in_100_Days/Day006_Cen...

   

1) To autoconnect to the M85 device, Look for a particular data in Advertising or Scan Response packet that you feel is unique to the M85 device. I see in Advertisement Packet (the image you uploaded, screen 1) that they send 16-bit UUID and the Name of the device. You can use these two data points to filter the desired device while you are scanning from your PSoC 4 BLE. the Scan report comes as an event 'CYBLE_EVT_GAPC_SCAN_PROGRESS_RESULT' in stack event handler.

   

2) Initiate a connection once you receive a ADV packet with above information.

   

3) Once connected, enable Indication on characteristic which has Blood Pressure Data. To enable Indication, you have to write a 16-bit value of 0x0002 to the CCCD of associated Blood Pressure characteristic. The attribute handle for CCCD is usually +1 of the attribute handle of the characterisitc itself. Use the API CyBle_GattcWriteCharacteristicDescriptors() for this case.

   

4) You should now start receving the data as part of event 'CYBLE_EVT_GATTC_HANDLE_VALUE_IND'

   

You can refer following two app notes to get a better understanding of how BLE events are handled:

   

http://www.cypress.com/?rID=102504     AN91267 - Getting Started with PSoC® 4 BLE

   

http://www.cypress.com/?rID=110107     AN91184 - PSoC 4 BLE - Designing BLE Applications

   

http://www.cypress.com/?rID=109900     AN91162 - Creating a BLE Custom Profile

View solution in original post

0 Likes
9 Replies
Anonymous
Not applicable

The screenshots you attached only show the advertised information of the M85.  That is the information it sends out to tell other BT devices that it is there.  If you haven't done it, select that M85 in the list and click the "Connect" button.  After the connection has completed, you will most likely want to click the "Discover All Attributes" button.  This will request information about what data interactions the M85 has available.  Some of those attributes will contain the sensor information you are probably looking for.

   

Best regards,

   

Matt

0 Likes
Anonymous
Not applicable

@Lars,

   

As Matt suggested, use the CySmart PC Tool to Discover All Attributes of the M85 peripheral device and observe the list. This will give you the following information:

   

1) Number of Services/Characteristics supported by the M85 device

   

2) Attribute Handles of all those Services/characteristics

   

3) The Characteristic for Blood pressure data transfer. Assuming they follow the standard BLE SIG definition, the Characteristics should be as defined at https://developer.bluetooth.org/gatt/services/Pages/ServiceViewer.aspx?u=org.bluetooth.service.blood... 

   

4) Note the Attribute handle and type of Data transfer mechanism it supports (it should be Indicate).

   

5) If by chance they support a custom characteristic to send the Blood Pressure data, then you can find the attribute handle, type of data transfer and size of data transfer from the same list.

   

Now once you have got the information for the device you want to connect to, then it is simple from there. Use the following project for reference:

   

https://github.com/cypresssemiconductorco/PSoC-4-BLE/tree/master/100_Projects_in_100_Days/Day006_Cen...

   

1) To autoconnect to the M85 device, Look for a particular data in Advertising or Scan Response packet that you feel is unique to the M85 device. I see in Advertisement Packet (the image you uploaded, screen 1) that they send 16-bit UUID and the Name of the device. You can use these two data points to filter the desired device while you are scanning from your PSoC 4 BLE. the Scan report comes as an event 'CYBLE_EVT_GAPC_SCAN_PROGRESS_RESULT' in stack event handler.

   

2) Initiate a connection once you receive a ADV packet with above information.

   

3) Once connected, enable Indication on characteristic which has Blood Pressure Data. To enable Indication, you have to write a 16-bit value of 0x0002 to the CCCD of associated Blood Pressure characteristic. The attribute handle for CCCD is usually +1 of the attribute handle of the characterisitc itself. Use the API CyBle_GattcWriteCharacteristicDescriptors() for this case.

   

4) You should now start receving the data as part of event 'CYBLE_EVT_GATTC_HANDLE_VALUE_IND'

   

You can refer following two app notes to get a better understanding of how BLE events are handled:

   

http://www.cypress.com/?rID=102504     AN91267 - Getting Started with PSoC® 4 BLE

   

http://www.cypress.com/?rID=110107     AN91184 - PSoC 4 BLE - Designing BLE Applications

   

http://www.cypress.com/?rID=109900     AN91162 - Creating a BLE Custom Profile

0 Likes
Anonymous
Not applicable

Hello,

   

at first thanks you for your replies.

   

I tried what Matt suggested but an error occurred. When I connect the BM85 with the CySmart App the device stops sending data and shutdown the BLE functionality. So I am not able to discover any attributes. I am barely able to click the button but then the device stops. Therefore my idea was to read the data with a program and the UART communication.

   

This is my current code:

   

   

#include <project.h>
#include <stdio.h>
#include <common.h>

   


/***************************************
*        Function Prototypes
***************************************/
void StackEventHandler(uint32 event, void* eventParam);

   

/***************************************
*        Global Variables
***************************************/

   


void StackEventHandler(uint32 event, void* eventParam) {
    
    CYBLE_GAPC_ADV_REPORT_T scanReport;
    uint8 isConnected = 0;
    CYBLE_API_RESULT_T apiResult;
    
    switch(event) {
        
        case CYBLE_EVT_STACK_ON:
            // Bluetooth activated, if everything is okay, start scanning.
            printf("Bluetooth ON\r\n");
            if (CYBLE_ERROR_OK==CyBle_GapcStartScan(CYBLE_SCANNING_SLOW)) {
                printf("Started to Scan\r\n");
            }
            break;

   

        case  CYBLE_EVT_GAPC_SCAN_START_STOP:
            /*if (!isConnected && CyBle_GetState() == CYBLE_STATE_DISCONNECTED) {
                if (CyBle_GapcStartScan(CYBLE_SCANNING_SLOW) == CYBLE_ERROR_OK) {
                    printf("Started to scan\r\n");
                }
            }*/
        break;
            
        case CYBLE_EVT_GAPC_SCAN_PROGRESS_RESULT:
            scanReport = *(CYBLE_GAPC_ADV_REPORT_T *) eventParam;
            
            printf("Found a device. The device sends the following data:\r\n");
            printf("%s\r\n", scanReport.data);
            
            if (strstr((const char *) scanReport.data, "Beurer BM85") != NULL) {
                printf("This is the correct device. I'm trying to connect.\r\n");
                
                // Stop the scan to connect to the device.
                CyBle_GapcStopScan();
                
                // Check if the device is already connected. If not then connect to the device.
                if (isConnected == 0) {
                    
                    apiResult = CyBle_GapcConnectDevice((CYBLE_GAP_BD_ADDR_T *) scanReport.peerBdAddr);
                    
                    if (apiResult == CYBLE_ERROR_OK) {
                        printf("A connection request has been sent to the device.\r\n");
                    } else {
                        printf("A connection request could not been sent to the device.\r\n");
                    }
                } else {
                    printf("The device is already connected.\r\n");
                }
            } else {
                printf("I'm sorry but this is not the device I am looking for.\r\n");
            }
        break;
            
        case CYBLE_EVT_GAP_DEVICE_CONNECTED:
            printf("The device is connected.\r\n");
            isConnected = 1;
        break;
            
        case CYBLE_EVT_GAP_DEVICE_DISCONNECTED:
            // The device was disconnected, restart scanning.
            printf("The device is disconnected.\r\n");
            if (CYBLE_ERROR_OK == CyBle_GapcStartScan(CYBLE_SCANNING_SLOW)) {
                printf("Started to Scan\r\n");
            }
        break;
            
        default:
        break;
    }
}

   


void InitializeSystem(void) {
    
    // Enable Global Interrupt Mask
    CyGlobalIntEnable;
    
    // Start BLE stack and register the event callback function.
    CyBle_Start(StackEventHandler);
    
    // Start the UART communication component.
    UART_Start();
}

   


int main() {
   
    // Initialize the system.
    InitializeSystem();
    
    /*Infinite Loop*/
    for (;;) {
        
        // Process the BLE events to generate events in the callback function.
        CyBle_ProcessEvents();
    }   
}

   

   

 

   

But here I am not able to connect to the device. If I let the program print the apiResult with printf("%u", apiResult) it says 262. I tried to ask for the error code with all possibilities that can happen but nothing happened. This error number seems to be not documented in the API documentation. 

   

Is this attempt even possible or do I need to discover the attributes with the CySmart app at first?

   

Best Regards

   

Lars 

0 Likes
Anonymous
Not applicable

 I see that you are calling various APIs under the ' CYBLE_EVT_GAPC_SCAN_PROGRESS_RESULT' event but you are not calling CyBle_ProcessEvents() so that they get registered. You should be calling this API often between BLE activities to ensure all events are processed.

   

Inside the event, scan for your device and call the CyBle_GapcStopScan() API, along with setting a flag.

   

Use this flag in the for(;;) of main() function to issue a CyBle_GapcConnectDevice() API, something like below:

   

/*Infinite Loop*/
    for (;;) {
        
        // Process the BLE events to generate events in the callback function.
        CyBle_ProcessEvents();

   

if(connectRequestSet)

   

{

   

connectRequestSet = 0;

   

apiResult = CyBle_GapcConnectDevice((CYBLE_GAP_BD_ADDR_T *) scanReport.peerBdAddr);

   

                       if (apiResult == CYBLE_ERROR_OK) {
                        printf("A connection request has been sent to the device.\r\n");
                    } else {
                        printf("A connection request could not been sent to the device.\r\n");
                    }

   

}

   

    }   

   

With respect to other issue where you stated that "When I connect the BM85 with the CySmart App the device stops sending data and shutdown the BLE functionality.", it could be easily a M85 implementation. I have seen few of these peripheral devices that only works with a particular App, such as Kensington Proximo keychain and App, where you need to access one particular characteristic within a given time after connection to ensure that you are the write App to talk to. If you fail to access/write that characteristic, then the device would know that you are not correct App to be connected to and will issue a disconnect. If you have a BLE sniffer and the correct App for M85, you can quickly do this check. 

lock attach
Attachments are accessible only for community members.
Anonymous
Not applicable

Hey,

   

thank you very much. That worked for me. I can now connect to a BLE device. I managed to get my hands on another device. This time it's the beurer BF800-F, a balance. Here I can discover all the attributes with the CySmart app. But for my purpose I need to discover all things with the code. So my plan is to use CyBle_GattcStartDiscovery. But the discovery complete event doesn't occure. Am I missing something that I need to activate or implement to use this function. If this is the wrong way maybe you can provide me an example on how to read out the data from the balance. I attached a screenshot from the discovery with the CySmart app. At first I want to read out the manufacture specific data to register the balance to my system and after that I want to use the balance and read out the measurement data. I hope I don't bother you to much with my questions. This is the first time ever that I need to program a chip and working with bluetooth in general.

   

My updated code:

   

#include <project.h>
#include <stdio.h>
#include <common.h>

   


/***************************************
*        Function Prototypes
***************************************/
void StackEventHandler(uint32 event, void* eventParam);

   

/***************************************
*        Global Variables
***************************************/
CYBLE_GAP_BD_ADDR_T device;
uint8 isDevice = 0;
uint8 isConnected = 0;
CYBLE_API_RESULT_T apiResult;
CYBLE_GAPC_ADV_REPORT_T scanReport;
uint8 connectRequestSet = 0;
CYBLE_CONN_HANDLE_T connHandle;
CYBLE_GATTC_READ_BY_GRP_RSP_PARAM_T readByGroupResponse;

   

void StackEventHandler(uint32 event, void* eventParam) {
    
    switch(event) {
        
        case CYBLE_EVT_STACK_ON:
            // Bluetooth activated, if everything is okay, start scanning.
            printf("Bluetooth ON\r\n");
            if (CYBLE_ERROR_OK==CyBle_GapcStartScan(CYBLE_SCANNING_SLOW)) {
                printf("Started to Scan\r\n");
            }
            break;

   

        case  CYBLE_EVT_GAPC_SCAN_START_STOP:
            /*if (!isConnected && CyBle_GetState() == CYBLE_STATE_DISCONNECTED) {
                if (CyBle_GapcStartScan(CYBLE_SCANNING_SLOW) == CYBLE_ERROR_OK) {
                    printf("Started to scan\r\n");
                }
            }*/
        break;
            
        case CYBLE_EVT_GAPC_SCAN_PROGRESS_RESULT:
            scanReport = *(CYBLE_GAPC_ADV_REPORT_T *) eventParam;
            
            printf("Found a device. The device sends the following data:\r\n");
            printf("%s\r\n", scanReport.data);
            
            if (strstr((const char *) scanReport.data, "Beurer BF800") != NULL) {
                
                device.bdAddr[5u] = scanReport.peerBdAddr[5u];
                device.bdAddr[4u] = scanReport.peerBdAddr[4u];
                device.bdAddr[3u] = scanReport.peerBdAddr[3u];
                device.bdAddr[2u] = scanReport.peerBdAddr[2u];
                device.bdAddr[1u] = scanReport.peerBdAddr[1u];
                device.bdAddr[0u] = scanReport.peerBdAddr[0u];
                
                CyBle_GapcStopScan();
                connectRequestSet = 1;
                printf("This is the correct device. I'm trying to connect.\r\n");
                
            } else {
                printf("I'm sorry but this is not the device I am looking for.\r\n");
            }
        break;
            
        case CYBLE_EVT_GAP_DEVICE_CONNECTED:
            printf("The device is connected.\r\n");
            isConnected = 1;
            connHandle = *(CYBLE_CONN_HANDLE_T *) eventParam;
        break;
            
        case CYBLE_EVT_GAP_DEVICE_DISCONNECTED:
            // The device was disconnected, restart scanning.
            printf("The device is disconnected.\r\n");
            if (CYBLE_ERROR_OK == CyBle_GapcStartScan(CYBLE_SCANNING_SLOW)) {
                printf("Started to Scan\r\n");
            }
        break;
            
        case CYBLE_EVT_GATTC_HANDLE_VALUE_IND:
            scanReport = *(CYBLE_GAPC_ADV_REPORT_T *) eventParam;
            
            printf("Data:\r\n");
            printf("%s", scanReport.data);
        break;            
            
        case CYBLE_EVT_GATTC_DISCOVERY_COMPLETE:
            printf("Discovery complete.\r\n");
            printf("Discovered services: \r\n");
            
            uint8 i;
            for(i=0u; i < CYBLE_SRVI_COUNT; i++) {
                if(cyBle_serverInfo.uuid == CYBLE_UUID_DEVICE_INFO_SERVICE) {
                    if(cyBle_serverInfo.range.startHandle < cyBle_serverInfo.range.endHandle) {
                        printf("Peer device supports Device Information Service \r\n");
                    } else {
                        printf("Peer device doesn't supports Device Information Service \r\n");
                    }
                }
            }                
        break; 
            
        default:
        break;
    }
}

   


void InitializeSystem(void) {
    
    // Enable Global Interrupt Mask
    CyGlobalIntEnable;
    
    // Start BLE stack and register the event callback function.
    CyBle_Start(StackEventHandler);
    
    // Start the UART communication component.
    UART_Start();
}

   


int main() {
   
    // Initialize the system.
    InitializeSystem();
    
    /*Infinite Loop*/
    for (;;) {
        
        // Process the BLE events to generate events in the callback function.
        CyBle_ProcessEvents();
        
        if (connectRequestSet) {
            connectRequestSet = 0;
            
            apiResult = CyBle_GapcConnectDevice(&device);
            if (apiResult == CYBLE_ERROR_OK) {
                printf("A connection request has been sent to the device.\r\n");
            } else {
                printf("A connection request could not been sent to the device.\r\n");
            }
        }
        
        if (isConnected) {
            CyBle_GattcStartDiscovery(connHandle);
            isConnected = 0;
        }
    }   
}

   

 

   

Best Regards

   

 

   

Lars

0 Likes
Bob_Marlowe
Level 10
Level 10
First like given 50 questions asked 10 questions asked

@Lars

   

Avoid posting code here, it is takes too much time to go through it without the help of the IDE. When posting a complete project we can look at all of your settings, component and your code (and believe me you can make errors in configuration...)

   

 To do so, use
Creator->File->Create Workspace Bundle (minimal)
and attach the resulting file.

   

 

   

Bob

   

PS: Where in Germany are you located? I live near Bremen

0 Likes
lock attach
Attachments are accessible only for community members.
Anonymous
Not applicable

Hi,

   

I did compress it. I am located near Berlin.

   

Lars

0 Likes
Anonymous
Not applicable

Hey guys,

   

I have another question. Until now I used the Observer Project from the 100 Projects as the basic project. Now I created a new one to clean the code a bit up. But when I want to use the printf function with the UART SCB mode v3.0 nothing happens and the application stopped. I used the same common.c with the _write function. Do I need to implement some other things. Google wasn't helpful on this topic.

   

 

   

Thanks for your great help

   

 

   

best regards

   

 

   

Lars

0 Likes
Bob_Marlowe
Level 10
Level 10
First like given 50 questions asked 10 questions asked

There is a nice function in Creator that allows for searching the entire workspace of a project (your Observer) for a string (printf) which reveals a file named "common.c" containing the connection between the UART component and the internals used be printf().

   

 

   

Bob

0 Likes