Multiple characters from UART to BLE notify characteristics

⚠️
Hi there.. thanks for coming to the forums. Exciting news! we’re now in the process of moving to our new forum platform that will offer better functionality and is contained within the main Dialog website. All posts and accounts have been migrated. We’re now accepting traffic on the new forum only - please POST any new threads at https://www.dialog-semiconductor.com/support . We’ll be fixing bugs / optimising the searching and tagging over the coming days.
10 posts / 0 new
Last post
julienr
Offline
Last seen: 4 months 3 weeks ago
Joined: 2020-10-09 12:32
Multiple characters from UART to BLE notify characteristics

Hi,

I am trying to send characters from UART to a BLE notify characteristics

Sending a single character at a time works correctly

But I have a problem when sending multiple characters at a time:

- The notify characteristic is updated the correct number of times (for example when I send 5 characters through UART the notify characteristic is updated 5 times)

- But some of the characters are repeated (for example when I send "abcde" through UART the notify characteristic wil be updated with "aeeee" or "addde", "abcee"...)

- To make sure the characters are correctly received from UART I resend the received characters through UART, like an "echo" and the characters are always correct

 

I am working with the PRO development kit with DA14531 Tiny Module and Keil, I used the "ble_app_peripheral" example as base

Here is the code I am using:

const int READ_CHAR_COUNT = 1;

static char buffer[READ_CHAR_COUNT + 1];

volatile bool uart_receive_finished = false;
volatile uint16_t data_received_cnt = 0;

static uint8_t blebuf[1];


void uart_receive_intr_init(){
	
	uart_receive_finished = false;
	data_received_cnt = 0;
	buffer[0]=0;
	uart_register_rx_cb(UART1, uart_receive_cb);
	
	
	uart_receive(UART1, (uint8_t *) buffer, READ_CHAR_COUNT, UART_OP_INTR);
}

static void uart_receive_cb(uint16_t length)
{
    data_received_cnt = length;
    uart_receive_finished = true;
	
    // Put received byte in ring buffer
    buffer_put_byte(buffer[0]);

    uart_receive(UART1, (uint8_t *) buffer, READ_CHAR_COUNT, UART_OP_INTR);
}


arch_main_loop_callback_ret_t user_app_on_system_powered(void)
{     

	if (buffer_get_byte(&blebuf[0])!=-1)
	{

		struct custs1_val_ntf_ind_req *req = KE_MSG_ALLOC_DYN(CUSTS1_VAL_NTF_REQ, 
				prf_get_task_from_id(TASK_ID_CUSTS1),
				TASK_APP,custs1_val_ntf_ind_req,
				DEF_SVC1_LONG_VALUE_CHAR_LEN);


		static uint8_t sample      __SECTION_ZERO("retention_mem_area0");
		sample = blebuf[0];

		req->handle = SVC1_IDX_LONG_VALUE_VAL;
		req->length = DEF_SVC1_LONG_VALUE_CHAR_LEN;
		req->notification = true;
		memcpy(req->value,&sample, 1);

		ke_msg_send(req);

		uart_send(UART1, &sample, 1,UART_OP_BLOCKING); // "echo" to UART to check characters

	}
	return KEEP_POWERED;
}





 

Thanks in advance

 

 

 

 

 

 

PM_Dialog
Offline
Last seen: 1 month 1 week ago
Staff
Joined: 2018-02-08 11:03
Hi julienr,

Hi julienr,

Thanks for your question online and for your interest in our BLE solutions.

The user_on_ble_powered() will be triggered once the BLE is active. I saw that you are sending 1 byte per time, so probably when the user_on_ble_powered() is triggered, the value on the blebuf[] is not updated yet. If you are interested in sending 5 bytes, why don’t you save them all in one buffer and then send them via notifications?

Please add a breakpoint in user_on_ble_powered() : what is the value of the blebuf[] once the callback is triggered?

From you post, if I understood correctly, you are interested in developing a data-pumping application. So, I would recommend also checking the Dialog Serial Port Service (DSPS) example – link is provided below :

https://www.dialog-semiconductor.com/products/dialog-serial-port-service-dsps

The Serial Port Service (SPS) emulates a serial cable communication. It provides a simple substitute for RS-232 connections, including the familiar software flow control logic via Bluetooth low energy.

The AT CodeLess can be also used for data-pumping applications :

https://www.dialog-semiconductor.com/products/smartbond-codeless-commands

Thanks, PM_Dialog

julienr
Offline
Last seen: 4 months 3 weeks ago
Joined: 2020-10-09 12:32
Hi,

Hi,

Thanks for your answer

For compatibility reasons I need to implement this UART to notify characteristics, later the next step would be to use the DSPS profile

 

I don't know how many characters are to send so I store them in a ring buffer and send them one at a time each time user_on_ble_powered() is triggered

With a breakpoint in user_on_ble_powered() I can see that the buffer is correctly updated, I could also see that with the uart_send() at the end of user_on_ble_powered() all the correct characters are sent

 

