Hello,
I'm currently using the nRF52840 DK and i need some help.
On the other hand, i have BLE ela identifiers/sensors : elainnovation.com/bluetooth-low-energy.html
My code is already handling nRF52840 DK (the client) and BLE ela Sensor (the server) connection AND NUS discovering as you can see below
Now i need to write the command "L" in the Rx client characteristic to receive data (temperature for example) from the BLE sensor.
The problem is, whatever i'm sending with ble_nus_c_string_send function, it leads to a BLE_GAP_EVT_DISCONNECTED whereas I should get data thanks to BLE_GATTC_EVT_HVX events and on_hvx() function.
I've already tried to get temp data with nrf toolbox and UART tool and it works perfectly just by connecting to the sensor and sending L when I enable notifications by setting TX BLE sensor characteristic.
If I do not set TX BLE sensor characteristic via UART tool, it also leads to a disconnection. So i though that was the problem in my code too but i'm using ble_nus_c_tx_notif_enable() so the BLE server should be able to receive RX commands when i'm using ble_nus_c_string_send() function.
Here is my main.c
/***************************************************************************************/ /* * beacon_scanner * Created by Manuel Montenegro, Sep 7, 2018. * * This is a Bluetooth 5 scanner. This code reads every advertisement from beacons * and sends its data through serial port. * * This code has been developed for Nordic Semiconductor nRF52840 PDK. */ /***************************************************************************************/ #include <stdint.h> #include <stdio.h> #include <string.h> #include "nordic_common.h" #include "nrf_sdm.h" #include "ble.h" #include "ble_hci.h" #include "ble_nus_c.h" // change 6 //#include "app_uart.h" // change uart //#include "ble_nus.h" #include "ble_db_discovery.h" #include "ble_srv_common.h" #include "nrf_sdh.h" #include "nrf_sdh_ble.h" #include "nrf_sdh_soc.h" #include "nrf_pwr_mgmt.h" #include "app_util.h" #include "app_error.h" #include "ble_dis_c.h" #include "ble_rscs_c.h" #include "app_util.h" #include "app_timer.h" #include "bsp_btn_ble.h" #include "peer_manager.h" #include "peer_manager_handler.h" #include "fds.h" #include "nrf_fstorage.h" #include "ble_conn_state.h" #include "nrf_ble_gatt.h" #include "nrf_pwr_mgmt.h" #include "nrf_ble_scan.h" #include "nrf_log.h" #include "nrf_log_ctrl.h" #include "nrf_log_default_backends.h" #define APP_BLE_CONN_CFG_TAG 1 /**< Tag that identifies the BLE configuration of the SoftDevice. */ #define APP_BLE_OBSERVER_PRIO 3 /**< BLE observer priority of the application. There is no need to modify this value. */ #define APP_SOC_OBSERVER_PRIO 1 /**< SoC observer priority of the application. There is no need to modify this value. */ #define SCAN_INTERVAL 0x0160 /**< Determines scan interval in units of 0.625 millisecond. */ #define SCAN_WINDOW 0x0160 /**< Determines scan window in units of 0.625 millisecond. */ #define SCAN_DURATION 0x0000 /**< Duration of the scanning in units of 10 milliseconds. If set to 0x0000, scanning continues until it is explicitly disabled. */ #define NRF_LOG_BACKEND_UART_BAUDRATE 15400960 NRF_BLE_SCAN_DEF(m_scan); /**< Scanning Module instance. */ // change 1 : 1 instance BLE_NUS_C_DEF(m_ble_nus_c); /**< BLE NUS service client instance. */ // change 0 db discovery BLE_DB_DISCOVERY_DEF(m_db_disc); /**< Database discovery module instance. */ static bool m_memory_access_in_progress; /**< Flag to keep track of ongoing operations on persistent memory. */ typedef struct{ uint16_t x; uint16_t y; uint16_t z; }angle_val; typedef struct { uint8_t * p_data; /**< Pointer to data. */ uint16_t data_len; /**< Length of data. */ uint8_t tag_type; uint16_t temp_val; uint8_t hum_val; uint16_t mag_val; uint16_t mov_val; angle_val ang_val; uint8_t * p_name; uint16_t name_len; uint8_t rssi; }data_t; data_t tag; const char * tag_ID = "000"; const char * tag_temp = "800"; const char * tag_TH = "900"; const char * tag_MAG = "C00"; const char * tag_MOV = "B00"; const char * tag_ANG = "B00"; static ble_gap_scan_params_t m_scan_param = /**< Scan parameters requested for scanning and connection. */ { .active = 0x00, .extended = 0x00, .interval = SCAN_INTERVAL, .window = SCAN_WINDOW, .timeout = 0x0000, // No timeout. .scan_phys = BLE_GAP_PHY_1MBPS, .filter_policy = BLE_GAP_SCAN_FP_ACCEPT_ALL, }; /// for connected mode static char const m_target_periph_name[] = "800CDE"; /**< Name of the device we try to connect to. This name is searched in the scan report data*/ static uint16_t m_conn_handle = BLE_CONN_HANDLE_INVALID; /**< Handle of the current connection. */ static const ble_gap_addr_t m_peer_addr = { .addr_type = BLE_GAP_ADDR_TYPE_PUBLIC, .addr = {0x00, 0x02, 0xA6, 0x81, 0x2A, 0x5F} }; /** * @brief Scan parameters requested for scanning and connection. */ /** * @brief Connection parameters requested for connection. */ static const ble_gap_conn_params_t m_connection_param = { .min_conn_interval = (uint16_t) NRF_BLE_SCAN_MIN_CONNECTION_INTERVAL, // Minimum connection .max_conn_interval = (uint16_t) NRF_BLE_SCAN_MAX_CONNECTION_INTERVAL, // Maximum connection .slave_latency = NRF_BLE_SCAN_SLAVE_LATENCY, // Slave latency .conn_sup_timeout = (uint16_t) NRF_BLE_SCAN_SUPERVISION_TIMEOUT // Supervision time-out }; uint8_t cpt_connect = 0; static void scan_start(const char* m_target_periph_name); ////////////////// //// HANDLERS //// ////////////////// /**@brief Function for handling BLE events. * * @param[in] p_ble_evt Bluetooth stack event. * @param[in] p_context Unused. */ static void ble_evt_handler(ble_evt_t const * p_ble_evt, void * p_context) { uint8_t name_offset = 8; uint8_t ui8_loop = 0; // used for loops ret_code_t err_code; switch (p_ble_evt->header.evt_id) { case BLE_GAP_EVT_ADV_REPORT: { tag.tag_type = m_scan.scan_buffer.p_data[2]; tag.rssi = p_ble_evt->evt.gap_evt.params.adv_report.rssi; // ELA if(tag.tag_type == 6){ // T&H -40 / +85 if(m_scan.scan_buffer.p_data[11] == 0x6F && m_scan.scan_buffer.p_data[12] == 0x2A) { name_offset = 16; tag.name_len = 6; tag.p_name = m_scan.scan_buffer.p_data + name_offset; tag.p_name[tag.name_len] = '\0'; tag.temp_val = ((uint16_t)m_scan.scan_buffer.p_data[8] << 8) | m_scan.scan_buffer.p_data[7]; tag.hum_val = m_scan.scan_buffer.p_data[13]; uint8_t ret = strncmp((const char *)tag.p_name, tag_TH,3); if( ret == 0 || (tag.temp_val > 0x0000 && tag.temp_val < 0x2134) || (tag.temp_val > 0xF05F && tag.temp_val < 0xFFFF)) { NRF_LOG_RAW_INFO ("[%X%s%04X%X]",tag.rssi, tag.p_name,tag.temp_val, tag.hum_val); } // Temp -40 / +85 } else if(m_scan.scan_buffer.p_data[5] == 0x6E && m_scan.scan_buffer.p_data[6] == 0x2A) { name_offset = 11; tag.name_len = 6; tag.temp_val = ((uint16_t)m_scan.scan_buffer.p_data[8] << 8) | m_scan.scan_buffer.p_data[7]; tag.p_name = m_scan.scan_buffer.p_data + name_offset; tag.p_name[tag.name_len] = '\0'; uint8_t ret = strncmp((const char *)tag.p_name, tag_temp,3); if( ret == 0 || (tag.temp_val > 0x0000 && tag.temp_val < 0x2134) || (tag.temp_val > 0xF05F && tag.temp_val < 0xFFFF)) { NRF_LOG_RAW_INFO ("[%X%s%04X]",tag.rssi, tag.p_name,tag.temp_val); } // MAG -40 / +85 or MOV } else if(m_scan.scan_buffer.p_data[5] == 0x06 && m_scan.scan_buffer.p_data[6] == 0x2A) { name_offset = 11; tag.name_len = 6; tag.mov_val = tag.mag_val = ((uint16_t)m_scan.scan_buffer.p_data[8] << 8) | m_scan.scan_buffer.p_data[7]; tag.p_name = m_scan.scan_buffer.p_data + name_offset; tag.p_name[tag.name_len] = '\0'; if( strncmp((const char *)tag.p_name, tag_MAG,3) == 0) { NRF_LOG_RAW_INFO ("[%X%s%04X]",tag.rssi, tag.p_name,tag.mag_val); }else if (strncmp((const char *)tag.p_name, tag_MOV,3) == 0) { NRF_LOG_RAW_INFO ("[%X%s%04X]",tag.rssi, tag.p_name,tag.mov_val); } // ANG } else if(m_scan.scan_buffer.p_data[5] == 0xA1 && m_scan.scan_buffer.p_data[6] == 0x2A) { name_offset = 15; tag.name_len = 6; tag.ang_val.x = ((uint16_t)m_scan.scan_buffer.p_data[8] << 8) | m_scan.scan_buffer.p_data[7]; tag.ang_val.y = ((uint16_t)m_scan.scan_buffer.p_data[10] << 8) | m_scan.scan_buffer.p_data[9]; tag.ang_val.z = ((uint16_t)m_scan.scan_buffer.p_data[12] << 8) | m_scan.scan_buffer.p_data[11]; tag.p_name = m_scan.scan_buffer.p_data + name_offset; tag.p_name[tag.name_len] = '\0'; if( strncmp((const char *)tag.p_name, tag_ANG,3) == 0) { NRF_LOG_RAW_INFO ("[%X%s%04X%04X%04X]",tag.rssi, tag.p_name,tag.ang_val.x,tag.ang_val.y,tag.ang_val.z); } } }else if (tag.tag_type == 4){ if(m_scan.scan_buffer.p_data[5] == 0x4C && m_scan.scan_buffer.p_data[6] == 0x00) { // ID name_offset = 9; tag.name_len = 16; tag.p_name = m_scan.scan_buffer.p_data + name_offset; //tag.p_name[tag.name_len] = '\0'; ui8_loop = 0; NRF_LOG_RAW_INFO ("[%X",tag.rssi); while(ui8_loop < tag.name_len) { NRF_LOG_RAW_INFO("%02x", tag.p_name[ui8_loop]); ui8_loop++; } NRF_LOG_RAW_INFO ("]"); } } break; } // connexion events case BLE_GAP_EVT_CONNECTED: NRF_LOG_RAW_INFO ("BLE_GAP_EVT_CONNECTED FIRED\r\n"); /*m_conn_handle = p_ble_evt->evt.gap_evt.conn_handle; // change 2 : sending "Notifications enabled" data to the BLE ela sensor uint8_t ui8_string [21]= {78, 111, 116, 105, 102, 105, 99, 97, 116, 105, 111, 110, 115, 32, 101, 110, 97, 98, 108, 101, 100}; err_code = ble_nus_c_string_send(&(m_ble_nus_c), ui8_string, 21); NRF_LOG_RAW_INFO ("error after ble_nus_c_string_send = %d\r\n", err_code); APP_ERROR_CHECK(err_code);*/ err_code = ble_nus_c_handles_assign(&m_ble_nus_c, p_ble_evt->evt.gap_evt.conn_handle, NULL); APP_ERROR_CHECK(err_code); err_code = ble_db_discovery_start(&m_db_disc, p_ble_evt->evt.gap_evt.conn_handle); APP_ERROR_CHECK(err_code); /*err_code = sd_ble_gap_disconnect(m_conn_handle, BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION); if(err_code != NRF_ERROR_INVALID_STATE) { APP_ERROR_CHECK(err_code); } scan_start(NULL);*/ break; case BLE_GAP_EVT_DISCONNECTED: NRF_LOG_RAW_INFO ("BLE_GAP_EVT_DISCONNECTED FIRED\r\n"); m_conn_handle = BLE_CONN_HANDLE_INVALID; scan_start(NULL); break; case BLE_GATTC_EVT_TIMEOUT: // Disconnect on GATT Client timeout event. err_code = sd_ble_gap_disconnect(p_ble_evt->evt.gattc_evt.conn_handle, BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION); APP_ERROR_CHECK(err_code); break; case BLE_GATTS_EVT_TIMEOUT: // Disconnect on GATT Server timeout event. err_code = sd_ble_gap_disconnect(p_ble_evt->evt.gatts_evt.conn_handle, BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION); APP_ERROR_CHECK(err_code); break; default: // No implementation needed. break; } } /** * @brief SoftDevice SoC event handler. * * @param[in] evt_id SoC event. * @param[in] p_context Context. */ static void soc_evt_handler(uint32_t evt_id, void * p_context) { switch (evt_id) { case NRF_EVT_FLASH_OPERATION_SUCCESS: /* fall through */ case NRF_EVT_FLASH_OPERATION_ERROR: if (m_memory_access_in_progress) { m_memory_access_in_progress = false; scan_start(NULL); } break; default: // No implementation needed. break; } } // changement 4 static void ble_nus_c_evt_handler(ble_nus_c_t * p_ble_nus_c, ble_nus_c_evt_t const * p_ble_nus_evt) { ret_code_t err_code; switch (p_ble_nus_evt->evt_type && (p_ble_nus_evt->conn_handle!=0)) { case BLE_NUS_C_EVT_DISCOVERY_COMPLETE: NRF_LOG_RAW_INFO("Discovery complete.\r\n"); err_code = ble_nus_c_handles_assign(p_ble_nus_c, p_ble_nus_evt->conn_handle, &p_ble_nus_evt->handles); APP_ERROR_CHECK(err_code); err_code = ble_nus_c_tx_notif_enable(p_ble_nus_c); APP_ERROR_CHECK(err_code); NRF_LOG_RAW_INFO("Connected to device with Nordic UART Service.\r\n"); uint8_t ui8_string[1] = {'L'}; err_code = ble_nus_c_string_send(&(m_ble_nus_c), ui8_string, 1); APP_ERROR_CHECK(err_code); break; case BLE_NUS_C_EVT_NUS_TX_EVT: //changement 5 //ble_nus_chars_received_uart_print(p_ble_nus_evt->p_data, p_ble_nus_evt->data_len); for(uint8_t ui8_for = 0; ui8_for < p_ble_nus_evt->data_len; ui8_for++) { NRF_LOG_RAW_INFO("%x ", p_ble_nus_evt->p_data[ui8_for]); } NRF_LOG_RAW_INFO("\r\n BLE_NUS_C_EVT_NUS_TX_EVT FIRED\r\n"); break; case BLE_NUS_C_EVT_DISCONNECTED: NRF_LOG_RAW_INFO("Disconnected +++ BLE_NUS_C_EVT_DISCONNECTED\r\n"); scan_start(NULL); break; } } /**@brief Function for handling database discovery events. * * @details This function is callback function to handle events from the database discovery module. * Depending on the UUIDs that are discovered, this function should forward the events * to their respective services. * * @param[in] p_event Pointer to the database discovery event. */ static void db_disc_handler(ble_db_discovery_evt_t *p_evt) { ble_nus_c_on_db_disc_evt(&m_ble_nus_c, p_evt); } /**@brief Function for handling Scanning Module events. */ static void scan_evt_handler(scan_evt_t const * p_scan_evt) { ret_code_t err_code; switch(p_scan_evt->scan_evt_id) { case NRF_BLE_SCAN_EVT_SCAN_TIMEOUT: NRF_LOG_INFO("Scan timed out."); scan_start(NULL); break; // handling of connected events case NRF_BLE_SCAN_EVT_CONNECTING_ERROR: err_code = p_scan_evt->params.connecting_err.err_code; APP_ERROR_CHECK(err_code); break; case NRF_BLE_SCAN_EVT_CONNECTED: { ble_gap_evt_connected_t const * p_connected = p_scan_evt->params.connected.p_connected; // Scan is automatically stopped by the connection. NRF_LOG_INFO("Connecting to target %02x%02x%02x%02x%02x%02x", p_connected->peer_addr.addr[5], p_connected->peer_addr.addr[4], p_connected->peer_addr.addr[3], p_connected->peer_addr.addr[2], p_connected->peer_addr.addr[1], p_connected->peer_addr.addr[0] ); } break; default: break; } } //////////////////////// //// INIT FUNCTIONS //// //////////////////////// /**@brief Function for initializing the BLE stack. * * @details Initializes the SoftDevice and the BLE event interrupt. */ static void ble_stack_init(void) { ret_code_t err_code; err_code = nrf_sdh_enable_request(); APP_ERROR_CHECK(err_code); // Configure the BLE stack using the default settings. // Fetch the start address of the application RAM. uint32_t ram_start = 0; err_code = nrf_sdh_ble_default_cfg_set(APP_BLE_CONN_CFG_TAG, &ram_start); APP_ERROR_CHECK(err_code); // ble_cfg.common_cfg.vs_uuid_cfg.vs_uuid_count = 4; //err_code = sd_ble_cfg_set(BLE_COMMON_CFG_VS_UUID, &ble_cfg, ram_start); // Enable BLE stack. err_code = nrf_sdh_ble_enable(&ram_start); APP_ERROR_CHECK(err_code); // Register handlers for BLE and SoC events. NRF_SDH_BLE_OBSERVER(m_ble_observer, APP_BLE_OBSERVER_PRIO, ble_evt_handler, NULL); NRF_SDH_SOC_OBSERVER(m_soc_observer, APP_SOC_OBSERVER_PRIO, soc_evt_handler, NULL); // changement 3 //NRF_SDH_BLE_OBSERVER(m_nus_observer, BLE_NUS_C_BLE_OBSERVER_PRIO, ble_nus_c_evt_handler, &(m_ble_nus_c)); } /**@brief Function for initializing the scanning and setting the filters. */ static void scan_init(void) { ret_code_t err_code; nrf_ble_scan_init_t init_scan; memset(&init_scan, 0, sizeof(init_scan)); init_scan.connect_if_match = true; init_scan.conn_cfg_tag = APP_BLE_CONN_CFG_TAG; init_scan.p_scan_param = &m_scan_param; err_code = nrf_ble_scan_init(&m_scan, &init_scan, scan_evt_handler); APP_ERROR_CHECK(err_code); // preventing connexion after we set the real filter err_code = nrf_ble_scan_filters_enable(&m_scan, NRF_BLE_SCAN_NAME_FILTER, false); APP_ERROR_CHECK(err_code); err_code = nrf_ble_scan_filter_set(&m_scan, SCAN_NAME_FILTER, "0xbadf00d"); APP_ERROR_CHECK(err_code); } /**@brief Function for initializing logging. */ static void log_init(void) { ret_code_t err_code = NRF_LOG_INIT(NULL); APP_ERROR_CHECK(err_code); NRF_LOG_DEFAULT_BACKENDS_INIT(); } /**@brief Function for initializing the timer. */ static void timer_init(void) { ret_code_t err_code = app_timer_init(); APP_ERROR_CHECK(err_code); } /**@brief Function for initializing power management. */ static void power_management_init(void) { ret_code_t err_code; err_code = nrf_pwr_mgmt_init(); APP_ERROR_CHECK(err_code); } /**@brief Database discovery initialization. */ static void db_discovery_init(void) { ret_code_t err_code = ble_db_discovery_init(db_disc_handler); APP_ERROR_CHECK(err_code); } ///////////////////////// //// OTHER FUNCTIONS //// ///////////////////////// /**@brief Function for starting scanning. * * @param[in] p_target_periph_name Name of the device we try to connect to. This name is searched in the scan report data * if NULL, we are just scanning */ static void scan_start(const char* p_target_periph_name) { ret_code_t err_code; // If there is any pending write to flash, defer scanning until it completes. if (nrf_fstorage_is_busy(NULL)) { m_memory_access_in_progress = true; return; } if(p_target_periph_name != NULL) { err_code = nrf_ble_scan_all_filter_remove(&m_scan); APP_ERROR_CHECK(err_code); err_code = nrf_ble_scan_filters_enable(&m_scan, NRF_BLE_SCAN_NAME_FILTER, false); APP_ERROR_CHECK(err_code); err_code = nrf_ble_scan_filter_set(&m_scan, SCAN_NAME_FILTER, p_target_periph_name); APP_ERROR_CHECK(err_code); }else{ // Disable filters. err_code = nrf_ble_scan_filters_disable(&m_scan); APP_ERROR_CHECK(err_code); err_code = nrf_ble_scan_all_filter_remove(&m_scan); APP_ERROR_CHECK(err_code); } err_code = nrf_ble_scan_start(&m_scan); APP_ERROR_CHECK(err_code); } /**@brief Function for initializing nus_c */ static void nus_c_init(void) { uint32_t err_code; ble_nus_c_init_t nus_c_init_t; nus_c_init_t.evt_handler = ble_nus_c_evt_handler; //for (uint32_t m_ble_nus_c_count = 0; m_ble_nus_c_count < NRF_SDH_BLE_TOTAL_LINK_COUNT; m_ble_nus_c_count++) // { err_code = ble_nus_c_init(&m_ble_nus_c, &nus_c_init_t); APP_ERROR_CHECK(err_code); //} } /////////////////// //// MAIN LOOP //// /////////////////// /**@brief Function for handling the idle state (main loop). * * @details Handles any pending log operations, then sleeps until the next event occurs. */ static void idle_state_handle(void) { if (NRF_LOG_PROCESS() == false) { nrf_pwr_mgmt_run(); } } int main(void) { for (int i=0; i<tag.name_len;i++) { tag.p_name[i] = '\0'; } // Initialize. log_init(); timer_init(); //uart_init(); // change 2 uart power_management_init(); ble_stack_init(); scan_init(); db_discovery_init(); // change discovery nus_c_init(); // Start execution. NRF_LOG_RAW_INFO( " ----------------\r\n"); NRF_LOG_RAW_INFO( "| Beacon 666 scanner |"); NRF_LOG_RAW_INFO("\r\n ----------------\r\n"); scan_start(m_target_periph_name); // Enter main loop. for (;;) { idle_state_handle(); } }
Any clue is accepted !
Thanks