RSSI value through the BLE connection process in nRF connect SDK

Hi Nordic,

I am evaluating the nrf52833 DK with nrf connect SDK. I am using by dev kit here as a central devie and I want to get the RSSI values of the periherral devices through the BLE connection process. Here I don't want to initiate the scanning process, so I am connecting to that device by hard coding the MAC addresses in my code. Here I want to get the RSSI signal strength of the peripheral devices in the connection process. How do I do that in nrf connect SDK?

Thanks,

Pranathi.

Parents
  • Hi Pranathi,

    To be clear, there is no way to connect without scanning. When you excplicitly attemt to connect to a specific BLE address, what happens is that scanning is started, and when you receive a connectable advertising packet from the specified address, the BLE stack will connect to it.

    With that out of the way, to obtain the RSSI in a connection you can use BT_HCI_OP_READ_RSSI. You can find an example of that in read_conn_rssi() in zephyr/samples/bluetooth/hci_pwr_ctrl/src/main.c.

    Einar

  • Hi Einar,

    I am explicitely able to connect to the BLE device with my Dev kit without scanning. And to read RSSI, I have added the function read_conn_rssi() in my code and called it.

    I am getting the Read RSSI error as -5, which is internally mentioned as I/O error. 

    CODE:

    static void read_conn_rssi(uint16_t handle, int8_t *rssi)
    {
    	struct net_buf *buf, *rsp = NULL;
    	struct bt_hci_cp_read_rssi *cp;
    	struct bt_hci_rp_read_rssi *rp;
    
    	int err;
    
    	buf = bt_hci_cmd_create(BT_HCI_OP_READ_RSSI, sizeof(*cp));
    	if (!buf) {
    		printk("Unable to allocate command buffer\n");
    		return;
    	}
    
    	cp = net_buf_add(buf, sizeof(*cp));
    	cp->handle = sys_cpu_to_le16(handle);
    
    	err = bt_hci_cmd_send_sync(BT_HCI_OP_READ_RSSI, buf, &rsp);
    	if (err) {
    		uint8_t reason = rsp ?
    			((struct bt_hci_rp_read_rssi *)rsp->data)->status : 0;
    		printk("Read RSSI err: %d reason 0x%02x\n", err, reason);
    		return;
    	}
    
    	rp = (void *)rsp->data;
    	*rssi = rp->rssi;
    
    	net_buf_unref(rsp);
    }
    
    static void connected(struct bt_conn *conn, uint8_t err)
    {
        char addr[BT_ADDR_LE_STR_LEN];
    
    	
         
        bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
    
        if (err) {
            printk("Failed to connect to %s (%u)\n", addr, err);
    
            bt_conn_unref(default_conn);
            default_conn = NULL;
    	}
    	else
    	{
    
    	}
    
        if (conn != default_conn) {
            return;
        }
        printk("\nConnected: %s\n", addr);
    	int8_t rssi = 0xFF;
    	// printk("\nRSSI:%d\n",rssi);
    	read_conn_rssi(default_conn_handle, &rssi);
    	printk("Connected (%d) - RSSI = %d\n",default_conn_handle, rssi);
    }

    OUTPUT:

    How do I solve it?

    Thanks,

    Pranathi

  • Hi Einar,

    I was trying in the meanwhile I added the prj.conf 

    CONFIG_BT_CTLR_ADVANCED_FEATURES=y
    CONFIG_BT_CTLR_CONN_RSSI=y
    Now I am getting a constant value of 127 as the RSSI value.
    Atleast I am not getting the read error anymore....but am I missing something so I am only getting a 127 constant value every time I run the program?

    Thanks,

    Pranathi

  • Hi,

    You cannot read the RSSI in the connected callback. You need to wait until it has returned and call it later. See this thread for details.

