Hope you are doing good!
I am using two nrf52833DK's one as a Central and the other as a Peripheral. I am also using another custom board (nrf52833) as a second peripheral.
NCS 2.2.0 for multi NUS central and 2.3.0 for peripheral_uart
Multi-NUS (github.com/.../multi-NUS), working fine.Able to connect the two peripherals.can send and receive data. Now issues i am facing are the following.
- When I connect and disconnect the peripheral and connect again(repeating this step every 20 secs), the following message on RTT [00:19:51.936,981] central_uart: ATT error code: 0x20011C0C
[00:19:56.497,711] bt_conn: Found valid connection in the connected state
[00:19:56.507,873] bt_conn: Found valid connection in the connected state
[00:19:56.507,873] central_uart: Connecting failed
[00:19:59.988,037] central_uart: Disconnected: E8:2B:FD:17:14:C2 (random) (reason 8)
[00:20:25.330,444] central_uart: Disconnected: F7:13:07:67:2D:04 (random) (reason 8) - Central (Multi-NUS) becomes unresponsive. So peripheral reset has no impact on it. Need to reset the central.
I followed the https://github.com/NordicMatt/multi-NUS/issues/1 but still the same issue as discussed.
3. I observed the same that after
main.c
/* * Copyright (c) 2018 Nordic Semiconductor ASA * * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause */ /** @file * @brief Nordic UART Service Client sample */ #include <errno.h> #include <zephyr/kernel.h> #include <zephyr/device.h> #include <zephyr/devicetree.h> #include <zephyr/sys/byteorder.h> #include <zephyr/sys/printk.h> #include <zephyr/bluetooth/bluetooth.h> #include <zephyr/bluetooth/hci.h> #include <zephyr/bluetooth/conn.h> #include <zephyr/bluetooth/uuid.h> #include <zephyr/bluetooth/gatt.h> #include <nrfx_rtc.h> // RTC // code added by luis pc// code added by usman #include <bluetooth/services/nus.h> #include <bluetooth/services/nus_client.h> #include <bluetooth/gatt_dm.h> #include <bluetooth/scan.h> #include <bluetooth/conn_ctx.h> #include <zephyr/settings/settings.h> #include <zephyr/drivers/uart.h> #include <zephyr/logging/log.h> #include <zephyr/drivers/spi.h> #include<zephyr/devicetree.h> #include <zephyr/sys/printk.h> #include <stdio.h> #include <zephyr/drivers/gpio.h> uint8_t num = 0; int8_t Rsrp_Usigned; const char Rsrp_Quant[16]={0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F}; uint8_t Central_Con_Array[6]={0xAA,0xA0,0x00,'&',')',0x00}; //(20A )0xA nrf9160 as gateway (sensor in peripheral),(20B) LTE RSSI it will be fill in nrf9160 ,(21A) BLE RSSI , (21B) simultenous connections and last element is & ,(20,21) uint8_t Central_Arr[30]; //#include <bluetooth/conn.h> #define LOG_MODULE_NAME central_uart LOG_MODULE_REGISTER(LOG_MODULE_NAME,LOG_LEVEL_DBG); /* UART payload buffer element size. */ #define UART_BUF_SIZE 251 // 20 #define KEY_PASSKEY_ACCEPT DK_BTN1_MSK #define KEY_PASSKEY_REJECT DK_BTN2_MSK #define NUS_WRITE_TIMEOUT K_MSEC(150) #define UART_WAIT_FOR_BUF_DELAY K_MSEC(50) #define UART_RX_TIMEOUT 50 #define ROUTED_MESSAGE_CHAR '*' #define BROADCAST_INDEX 99 #define SPI_DEV_NAME "spi_3" #define cs DT_ALIAS(led1)// 11 for nrf52833 #define pdn DT_ALIAS(led2)// 28 for nrf52833 static const struct device *uart = DEVICE_DT_GET(DT_NODELABEL(uart0)); static struct k_work_delayable uart_work; static K_SEM_DEFINE(nus_write_sem, 0, 1); struct uart_data_t { void *fifo_reserved; uint8_t data[UART_BUF_SIZE]; uint16_t len; }; BT_CONN_CTX_DEF(conns, CONFIG_BT_MAX_CONN, sizeof(struct bt_nus_client)); static K_FIFO_DEFINE(fifo_uart_tx_data); static K_FIFO_DEFINE(fifo_uart_rx_data); static struct bt_conn *default_conn; static bool routedMessage = false; static bool messageStart = true; static struct bt_nus_client nus_client; struct bt_le_scan_param m_scan_param = { .type = BT_LE_SCAN_TYPE_ACTIVE, .interval = BT_GAP_SCAN_FAST_INTERVAL, .window = BT_GAP_SCAN_FAST_WINDOW, .options = BT_LE_SCAN_OPT_CODED | BT_LE_SCAN_OPT_NO_1M }; /* static void ble_data_sent(struct bt_nus_client *nus, uint8_t err, const uint8_t *const data, uint16_t len) { ARG_UNUSED(nus); struct uart_data_t *buf; // Retrieve buffer context. // buf = CONTAINER_OF(data, struct uart_data_t, data); k_free(buf); k_sem_give(&nus_write_sem); if (err) { LOG_WRN("ATT error code: 0x%02X", err); } } */ static void ble_data_sent(uint8_t err, const uint8_t *const data, uint16_t len) { k_sem_give(&nus_write_sem); if (err) { LOG_WRN("ATT error code: 0x%02X", err); } } /* New function for sending data into the multi-NUS * Extensions to the behavior of message routing can be made here. * If the first character is *, this indicates a routed message. * If the first character is not *, then this is a broadcast message sent to all peers. * Iaf the message is routed, the two characters after the * will be read as the peer number * and the message will be sent only to that peer. Numbers must be written as two digits, i.e 01 for 1. * The default behavior will be to broadcast in the case of failure of message parsing. */ static int multi_nus_send(struct uart_data_t *buf){ int err = 0; char * message = buf->data; int length = buf->len; static bool broadcast = false; static int nus_index = 0; LOG_INF("Multi-Nus Send"); /*How many connections are there in the Connection Context Library?*/ const size_t num_nus_conns = bt_conn_ctx_count(&conns_ctx_lib); /*Handle the routing of the message only at the beginning of the message*/ if (messageStart) { messageStart = false; /*Check if it's a routed message*/ if (message[0] == ROUTED_MESSAGE_CHAR) { routedMessage = true; /*Determine who the intended recipient is*/ char str[2]; str[0] = message[1]; str[1] = message[2]; nus_index = atoi(str); /*Is this a number that makes sense?*/ if ((nus_index >= 0) && (nus_index < num_nus_conns)){ broadcast = false; /*Move the data buffer pointer to after the recipient info and shorten the length*/ message = &message[3]; length = length - 3; } else if (nus_index == BROADCAST_INDEX) { broadcast = true; message = &message[3]; length = length - 3; } } else { broadcast = true; } } /* If it's a routed message, send it to that guy. * If it's not, broadcast it to everyone. */ if (broadcast == false){ const struct bt_conn_ctx *ctx = bt_conn_ctx_get_by_id(&conns_ctx_lib, nus_index); LOG_INF("Trying to send to server %d", nus_index); if (ctx) { struct bt_nus_client *nus_client = ctx->data; if (nus_client) { err = bt_nus_client_send(nus_client, message, length); if (err) { LOG_WRN("Failed to send data over BLE connection" "(err %d)", err); }else{ LOG_INF("Sent to server %d: %s", nus_index, log_strdup(message)); } err = k_sem_take(&nus_write_sem, NUS_WRITE_TIMEOUT); if (err) { LOG_WRN("NUS send timeout"); } } bt_conn_ctx_release(&conns_ctx_lib, (void *)ctx->data); } }else{//Broadcast message LOG_INF("Broadcast"); printk("broad cast message to : %d " ,num_nus_conns); for (int i = 0; i < num_nus_conns; i++) { const struct bt_conn_ctx *ctx = bt_conn_ctx_get_by_id(&conns_ctx_lib, i); if (ctx) { struct bt_nus_client *nus_client = ctx->data; if (nus_client) { err = bt_nus_client_send(nus_client, message, length); if (err) { LOG_WRN("Failed to send data over BLE connection" "(err %d)", err); }else{ LOG_INF("Sent to server %d: %s", i, log_strdup(message)); } bt_conn_ctx_release(&conns_ctx_lib, (void *)ctx->data); err = k_sem_take(&nus_write_sem, NUS_WRITE_TIMEOUT); if (err) { LOG_WRN("NUS send timeout"); } } } } } if ( (message[length-1] == '\n') || (message[length-1] == '\r') ) { messageStart = true; routedMessage = false; } return err; } /* This function has been updated to add the ability for a peer to route a message by * appending a '*' as in the multi-NUS send function. So a peer could send the message * *00 to send a message to peer 0. If the peer sends a *99, that message is broadcast to * all peers */ void print_uart(const struct device * dev,char *buf) { int msg_len = 25; //strlen(buf); // for (int i = 0; i < msg_len; i++) { uart_poll_out(dev, buf[i]); } } bool Data_Integrity_Check(uint8_t * Peri_Data){ /* printf("Data_Integrity_Check .......\n"); for(char i=0; i<31; i++){ // print data coming from peripheral Via BLE , 31 bytes printf(" %x ",Peri_Data[i]); } printf("checksum from peripheral is %x \n",Peri_Data[30]); */ uint16_t crc = crc16_ccitt(0x1021,Peri_Data,30); // crc polynomial 0x1021 , input arguments , Array and no. of bytes to calc checksum crc =(crc&0x00FF); //Only LSB is required // printf("CRC: 0x%04X\n", crc); if(crc==Peri_Data[30]){ // compare the crc calculated by received data , and the checksum send by peripheral @ index # 30 and byte # 31 // printf("check sum matched ....\n"); return true; } else { printf("check sum Not matched ....\n"); return false; } return false; } void Central_frame(uint8_t * Peri_Data){ //char * index; uint8_t * Source_Ptr; uint8_t * Dest_Ptr; Source_Ptr = Peri_Data+11; // Peri_Data(i+11); Dest_Ptr = Central_Arr; // &Central_Arr[0]; // both are same , &Central_Arr[0] OR Central_Arr; for(char i=0; i<19; i++){ *Dest_Ptr = *Source_Ptr; Dest_Ptr++; Source_Ptr++; } Central_Arr[0]=0xB0; Central_Arr[2]=0xB2; Central_Arr[3]=0xB3; /* printf(" Array extraction Central Array"); for(char i=0; i<18; i++){ printf(" %x ",Central_Arr[i]); } */ /* Central_Arr[0]=0xB0; Central_Arr[1]=Peri_Data[12]; Central_Arr[2]=0xB2; Central_Arr[3]=0xB3; //while(*Peri_Data!=NULL){ Central_Arr[4]=Peri_Data[15]; Central_Arr[5]=Peri_Data[16]; Central_Arr[6]=Peri_Data[17]; */ //} } static uint8_t ble_data_received(struct bt_nus_client *nus, const uint8_t *data, uint16_t len) { ARG_UNUSED(nus); int err; bool Data_Valid; for (uint16_t pos = 0; pos != len;) { struct uart_data_t *tx = k_malloc(sizeof(*tx)); if (!tx) { LOG_WRN("Not able to allocate UART send data buffer"); return BT_GATT_ITER_CONTINUE; } /* Keep the last byte of TX buffer for potential LF char. */ size_t tx_data_size = sizeof(tx->data) ;//- 1; Added if ((len - pos) > tx_data_size) { tx->len = tx_data_size; } else { tx->len = (len - pos); } memcpy(tx->data, &data[pos], tx->len); pos += tx->len; /* Append the LF character when the CR character triggered * transmission from the peer. */ if ((pos == len) && (data[len - 1] == '\r')) { tx->data[tx->len] = '\n'; tx->len++; } /* Routed messages. See the comments above. * Check for *, if there's a star, send it over to the multi-nus send function */ if (( data[0] == '*') || (routedMessage == true) ) { multi_nus_send(tx); } // printf("number of connections ..... %d",num); Data_Valid = Data_Integrity_Check(tx->data); // Data_Integrity_Check , data is valid or not ? Central_frame(tx->data); if(Data_Valid==true){ // if data is valid then proceed further else return, varify check sum printk("($"); // data send to gateway nrf9160 should be between $ (31 bytes ) & // err = uart_tx(uart, tx->data, tx->len, SYS_FOREVER_MS); //send the packet to uart for nrf9160 // err = uart_tx(uart, Central_Arr, 18, SYS_FOREVER_MS); //send the packet to uart for nrf9160 /* for(char i=0; i<18; i++){ printk("%x ",Central_Arr[i]); // & is the last element of Central_Con_Array } */ Central_Con_Array[2]=(Central_Con_Array[2]&0xF0)|(num&0x0F); // ( 21B) // Nibble to write in Lower 4 bits (0xF0 = 11110000) for(char i=0; i<6; i++){ //printk("0x%02X ",Central_Con_Array[i]); // & is the last element of Central_Con_Array Central_Arr[i+19]=Central_Con_Array[i]; } //Central_Arr[22]=NULL; print_uart(uart,Central_Arr); // set the value of 25 characters , plz go inside the fn } else if (Data_Valid==false){ // if data is NOT valid then NOT send the packet to uart for nrf9160 printf("DO Nothing ...... \n"); } k_free(tx); if (err) { k_fifo_put(&fifo_uart_tx_data, tx); } } return BT_GATT_ITER_CONTINUE; } static void uart_cb(const struct device *dev, struct uart_event *evt, void *user_data) { ARG_UNUSED(dev); static size_t aborted_len; struct uart_data_t *buf; static uint8_t *aborted_buf; static bool disable_req; switch (evt->type) { case UART_TX_DONE: LOG_DBG("UART_TX_DONE"); if ((evt->data.tx.len == 0) || (!evt->data.tx.buf)) { return; } if (aborted_buf) { buf = CONTAINER_OF(aborted_buf, struct uart_data_t, data); aborted_buf = NULL; aborted_len = 0; } else { buf = CONTAINER_OF(evt->data.tx.buf, struct uart_data_t, data); } k_free(buf); buf = k_fifo_get(&fifo_uart_tx_data, K_NO_WAIT); if (!buf) { return; } if (uart_tx(uart, buf->data, buf->len, SYS_FOREVER_MS)) { LOG_WRN("Failed to send data over UART"); } break; case UART_RX_RDY: LOG_DBG("UART_RX_RDY"); buf = CONTAINER_OF(evt->data.rx.buf, struct uart_data_t, data); buf->len += evt->data.rx.len; if (disable_req) { return; } if ((evt->data.rx.buf[buf->len - 1] == '\n') || (evt->data.rx.buf[buf->len - 1] == '\r')) { disable_req = true; uart_rx_disable(uart); } break; case UART_RX_DISABLED: LOG_DBG("UART_RX_DISABLED"); disable_req = false; buf = k_malloc(sizeof(*buf)); if (buf) { buf->len = 0; } else { LOG_WRN("Not able to allocate UART receive buffer"); k_work_reschedule(&uart_work, UART_WAIT_FOR_BUF_DELAY); return; } uart_rx_enable(uart, buf->data, sizeof(buf->data), UART_RX_TIMEOUT); break; case UART_RX_BUF_REQUEST: LOG_DBG("UART_RX_BUF_REQUEST"); buf = k_malloc(sizeof(*buf)); if (buf) { buf->len = 0; uart_rx_buf_rsp(uart, buf->data, sizeof(buf->data)); } else { LOG_WRN("Not able to allocate UART receive buffer"); } break; case UART_RX_BUF_RELEASED: LOG_DBG("UART_RX_BUF_RELEASED"); buf = CONTAINER_OF(evt->data.rx_buf.buf, struct uart_data_t, data); if (buf->len > 0) { k_fifo_put(&fifo_uart_rx_data, buf); } else { k_free(buf); } break; case UART_TX_ABORTED: LOG_DBG("UART_TX_ABORTED"); if (!aborted_buf) { aborted_buf = (uint8_t *)evt->data.tx.buf; } aborted_len += evt->data.tx.len; buf = CONTAINER_OF(aborted_buf, struct uart_data_t, data); uart_tx(uart, &buf->data[aborted_len], buf->len - aborted_len, SYS_FOREVER_MS); break; default: break; } } static void uart_work_handler(struct k_work *item) { struct uart_data_t *buf; buf = k_malloc(sizeof(*buf)); if (buf) { buf->len = 0; } else { LOG_WRN("Not able to allocate UART receive buffer"); k_work_reschedule(&uart_work, UART_WAIT_FOR_BUF_DELAY); return; } uart_rx_enable(uart, buf->data, sizeof(buf->data), UART_RX_TIMEOUT); } static int uart_init(void) { int err; struct uart_data_t *rx; if (!device_is_ready(uart)) { LOG_ERR("UART device not ready"); return -ENODEV; } rx = k_malloc(sizeof(*rx)); if (rx) { rx->len = 0; } else { return -ENOMEM; } k_work_init_delayable(&uart_work, uart_work_handler); err = uart_callback_set(uart, uart_cb, NULL); if (err) { return err; } return uart_rx_enable(uart, rx->data, sizeof(rx->data), UART_RX_TIMEOUT); } static void discovery_complete(struct bt_gatt_dm *dm, void *context) { struct bt_nus_client *nus = context; LOG_INF("Service discovery completed"); bt_gatt_dm_data_print(dm); bt_nus_handles_assign(dm, nus); bt_nus_subscribe_receive(nus); bt_gatt_dm_data_release(dm); // Added code from multinus int err = bt_scan_start(BT_SCAN_TYPE_SCAN_ACTIVE); if (err) { LOG_ERR("Scanning failed to start (err %d)", err); } else { LOG_INF("Scanning started"); } /* Send a message to the new NUS server informing it of its ID in this * mini-network * The new NUS will have been added to the connection context library and so * will be the highest index as they are added incrementally upwards. * This is a bit of a workaround because in this function, I don't know * the ID of this connection which is the piece of info I want to transmit. */ size_t num_nus_conns = bt_conn_ctx_count(&conns_ctx_lib); size_t nus_index = 99; /* This is a little inelegant but we must get the index of the device to * convey it. This bit sends the index number to the peripheral. */ for (size_t i = 0; i < num_nus_conns; i++) { const struct bt_conn_ctx *ctx = bt_conn_ctx_get_by_id(&conns_ctx_lib, i); if (ctx) { if (ctx->data == nus) { nus_index = i; char message[3]; sprintf(message, "%d", nus_index); message[2] = '\r'; int length = 3; err = bt_nus_client_send(nus, message, length); if (err) { LOG_WRN("Failed to send data over BLE connection" "(err %d)", err); } else { LOG_INF("Sent to server %d: %s", nus_index, log_strdup(message)); } bt_conn_ctx_release(&conns_ctx_lib, (void *)ctx->data); break; } else { bt_conn_ctx_release(&conns_ctx_lib, (void *)ctx->data); } } } } static void discovery_service_not_found(struct bt_conn *conn, void *context) { LOG_INF("Service not found"); } static void discovery_error(struct bt_conn *conn, int err, void *context) { LOG_WRN("Error while discovering GATT database: (%d)", err); } struct bt_gatt_dm_cb discovery_cb = { .completed = discovery_complete, .service_not_found = discovery_service_not_found, .error_found = discovery_error, }; /* static void gatt_discover(struct bt_conn *conn) { int err; if (conn != default_conn) { return; } err = bt_gatt_dm_start(conn, BT_UUID_NUS_SERVICE, &discovery_cb, &nus_client); if (err) { LOG_ERR("could not start the discovery procedure, error " "code: %d", err); } } */ static void gatt_discover(struct bt_conn *conn) { int err; struct bt_nus_client *nus_client = bt_conn_ctx_get(&conns_ctx_lib, conn); if (!nus_client) { return; } err = bt_gatt_dm_start(conn, BT_UUID_NUS_SERVICE, &discovery_cb, nus_client); if (err) { LOG_ERR("could not start the discovery procedure, error " "code: %d", err); } bt_conn_ctx_release(&conns_ctx_lib, (void *) nus_client); } static void exchange_func(struct bt_conn *conn, uint8_t err, struct bt_gatt_exchange_params *params) { if (!err) { LOG_INF("MTU exchange done"); } else { LOG_WRN("MTU exchange failed (err %" PRIu8 ")", err); } } /*MTU exchange*/ static void mtu_exchange_cb(struct bt_conn *conn, uint8_t err, struct bt_gatt_exchange_params *params) { LOG_INF("MTU exchange %u %s (%u)", bt_conn_index(conn), err == 0U ? "successful" : "failed", bt_gatt_get_mtu(conn)); } static struct bt_gatt_exchange_params mtu_exchange_params[CONFIG_BT_MAX_CONN]; static int mtu_exchange(struct bt_conn *conn) { uint8_t conn_index; int err; conn_index = bt_conn_index(conn); LOG_INF("MTU (%u): %u", conn_index, bt_gatt_get_mtu(conn)); mtu_exchange_params[conn_index].func = mtu_exchange_cb; err = bt_gatt_exchange_mtu(conn, &mtu_exchange_params[conn_index]); if (err) LOG_INF("MTU exchange failed (err %d)", err); else LOG_INF("Exchange pending..."); return err; } static void connected(struct bt_conn *conn, uint8_t conn_err) { char addr[BT_ADDR_LE_STR_LEN]; int err; struct bt_nus_client_init_param init = { // code added .cb = { .received = ble_data_received, .sent = ble_data_sent, } }; bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr)); if (conn_err) { LOG_INF("Failed to connect to %s (%d)", log_strdup(addr), conn_err); printk("Failed to connect to %s (%d)", log_strdup(addr), conn_err); if (default_conn == conn) { bt_conn_unref(default_conn); default_conn = NULL; err = bt_scan_start(BT_SCAN_TYPE_SCAN_ACTIVE); if (err) { LOG_ERR("Scanning failed to start (err %d)", err); printk("Scanning failed to start (err %d)", err); } } return; } mtu_exchange(default_conn); LOG_INF("Connected: %s", log_strdup(addr)); num++; printf("Connected.... "); // code added /*Allocate memory for this connection using the connection context library. For reference, this code was taken from hids.c */ struct bt_nus_client *nus_client = bt_conn_ctx_alloc(&conns_ctx_lib, conn); if (!nus_client) { LOG_WRN("There is no free memory to " "allocate the connection context"); } memset(nus_client, 0, bt_conn_ctx_block_size_get(&conns_ctx_lib)); err = bt_nus_client_init(nus_client, &init); bt_conn_ctx_release(&conns_ctx_lib, (void *)nus_client); if (err) { LOG_ERR("NUS Client initialization failed (err %d)", err); }else{ LOG_INF("NUS Client module initialized"); } gatt_discover(conn); /* static struct bt_gatt_exchange_params exchange_params; exchange_params.func = exchange_func; err = bt_gatt_exchange_mtu(conn, &exchange_params); if (err) { LOG_WRN("MTU exchange failed (err %d)", err); } err = bt_conn_set_security(conn, BT_SECURITY_L2); if (err) { LOG_WRN("Failed to set security: %d", err); gatt_discover(conn); } */ err = bt_scan_stop(); if ((!err) && (err != -EALREADY)) { LOG_ERR("Stop LE scan failed (err %d)", err); } } static void disconnected(struct bt_conn *conn, uint8_t reason) { char addr[BT_ADDR_LE_STR_LEN]; int err; bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr)); LOG_INF("Disconnected...: %s (reason %u)", log_strdup(addr), reason); err = bt_conn_ctx_free(&conns_ctx_lib, conn); // code added if (err) { LOG_WRN("The memory was not allocated for the context of this " "connection."); } else{ LOG_WRN("The memory allocated for the context of this " "connection."); } bt_conn_unref(conn); default_conn = NULL; num--; printf("Disconnected "); /* if (default_conn != conn) { return; } bt_conn_unref(default_conn); default_conn = NULL; err = bt_scan_start(BT_SCAN_TYPE_SCAN_ACTIVE); if (err) { LOG_ERR("Scanning failed to start (err %d)", err); } printf("Start Scanning again ..... "); */ } static void security_changed(struct bt_conn *conn, bt_security_t level, enum bt_security_err err) { char addr[BT_ADDR_LE_STR_LEN]; bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr)); if (!err) { LOG_INF("Security changed: %s level %u", log_strdup(addr), level); } else { LOG_WRN("Security failed: %s level %u err %d", log_strdup(addr), level, err); } gatt_discover(conn); } BT_CONN_CB_DEFINE(conn_callbacks) = { .connected = connected, .disconnected = disconnected, .security_changed = security_changed }; static void scan_filter_match(struct bt_scan_device_info *device_info, struct bt_scan_filter_match *filter_match, bool connectable) { int err; char addr[BT_ADDR_LE_STR_LEN]; struct bt_conn_le_create_param *conn_params; bt_addr_le_to_str(device_info->recv_info->addr, addr, sizeof(addr)); printk("Filters matched. Address: %s connectable: %s\n", addr, connectable ? "yes" : "no"); err = bt_scan_stop(); if (err) { printk("Stop LE scan failed (err %d)\n", err); } conn_params = BT_CONN_LE_CREATE_PARAM( BT_CONN_LE_OPT_CODED | BT_CONN_LE_OPT_NO_1M, BT_GAP_SCAN_FAST_INTERVAL, BT_GAP_SCAN_FAST_INTERVAL); err = bt_conn_le_create(device_info->recv_info->addr, conn_params, BT_LE_CONN_PARAM_DEFAULT, &default_conn); if (err) { printk("Create conn failed (err %d)\n", err); err = bt_scan_start(BT_SCAN_TYPE_SCAN_ACTIVE); if (err) { printk("Scanning failed to start (err %d)\n", err); return; } } printk("Connection pending\n"); } //BT_SCAN_CB_INIT(scan_cb, scan_filter_match, NULL, NULL, NULL); //BT_SCAN_CB_INIT(scan_cb, scan_filter_match, NULL,scan_connecting_error, scan_connecting); static void scan_connecting_error(struct bt_scan_device_info *device_info) { LOG_WRN("Connecting failed"); printk("RSSI VALUE IS %d",device_info->recv_info->rssi); Rsrp_Usigned=device_info->recv_info->rssi; //-76 ---> 76 Rsrp_Usigned=(Rsrp_Usigned/6)*(-1); //76/6 = 12 , Rsrp_Usigned=Rsrp_Quant[Rsrp_Usigned]; //Quantization range is (0-96) , divided into 16 level of 6 step each , 16*6 = 96, value will be = 0x0C // printk("Rsrp_Usigned %d",Rsrp_Usigned); Central_Con_Array[2]=(Rsrp_Usigned<<4)|(Central_Con_Array[2]&0x0F); // ( 21A) // Nibble to write in upper 4 bits (0x0F = 00001111) // printk("Central_Con_Array[1] %d",Central_Con_Array[1]); } static void scan_connecting(struct bt_scan_device_info *device_info, struct bt_conn *conn) { default_conn = bt_conn_ref(conn); } static int nus_client_init(void) { int err; struct bt_nus_client_init_param init = { .cb = { .received = ble_data_received, .sent = ble_data_sent, } }; err = bt_nus_client_init(&nus_client, &init); if (err) { LOG_ERR("NUS Client initialization failed (err %d)", err); return err; } LOG_INF("NUS Client module initialized"); return err; } BT_SCAN_CB_INIT(scan_cb, scan_filter_match, NULL,scan_connecting_error, scan_connecting); static void scan_init(void) { int err; // Use active scanning and disable duplicate filtering to handle any // devices that might update their advertising data at runtime. const char *perName1="Nordic_UART_Service"; struct bt_le_conn_param m_conn_param={ .interval_min=120, .interval_max=220, .timeout=100, }; struct bt_scan_init_param scan_init = { .connect_if_match = 1, //1 .scan_param = &m_scan_param, .conn_param = &m_conn_param, //NULL // }; bt_scan_init(&scan_init); bt_scan_cb_register(&scan_cb); //err = bt_scan_filter_add(BT_SCAN_FILTER_TYPE_UUID, BT_UUID_NUS_SERVICE); err = bt_scan_filter_add(BT_SCAN_FILTER_TYPE_NAME,perName1); if (err) { printk("Scanning filters cannot be set (err %d)\n", err); return; } //err = bt_scan_filter_enable(BT_SCAN_UUID_FILTER, false); err = bt_scan_filter_enable(BT_SCAN_NAME_FILTER, false); if (err) { printk("Filters cannot be turned on (err %d)\n", err); } } /* static int scan_init(void) { int err; struct bt_scan_init_param scan_init = { .connect_if_match = 1, }; bt_scan_init(&scan_init); bt_scan_cb_register(&scan_cb); err = bt_scan_filter_add(BT_SCAN_FILTER_TYPE_UUID, BT_UUID_NUS_SERVICE); if (err) { LOG_ERR("Scanning filters cannot be set (err %d)", err); return err; } err = bt_scan_filter_enable(BT_SCAN_UUID_FILTER, false); if (err) { LOG_ERR("Filters cannot be turned on (err %d)", err); return err; } LOG_INF("Scan module initialized"); return err; } */ static void auth_cancel(struct bt_conn *conn) { char addr[BT_ADDR_LE_STR_LEN]; bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr)); LOG_INF("Pairing cancelled: %s", log_strdup(addr)); } static void pairing_complete(struct bt_conn *conn, bool bonded) { char addr[BT_ADDR_LE_STR_LEN]; bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr)); LOG_INF("Pairing completed: %s, bonded: %d", log_strdup(addr), bonded); } static void pairing_failed(struct bt_conn *conn, enum bt_security_err reason) { char addr[BT_ADDR_LE_STR_LEN]; bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr)); LOG_WRN("Pairing failed conn: %s, reason %d", log_strdup(addr), reason); } static struct bt_conn_auth_cb conn_auth_callbacks = { .cancel = auth_cancel, }; static struct bt_conn_auth_info_cb conn_auth_info_callbacks = { .pairing_complete = pairing_complete, .pairing_failed = pairing_failed }; /////////////////////////////// code added ///////////////////////////////////////// const struct device * spi_dev; static struct spi_config spi_cfg = { .operation = SPI_WORD_SET(8) | SPI_OP_MODE_MASTER | SPI_TRANSFER_MSB // | SPI_MODE_CPOL // | SPI_MODE_CPHA , .frequency = 4000000, .slave = 0, //.cs=NULL, }; static const struct gpio_dt_spec cs_low = GPIO_DT_SPEC_GET(cs, gpios); static const struct gpio_dt_spec pdn_high = GPIO_DT_SPEC_GET(pdn, gpios); static struct spi_buf rx; const struct spi_buf_set rx_bufs = { .buffers = &rx, .count = 1 }; static struct spi_buf tx; const struct spi_buf_set tx_bufs = { .buffers = &tx, .count = 1 }; static void spi_init(void) { spi_dev = device_get_binding(SPI_DEV_NAME); // code added if (!spi_dev) { printk("SPI device not found\n"); return; } } void Nrf21540_Write_Register() { int err,ret; //static uint8_t tx_buffer[2] = {0xC0, 0x7D}; // 0x7D = 31 ,0x45 = 11 , 0x05 static uint8_t tx_buffer[2] = {0xC1, 0x01}; // enable the RX for confreg1 tx.buf = tx_buffer; tx.len = sizeof(tx_buffer); static uint8_t rx_buffer[2]; rx.buf = rx_buffer; rx.len = sizeof(rx_buffer); // while (1) { ret = gpio_pin_set_dt(&cs_low,0); // low if (ret < 0) { return; } //err = spi_transceive(spi_dev, &spi_cfg, &tx_bufs, &rx_bufs); //rx_bufs err = spi_write(spi_dev,&spi_cfg,&tx_bufs); if (err < 0) { printf("SPI error: %d\n", err); } else { printf("write successfully : %d\n", err); for (int i = 0; i <2; i++){ printf(" %x",rx_buffer[i]); } printf("\n"); } ret = gpio_pin_set_dt(&cs_low,1); // high if (ret < 0) { return; } // } } void Nrf21540_Read_Register() { int err,ret; //static uint8_t tx_buffer[2] = {0x80, 0x00}; // 0x80 for reading register confreg0 ,0x8 1000 0000 for reading static uint8_t tx_buffer[2] = {0x90, 0x00}; // read the confreg1 register tx.buf = tx_buffer; tx.len = sizeof(tx_buffer); static uint8_t rx_buffer[2]; rx.buf = rx_buffer; rx.len = sizeof(rx_buffer); ret = gpio_pin_set_dt(&cs_low,0); // low if (ret < 0) { return; } err = spi_transceive(spi_dev, &spi_cfg, &tx_bufs, &rx_bufs); //rx_bufs //err = spi_write(spi_dev,&spi_cfg,&tx_bufs); //err = spi_read(spi_dev,&spi_cfg,&rx_bufs); if (err < 0) { printk("SPI error: %d\n", err); } else if (err==0){ printf("Read successfully : %d\n", err); for (int i = 0; i <2; i++){ printf(" %x",rx_buffer[i]); } printf("\n"); } ret = gpio_pin_set_dt(&cs_low,1); // high if (ret < 0) { return; } } void main(void) { int err,ret; //..................................... code added ....................................................... spi_init(); if (!device_is_ready(cs_low.port)) { return; } ret = gpio_pin_configure_dt(&cs_low, GPIO_OUTPUT_ACTIVE); ret = gpio_pin_configure_dt(&pdn_high ,GPIO_OUTPUT_ACTIVE); if (ret < 0) { return; } ret = gpio_pin_set_dt(&pdn_high,1); // 0.28 nrf21540 always high if (ret < 0) { return; } else printk("PDN high at start up ...\n"); //..................................... code added ....................................................... err = bt_conn_auth_cb_register(&conn_auth_callbacks); if (err) { LOG_ERR("Failed to register authorization callbacks."); return; } /* err = bt_conn_auth_info_cb_register(&conn_auth_info_callbacks); if (err) { printk("Failed to register authorization info callbacks.\n"); return; } */ err = bt_enable(NULL); if (err) { LOG_ERR("Bluetooth init failed (err %d)", err); return; } LOG_INF("Bluetooth initialized"); if (IS_ENABLED(CONFIG_SETTINGS)) { settings_load(); } // bt_conn_cb_register(&conn_callback); int (*module_init[])(void) = {uart_init, scan_init, nus_client_init}; for (size_t i = 0; i < ARRAY_SIZE(module_init); i++) { err = (*module_init[i])(); if (err) { return; } } printk("Starting Bluetooth Central UART example\n"); // uint8_t input[18] = {0x01, 0x02, 0x03, 0x04, 0x55, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12}; // uint16_t crc = crc16_ccitt(0x1021,input,18); // printf("CRC: 0x%04X\n", crc); //..................................... code added ....................................................... Nrf21540_Write_Register(); k_msleep(100); Nrf21540_Read_Register(); k_msleep(100); //............................. code added ................................. err = bt_scan_start(BT_SCAN_TYPE_SCAN_ACTIVE); if (err) { LOG_ERR("Scanning failed to start (err %d)", err); return; } LOG_INF("Scanning successfully started"); for (;;) { // Wait indefinitely for data to be sent over Bluetooth // /*struct uart_data_t *buf = k_fifo_get(&fifo_uart_rx_data, K_FOREVER); err = bt_nus_client_send(&nus_client, buf->data, buf->len); if (err) { LOG_WRN("Failed to send data over BLE connection" "(err %d)", err); printk("Failed to send data over BLE connection" "(err %d)", err); } err = k_sem_take(&nus_write_sem, NUS_WRITE_TIMEOUT); if (err) { LOG_WRN("NUS send timeout"); printk("NUS send timeout"); } */ /* Wait indefinitely for data to be sent over Bluetooth */ struct uart_data_t *buf = k_fifo_get(&fifo_uart_rx_data, K_FOREVER); multi_nus_send(buf); // Debug Variables k_free(buf); } }
prj.conf
#
# Copyright (c) 2018 Nordic Semiconductor
#
# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
#
CONFIG_SPI=y
CONFIG_SPI_NRFX=y
# Enable the UART driver
CONFIG_UART_ASYNC_API=y
CONFIG_NRFX_UARTE0=y
CONFIG_SERIAL=y
CONFIG_CONSOLE=y
CONFIG_UART_CONSOLE=y
# Enable the BLE stack with GATT Client configuration
CONFIG_BT=y
CONFIG_BT_CENTRAL=y
CONFIG_BT_SMP=y
CONFIG_BT_GATT_CLIENT=y
CONFIG_BT_MAX_CONN=20
CONFIG_BT_MAX_PAIRED=20
CONFIG_BT_CONN_CTX=y
# Enable the BLE modules from NCS
CONFIG_BT_NUS_CLIENT=y
CONFIG_BT_SCAN=y
CONFIG_BT_SCAN_FILTER_ENABLE=y
CONFIG_BT_SCAN_UUID_CNT=1
CONFIG_BT_GATT_DM=y
CONFIG_HEAP_MEM_POOL_SIZE=2048
# This example requires more workqueue stack
CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE=2048
# Enable bonding
CONFIG_BT_SETTINGS=y
CONFIG_FLASH=y
CONFIG_FLASH_PAGE_LAYOUT=y
CONFIG_FLASH_MAP=y
CONFIG_NVS=y
CONFIG_SETTINGS=y
# Config logger
CONFIG_LOG=y
CONFIG_USE_SEGGER_RTT=y
CONFIG_LOG_BACKEND_RTT=y
CONFIG_LOG_BACKEND_UART=n
CONFIG_ASSERT=y
CONFIG_BT_EXT_ADV=y
CONFIG_BT_CTLR_PHY_CODED=y
CONFIG_BT_USER_PHY_UPDATE=y
CONFIG_BT_SCAN_NAME_CNT=1
#CONFIG_BT_USER_DATA_LEN_UPDATE=y
#CONFIG_BT_AUTO_DATA_LEN_UPDATE=y
#CONFIG_BT_L2CAP_TX_MTU=247
#CONFIG_BT_BUF_ACL_TX_SIZE=251
#CONFIG_BT_BUF_ACL_RX_SIZE=251
#CONFIG_BT_CTLR_DATA_LENGTH_MAX=251
Please Note:
I tried with original example as well without any code addition
NCS 1.4.1 for multi NUS central & peripheral_uart both.
But still get the same issue as discussed above .
Thanks in Advance,
Regards,