To send notifications i use ke_msg_send(req), before sending a new notification is there a way to know if the previous on was treated or a queue mechanism ?

 

Thanks in advance

 

 

 

 

 

 

PM_Dialog
Offline
Last seen: 1 month 1 week ago
Staff
Joined: 2018-02-08 11:03
Hi julienr,

Hi julienr,

The system will send a BLE notification, once the user_app_on_system_powered() is triggered. The value will be sent to the characteristic, is the “sample” variable which is 1byte. So, every timer, the user_app_on_system_powered() is triggered, the “sample” value will be either updated or not, because is a new character is not received over UART, the “sample” will have the previous value.

For example, if the user_app_on_system_powered() hits before sending a new character over UART, the blebuf will have the previous value, so the characteristic will be updated with the previous value too!

If the blebuf is updated correctly, then the device will send this value over notifications.

>>To send notifications i use ke_msg_send(req), before sending a new notification is there a way to know if the previous on was treated or a queue mechanism ?

Apologies, but I can’t get this question. Could you please clarify it?

The DSPS is using a circular buffer to send the incoming data over UART. It’s not a straight-forward implementation, so I assume it would be much easier to use or to check the DSPS application code.

Thanks, PM_Dialog

julienr
Offline
Last seen: 4 months 3 weeks ago
Joined: 2020-10-09 12:32
Hi,

Hi,

 

Thanks for your answer

 

When user_app_on_system_powered() is triggered I check if there is a character in ring buffer :

if (buffer_get_byte(&blebuf[0])!=-1)

 

Only if it is the case I send the character value via notification :

struct custs1_val_ntf_ind_req *req = KE_MSG_ALLOC_DYN(CUSTS1_VAL_NTF_REQ, 
				prf_get_task_from_id(TASK_ID_CUSTS1),
				TASK_APP,custs1_val_ntf_ind_req,
				DEF_SVC1_LONG_VALUE_CHAR_LEN);


		static uint8_t sample      __SECTION_ZERO("retention_mem_area0");
		sample = blebuf[0];

		req->handle = SVC1_IDX_LONG_VALUE_VAL;
		req->length = DEF_SVC1_LONG_VALUE_CHAR_LEN;
		req->notification = true;
		memcpy(req->value,&sample, 1);

		ke_msg_send(req);

 

and just after that I send it back via UART (for test purpose) :

uart_send(UART1, &sample, 1,UART_OP_BLOCKING);

 

What I don't understand is why the same "sample" is always correct via UART and not via notifications

 

Thanks in advance

 

 

 

 

 

 

PM_Dialog
Offline
Last seen: 1 month 1 week ago
Staff
Joined: 2018-02-08 11:03
Hi julienr,

Hi julienr,

Can you please add a break-point in memcpy(req->value,&sample, 1); ?

Run your project, so every time that the user_app_on_system_powered() is triggered, then the DA14531 will be sending the “sample” via notifications.

What is the value that is mem-copied?

Probably the user_app_on_system_powered() has been ran before the “value” has been updated.

If the “sample” has the correct value, then the system will send this value over notifications.

Did you check the DSPS project? Additionally, are you using extended sleep mode?

If yes, when in sleep mode, the device will sleep between intervals (advertising or connection). All the peripheral blocks, including UART are powered off, so it’s not possible to have UART activity in sleep. The DSPS is using HW Flow Control for this.

Thanks. PM_Dialog

julienr
Offline
Last seen: 4 months 3 weeks ago
Joined: 2020-10-09 12:32
Hi,

Hi,

Thanks for your answer

When I put a breakpoint on "memcpy(req->value,&sample, 1);" I can see that each time "sample" has the correct value

 

Concerning the sleep mode I am using in user_config.h :

static const sleep_state_t app_default_sleep_mode = ARCH_SLEEP_OFF;

 

Thanks and best regards

 

 

 

 

 

 

PM_Dialog
Offline
Last seen: 1 month 1 week ago
Staff
Joined: 2018-02-08 11:03
Hi julienr,

Hi julienr,

If the “sample” has the correct value eac time the user_app_on_system_powered(), then the application should send the correct value via notifications. Do you have a BLE sniffer to check what is happening over the air?

Thanks, PM_Dialog

julienr
Offline
Last seen: 4 months 3 weeks ago
Joined: 2020-10-09 12:32
Hi,

Hi,

 

Thanks for your answer

To test the notifications I use the Lightblue App on Android, do you think the problem could be on the app side ?

I will try to get a sniffer the next days

Thanks and best regards

 

 

 

 

 

 

PM_Dialog
Offline
Last seen: 1 month 1 week ago
Staff
Joined: 2018-02-08 11:03
Hi julienr,

Hi julienr,

Apologies for the delay. Not sure if the problem is related to the app side. As mentioned before, if the “sample” has the correct value, then the deice should sent the correct data over notification to the app.

Thanks, PM_Dialog