nRF5340 Bluetooth advertising power consumption

Hello,

I'm working on an application which advertises a proprietary command-response service and I would like to optimize the power consumption. According to the online power profiler I should get as low as 36uA, but currently I am only able to achieve about 260uA. 

Is 260uA already the limit? Is there a way to set the application-core to a deeper sleep and wake up at bluetooth-events? Do I need to disable something additional in the device tree?

I was not able to find a sample achieving lower power consumption, is there any?

I'm using Nordic SDK 2.4 with zephyr on an nRF5340dk with the following sources.

 

# prj.conf

CONFIG_NCS_SAMPLES_DEFAULTS=y

CONFIG_BT=y
CONFIG_BT_PERIPHERAL=y
CONFIG_BT_DEVICE_NAME="NPP"

CONFIG_PM=y

// nrf5340dk_nrf5340_cpuapp_ns.overlay

&uart0 {
    status = "disabled";
};

&i2c1 {
    status = "disabled";
};

&spi4 {
    status = "disabled";
};

&adc {
    status = "disabled";
};

&pwm0 {
    status = "disabled";
};

&nfct {
    status = "disabled";
};

&usbd {
    status = "disabled";
};

&usbreg {
    status = "disabled";
};

// main.c



#include <zephyr/kernel.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 <stdint.h>
#include <errno.h>


static void bt_connected(struct bt_conn *conn, uint8_t err);
static void bt_disconnected(struct bt_conn *conn, uint8_t err);
static void response_ccc_cfg_changed(const struct bt_gatt_attr *attr, uint16_t value);
static ssize_t new_data(struct bt_conn *conn, const struct bt_gatt_attr *attr,
                const void *buf, uint16_t len, uint16_t offset, uint8_t flags);


const static char notify_msg[] = "notification";
const static char response_msg[] = "response";
static int notify_enabled = 0;
static int connected = 0;

const static struct bt_gatt_attr *response_attr = NULL;

static struct bt_conn_cb bt_conn_cb = {
    .connected = bt_connected,
    .disconnected = bt_disconnected,
};

#define MY_BT_UUID_VAL 				BT_UUID_128_ENCODE(0xDAE90050, 0x384C, 0x037A, 0x10B8, 0x21CD1C007486)
#define MY_BT_UUID_COMMAND_VAL 		BT_UUID_128_ENCODE(0xDAE90051, 0x384C, 0x037A, 0x10B8, 0x21CD1C007486)
#define MY_BT_UUID_RESPONSE_VAL 	BT_UUID_128_ENCODE(0xDAE90052, 0x384C, 0x037A, 0x10B8, 0x21CD1C007486)

#define MY_BT_UUID                	BT_UUID_DECLARE_128(MY_BT_UUID_VAL)
#define MY_BT_UUID_COMMAND        	BT_UUID_DECLARE_128(MY_BT_UUID_COMMAND_VAL)
#define MY_BT_UUID_RESPONSE       	BT_UUID_DECLARE_128(MY_BT_UUID_RESPONSE_VAL)

BT_GATT_SERVICE_DEFINE(svc,
    BT_GATT_PRIMARY_SERVICE(MY_BT_UUID),                           
    BT_GATT_CHARACTERISTIC(MY_BT_UUID_COMMAND, BT_GATT_CHRC_WRITE, 
                    BT_GATT_PERM_WRITE, NULL, new_data, NULL),  
    BT_GATT_CHARACTERISTIC(MY_BT_UUID_RESPONSE, BT_GATT_CHRC_NOTIFY, 
                    BT_GATT_PERM_NONE, NULL, NULL, NULL),
    BT_GATT_CCC(response_ccc_cfg_changed, BT_GATT_PERM_READ | BT_GATT_PERM_WRITE),  
);

static const struct bt_data ad[] = {
    BT_DATA_BYTES(BT_DATA_FLAGS, (BT_LE_AD_GENERAL | BT_LE_AD_NO_BREDR)),
    BT_DATA(BT_DATA_NAME_COMPLETE, CONFIG_BT_DEVICE_NAME, sizeof(CONFIG_BT_DEVICE_NAME)),
};
static const struct bt_data sd[] = {
    BT_DATA_BYTES(BT_DATA_UUID128_ALL, MY_BT_UUID_VAL),
};

#define ADV_PARAM BT_LE_ADV_PARAM(BT_LE_ADV_OPT_CONNECTABLE, BT_GAP_ADV_SLOW_INT_MIN, BT_GAP_ADV_SLOW_INT_MAX, NULL)


int main(void)
{
    response_attr = bt_gatt_find_by_uuid(svc.attrs, svc.attr_count, MY_BT_UUID_RESPONSE);

	bt_enable(NULL);
	bt_conn_cb_register(&bt_conn_cb);
	bt_le_adv_start((ADV_PARAM), ad, (ARRAY_SIZE(ad)), sd, (ARRAY_SIZE(sd)));
	return 0;
}



static void bt_connected(struct bt_conn *conn, uint8_t err) {
    connected++;
    return;
}

static void bt_disconnected(struct bt_conn *conn, uint8_t err) {
    connected--;
    return;
}

static void response_ccc_cfg_changed(const struct bt_gatt_attr *attr, uint16_t value) {
	if (value == BT_GATT_CCC_NOTIFY) {
		bt_gatt_notify(NULL, response_attr, notify_msg, sizeof(notify_msg));
		notify_enabled++;
	} else {
		notify_enabled--;
	}
    return;
}

static ssize_t new_data(struct bt_conn *conn, const struct bt_gatt_attr *attr,
                const void *buf, uint16_t len, uint16_t offset, uint8_t flags) {
	if (notify_enabled) {
		bt_gatt_notify(NULL, response_attr, response_msg, sizeof(response_msg));
	}
    return len;
}

The behavior of the application works fine.

Thank you in advance!

Best regards,

Sandro

Related