Hi guys,
I have developed an app to read data from some sensors and notify the central with a frequency of 100Hz. It seems to work but I would like to share my approach and let me know of any improvements
I have two application timers. The first one expires every 200us and sample some pressure sensors and the second expires every every 10ms. The 10ms timer calls the read_sensors(), where I sample the IMU (IMU_read()), increment a packet counter (packet_increment()), buffer the sensors data (my_sensors_buffer()) and attempt to transmit (data_tx())
void read_sensors(void *p_context) {
ret_code_t err_code;
UNUSED_PARAMETER(p_context);
// Read the IMU
IMU_read(&sampling);
// Increment the packet counter
packet_increment(&sampling,false);
logger(&sampling);
// Buffer that payload
my_sensors_buffer(&sampling);
// if the buffer is not empty Tx data
if (!nrf_queue_is_empty(&m_sensor_data_queue)) {
data_tx(&sampling);
}
}
I buffer the data using the queue library
void my_sensors_buffer(struct s_sampling *sampling) {
ret_code_t err_code;
uint16_t queue_available_space;
int8_t *payload = (int8_t *)sampling;
// Buffer the payload (32bytes)
for (uint16_t i = 0; i < sampling->size_of_payload; i++) {
err_code = nrf_queue_push(&m_sensor_data_queue, payload++);
APP_ERROR_CHECK(err_code);
}
}
When I call the data_tx() I try to transmit all the queued data while (err_code == NRF_SUCCESS)
The ble_cus_custom_value_update() gives a call to sd_ble_gatts_hvx()
void data_tx(struct s_sampling *sampling) {
ret_code_t err_code;
uint16_t queue_available_space;
err_code = NRF_SUCCESS;
while (err_code == NRF_SUCCESS) {
if (!sampling->busy) {
err_code = nrf_queue_read(&m_sensor_data_queue, sampling->tx_buffer, sampling->size_of_payload); // QUEUE_SIZE <= queue_utilization_get(p_queue)
APP_ERROR_CHECK(err_code);
}
err_code = ble_cus_custom_value_update(&m_cus, sampling);
if (err_code != NRF_ERROR_INVALID_STATE && err_code != BLE_ERROR_GATTS_SYS_ATTR_MISSING && err_code != NRF_ERROR_RESOURCES && err_code != NRF_ERROR_BUSY) { //
APP_ERROR_CHECK(err_code);
}
if (err_code == NRF_ERROR_RESOURCES) {
NRF_LOG_INFO("Error: %d ", err_code)
sampling->busy = true;
break;
}
sampling->busy = false;
if (nrf_queue_is_empty(&m_sensor_data_queue)) {
NRF_LOG_INFO("Queue is empty");
begin = app_timer_cnt_get(); // na - get the current ticks after just before notification (32bit long number)
NRF_LOG_INFO("Current ticks(empty queue) %d", begin)
break;
}
}
}
In case of NRF_ERROR_RESOURCES I wait for the BLE_GATTS_EVT_HVN_TX_COMPLETE event and call again the data_tx()
case BLE_GATTS_EVT_HVN_TX_COMPLETE:
packet_count = p_ble_evt->evt.gatts_evt.params.hvn_tx_complete.count;
NRF_LOG_INFO("BLE_GATTS_EVT_HVN_TX_COMPLETE");
NRF_LOG_INFO("Packet count: %d", packet_count);
on_tx_complete(&sampling);
break;
static void on_tx_complete(struct s_sampling *sampling) {
if (sampling->busy) { // if busy is true, there are still data in the buffer
data_tx(sampling);
}
}
This is the block diagram. A bit complicated :/