Reply Children
  • Hi Einar,

    I tried to call it in the main loop as per the thread discussion, but I guess I didn't get it right and I am confused on what exactly to do, can you explain me clearly how to do it?

  • Hi,

    I have modified the Zephyr Bluetooth central sample to print the RSSI found in the connection before disconnecting (it also prints the RSSI for the advertising packet as that is part of the official sample). You just need to add the two Kconigs you have allready included, and use with this .c file:

    /* main.c - Application main entry point */
    
    /*
     * Copyright (c) 2015-2016 Intel Corporation
     *
     * SPDX-License-Identifier: Apache-2.0
     */
    
    #include <zephyr/types.h>
    #include <stddef.h>
    #include <errno.h>
    #include <zephyr/kernel.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 <zephyr/sys/byteorder.h>
    
    static void start_scan(void);
    void check_rssi_and_disconnect(struct k_work *item);
    
    static struct bt_conn *default_conn;
    
    static K_WORK_DEFINE(ping_work, check_rssi_and_disconnect);
    
    static void read_conn_rssi(uint16_t handle, int8_t *rssi)
    {
    	struct net_buf *buf, *rsp = NULL;
    	struct bt_hci_cp_read_rssi *cp;
    	struct bt_hci_rp_read_rssi *rp;
    
    	int err;
    
    	buf = bt_hci_cmd_create(BT_HCI_OP_READ_RSSI, sizeof(*cp));
    	if (!buf) {
    		printk("Unable to allocate command buffer\n");
    		return;
    	}
    
    	cp = net_buf_add(buf, sizeof(*cp));
    	cp->handle = sys_cpu_to_le16(handle);
    
    	err = bt_hci_cmd_send_sync(BT_HCI_OP_READ_RSSI, buf, &rsp);
    	if (err) {
    		uint8_t reason = rsp ?
    			((struct bt_hci_rp_read_rssi *)rsp->data)->status : 0;
    		printk("Read RSSI err: %d reason 0x%02x\n", err, reason);
    		return;
    	}
    
    	rp = (void *)rsp->data;
    	*rssi = rp->rssi;
    
    	net_buf_unref(rsp);
    }
    
    void check_rssi_and_disconnect(struct k_work *item)
    {
    	int8_t rssi = 0xFF;
    	uint16_t conn_handle;
    
    
    	ARG_UNUSED(item);
    
    	printk("Check RSSI and disconnect\n");
    
    	int rc = bt_hci_get_conn_handle(default_conn, &conn_handle);
    	if(rc)
    	{
    		printk("fail getting conn handle");
    	}
    
    	read_conn_rssi(conn_handle, &rssi);
    
    	printk("RSSI in connection: %i\n", rssi);
    
    	bt_conn_disconnect(default_conn, BT_HCI_ERR_REMOTE_USER_TERM_CONN);
    }
    
    static void device_found(const bt_addr_le_t *addr, int8_t rssi, uint8_t type,
    			 struct net_buf_simple *ad)
    {
    	char addr_str[BT_ADDR_LE_STR_LEN];
    	int err;
    
    	if (default_conn) {
    		return;
    	}
    
    	/* We're only interested in connectable events */
    	if (type != BT_GAP_ADV_TYPE_ADV_IND &&
    	    type != BT_GAP_ADV_TYPE_ADV_DIRECT_IND) {
    		return;
    	}
    
    	bt_addr_le_to_str(addr, addr_str, sizeof(addr_str));
    	printk("Device found: %s (RSSI %d)\n", addr_str, rssi);
    
    	/* connect only to devices in close proximity */
    	if (rssi < -50) {
    		return;
    	}
    
    	if (bt_le_scan_stop()) {
    		return;
    	}
    
    	err = bt_conn_le_create(addr, BT_CONN_LE_CREATE_CONN,
    				BT_LE_CONN_PARAM_DEFAULT, &default_conn);
    	if (err) {
    		printk("Create conn to %s failed (%d)\n", addr_str, err);
    		start_scan();
    	}
    }
    
    static void start_scan(void)
    {
    	int err;
    
    	/* This demo doesn't require active scan */
    	err = bt_le_scan_start(BT_LE_SCAN_PASSIVE, device_found);
    	if (err) {
    		printk("Scanning failed to start (err %d)\n", err);
    		return;
    	}
    
    	printk("Scanning successfully started\n");
    }
    
    static void connected(struct bt_conn *conn, uint8_t err)
    {
    	char addr[BT_ADDR_LE_STR_LEN];
    
    	bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
    
    	if (err) {
    		printk("Failed to connect to %s (%u)\n", addr, err);
    
    		bt_conn_unref(default_conn);
    		default_conn = NULL;
    
    		start_scan();
    		return;
    	}
    
    	if (conn != default_conn) {
    		return;
    	}
    
    	printk("Connected: %s\n", addr);
    	k_work_submit(&ping_work);
    }
    
    static void disconnected(struct bt_conn *conn, uint8_t reason)
    {
    	char addr[BT_ADDR_LE_STR_LEN];
    
    	if (conn != default_conn) {
    		return;
    	}
    
    	bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
    
    	printk("Disconnected: %s (reason 0x%02x)\n", addr, reason);
    
    	bt_conn_unref(default_conn);
    	default_conn = NULL;
    
    	start_scan();
    }
    
    BT_CONN_CB_DEFINE(conn_callbacks) = {
    	.connected = connected,
    	.disconnected = disconnected,
    };
    
    int main(void)
    {
    	int err;
    
    	err = bt_enable(NULL);
    	if (err) {
    		printk("Bluetooth init failed (err %d)\n", err);
    		return 0;
    	}
    
    	printk("Bluetooth initialized\n");
    
    	start_scan();
    	return 0;
    }
    

  • I still got 127 after I use the work queue unless I add some dealy in check_rssi_and_disconnect() or call check_rssi_and_disconnect() from main loop.

    In the both situation, printk("fail getting conn handle") did not get exectuted.

Related