Hi,
I have a DA14531 SmartBond Tiny Module. I modified the ble_app_peripheral example to read data from the uart using the following code:
void user_app_uart_read(void){ uart_receive(UART2, (uint8_t *)user_uart_data, sizeof(user_uart_data), UART_OP_INTR); user_receive_data_len = sizeof(user_uart_data); user_uart_data[user_receive_data_len] = 0; uart_timer_used = app_easy_timer(500,user_app_uart_read); return; }
and write it in ble notifications using this modified adc1 code from custom profile service
MSGID = CUSTS1_VAL_WRITE_IND // in user_peripheral.c triggers this handler
void app_adcval1_timer_cb_handler() { char data_buff[50] = ""; uint8_t data_len; sprintf((char *)data_buff,"%s",user_uart_data); data_len = strlen(data_buff); 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, data_len); req->conidx = 0; req->handle = SVC1_IDX_ADC_VAL_1_VAL; req->length = data_len; req->notification = true; memcpy(req->value, data_buff, data_len); ke_msg_send(req); if (ke_state_get(TASK_APP) == APP_CONNECTED) { // Set it once again until Stop command is received in Control Characteristic timer_used = app_easy_timer(APP_PERIPHERAL_CTRL_TIMER_DELAY, app_adcval1_timer_cb_handler); } }
I have three questions:
1. (Using Notification to read) If I write the data "abcdef" on uart, It is displayed in the characteristic correctly. But when I send a "xxxx" after that, the characteristic shows the value "xxxxef" where it replaces only the newer value. How do I modify or clear my buffer so that it displays the correct data.
2. If I use the Read Command on my phone using BLE Scanner App, No data is displayed. I understand that I am only using NTF, so data is only displayed then. How do I modify my code to show data with Read Command too?
3. When I enable Write Permission (Write_Command)to this characteristic and I write a value using my phone to this characteristic, Is there any way I can differentiate that this value came from BLE Peer instead of UART. Because my requirement is like this: Read data from uart and send it to characteristic so it can be viewed on phone. Writing data to this characteristic should be written on uart.
SDK Used: 6.0.14.1114
Any help would be appreciated.
- Abishekh
Hi Abishekh,
Thank you for your online forum question and your interest in our BLE products.
1. From the code shared it seems that you are using function uart_receive for the reception of the uart data…
Please check the uart example of our SDK6 that can be found under
...\DA145xx_SDK\6.0.16.1144\projects\target_apps\peripheral_examples\uart
and in particular files uart_receive_examples.c…
1. From the code shared it seems that you are using function uart_receive for the reception of the uart data. The buffer which stores the data (user_uart_data) is overwritten with new uart data but its previous value is never cleared, so if the length of the previous data written is bigger than the current one, some of the previous characters are passed on the new notification as well. A workaround for this would be to clear the user_uart_data buffer in user_app_uart_read before receiving new data and updating the notification value not periodically, but only when new data have been written to the UART.
2. You can add the read functionality to the characteristic using the following steps as a reference:
Taking the ble_app_peripheral example you can follow the steps below to read the value of the adc characteristic:
a. In file user_custs1_def.h change the database initialization of the SVC1_IDX_ADC_VAL_1_VAL field to:
// ADC Value 1 Characteristic Value [SVC1_IDX_ADC_VAL_1_VAL] = {SVC1_ADC_VAL_1_UUID_128, ATT_UUID_128_LEN, PERM(RD, ENABLE) | PERM(NTF, ENABLE), PERM(RI, ENABLE)|DEF_SVC1_ADC_VAL_1_CHAR_LEN, 0, NULL},
this will enable the read indication feature for the characteristic.
b. In file user_peripheral.c add the following to the case CUSTS1_VALUE_REQ_IND
case CUSTS1_VALUE_REQ_IND: { struct custs1_value_req_ind const *msg_param = (struct custs1_value_req_ind const *) param; switch (msg_param->att_idx) { case SVC1_IDX_ADC_VAL_1_VAL: { user_svc1_read_adc_value_handler(msgid, msg_param, dest_id, src_id); } break;
this will invoke a user created handler for the read request of the adc value.
c. In file user_custs1_impl.c add the implementation of the handler function
void user_svc1_read_adc_value_handler( ke_msg_id_t const msgid, struct custs1_value_req_ind const *param, ke_task_id_t const dest_id, ke_task_id_t const src_id) { // As an example we increase value by five adc_value += 5; struct custs1_value_req_rsp *rsp = KE_MSG_ALLOC_DYN(CUSTS1_VALUE_REQ_RSP, prf_get_task_from_id(TASK_ID_CUSTS1), TASK_APP, custs1_value_req_rsp, DEF_SVC1_ADC_VAL_1_CHAR_LEN); // Provide the connection index. rsp->conidx = app_env[param->conidx].conidx; // Provide the attribute index. rsp->att_idx = param->att_idx; // Force current length to zero. rsp->length = sizeof(adc_value); // Provide the ATT error code. rsp->status = ATT_ERR_NO_ERROR; // Copy value memcpy(&rsp->value, &adc_value, rsp->length); // Send message ke_msg_send(rsp); }
3. When writing to a characteristic as a BLE peer, the case CUSTS1_VAL_WRITE_IND will be invoked in user_catch_rest_hndl in file user_peripheral.c. You can create a new subcase for when the characteristic in question has been written e.g. SVC1_IDX_ADC_VAL_1_VAL
case CUSTS1_VAL_WRITE_IND: { struct custs1_val_write_ind const *msg_param = (struct custs1_val_write_ind const *)(param); switch (msg_param->handle) { case SVC1_IDX_ADC_VAL_1_VAL: user_svc1_adc_wr_ind_handler(msgid, msg_param, dest_id, src_id); break;
Now user defined function user_svc1_adc_wr_ind_handler will be invoked when data is written by a BLE peer. You can add code inside user_svc1_adc_wr_ind_handler which will take the value written by the BLE peer and print it in the UART (similar to how user_svc1_led_wr_ind_handler uses the value written by the BLE peer to turn the LED on/off).
Best regards, AA_Dialog
Is there a way to detect when the uart buffer has data or empty?
and in particular files uart_receive_examples.c and uart_loopback_examples.c which contain functions that showcase different ways for receiving data from the UART. Note that you can use the uart_register_rx_cb api to register a callback function for the UART receive event when you are using UART in UART_OP_INTR mode. As an example the uart_loopback_interrupt_example registers function uart_read_cb for the receive event. After that it calls uart_receive with a length of one byte. When this byte is received uart_read_cb is invoked which in turns adds this byte to the ring buffer and calls uart_receive again, waiting for the next character reception from UART. You can use these examples as a reference to help you implement UART handling for your application.
How many hours does the connectivity lasts??
My Bluetooth application is created with the help of Ble_app_peripheral example. My Ble connection with the app gets disconnected for every 18hrs12min. What will be the issue??
Hi Surya,
There is no limit. Can you please run it with the debugger attached?
Additionally, I sniffer log would be very helpful to understand the root cause.
Regards,
PM_Renesas
Tq PM_Renesas
I have sorted out the issue. The problem was on the application side. I paired the BLE with the system using python script. The script is running for more than 24hrs from yesterday and it is working fine.
Glad that you solved it and thanks for the info.
Please raise a new forum ticket if you have follow up questions!