I would like for the high duty cycle direct advertising to restart immediately after the ~1.2s timeout.
[I'm using Zephyr. I'm also really new to programming these devices]
I've tried to modify the direct_adv example (to use high duty cycle & restart after timeout).
Below are the parts of my code that differ from the original example:
static void connected(struct bt_conn *conn, uint8_t err) { if (err) { printk("Connection failed (err 0x%02x)\n", err); printk("Stopping advertising...?\n"); int err_stop; err_stop = bt_le_adv_stop(); printk("Error code: %d\n",err_stop); int err_dis; err_dis = bt_conn_disconnect(conn,BT_HCI_ERR_REMOTE_USER_TERM_CONN); printk("Attempted to disconnect/end connection (%d)\n", err_dis); printk("Attempting to unreference connection...\n"); bt_conn_unref(conn); //try to fix 'bt_conn_exists_le: Found valid connection in disconnected state' error } else { printk("Connected\n"); } }
static void bt_ready(void) { int err; char addr[BT_ADDR_LE_STR_LEN]; printk("Bluetooth initialized\n"); printk("Wait two seconds...\n"); k_sleep(K_SECONDS(2)); printk("Load settings\n"); if (IS_ENABLED(CONFIG_SETTINGS)) { settings_load(); } bt_addr_le_copy(&bond_addr, BT_ADDR_LE_NONE); bt_foreach_bond(BT_ID_DEFAULT, copy_last_bonded_addr, NULL); /* Address is equal to BT_ADDR_LE_NONE if compare returns 0. * This means there is no bond yet. */ if (bt_addr_le_cmp(&bond_addr, BT_ADDR_LE_NONE) != 0) { bt_addr_le_to_str(&bond_addr, addr, sizeof(addr)); printk("Direct advertising to %s\n", addr); //Previously used low-duty: //adv_param = *BT_LE_ADV_CONN_DIR_LOW_DUTY(&bond_addr); //now using: (this will be high duty) adv_param = *BT_LE_ADV_CONN_DIR(&bond_addr); adv_param.options |= BT_LE_ADV_OPT_DIR_ADDR_RPA; err = bt_le_adv_start(&adv_param, NULL, 0, NULL, 0); } //[removed unmodified code for brevity] }
The bt_ready method is called every five seconds from main():
bt_ready(); bt_conn_auth_info_cb_register(&bt_conn_auth_info); while (1) { k_sleep(K_SECONDS(5)); bt_ready(); }
The log of the error:
*** Booting Zephyr OS build v3.2.99-ncs1 *** Bluetooth initialized Wait two seconds... [00:00:00.010,498] <inf> fs_nvs: nvs_mount: 6 Sectors of 4096 bytes [00:00:00.010,528] <inf> fs_nvs: nvs_mount: alloc wra: 0, fb0 [00:00:00.010,528] <inf> fs_nvs: nvs_mount: data wra: 0, c4 [00:00:00.010,650] <inf> sdc_hci_driver: hci_driver_open: SoftDevice Controller build revision: 6d 90 41 2a 38 e8 ad 17 29 a5 03 38 39 27 d7 85 |m.A*8... )..89'.. 1f 85 d8 e1 |.... [00:00:00.013,336] <inf> bt_hci_core: hci_vs_init: HW Platform: Nordic Semiconductor (0x0002) [00:00:00.013,366] <inf> bt_hci_core: hci_vs_init: HW Variant: nRF52x (0x0002) [00:00:00.013,397] <inf> bt_hci_core: hci_vs_init: Firmware: Standard Bluetooth controller (0x00) Version 109.16784 Build 2917677098 [00:00:00.013,793] <inf> bt_hci_core: bt_init: No ID address. App must call settings_load() Load settings Direct advertising to C0:DC:DA:1F:C4:81 (public) Advertising successfully started [00:00:02.019,561] <inf> bt_hci_core: bt_dev_show_info: Identity: F8:9D:09:B3:40:09 (random) [00:00:02.019,592] <inf> bt_hci_core: bt_dev_show_info: HCI: version 5.3 (0x0c) revision 0x11fa, manufacturer 0x0059 [00:00:02.019,622] <inf> bt_hci_core: bt_dev_show_info: LMP: version 5.3 (0x0c) subver 0x11fa Connection failed (err 0x3c) Stopping advertising...? Error code: 0 Attempted to disconnect/end connection (-128) Attempting to unreference connection... Bluetooth initialized Wait two seconds... Load settings Direct advertising to C0:DC:DA:1F:C4:81 (public) Advertising failed to start (err -22) [00:00:09.033,905] <wrn> bt_hci_core: bt_hci_cmd_send_sync: opcode 0x2027 status 0x12 [00:00:09.033,935] <err> bt_id: bt_id_add: Failed to add IRK to controller [00:00:09.038,665] <wrn> bt_conn: bt_conn_exists_le: Found valid connection in disconnected state
The 'Connection failed (err 0x3c)' error is fine (this is BT_HCI_ERR_ADV_TIMEOUT: High duty cycle directed connectable advertiser started by bt_le_adv_start failed to be connected within the timeout). We expect that to happen almost straight away.
I want to then start the advertising again. I originally tried calling bt_ready from inside the connected() callback where the above error is reported. I now try from a loop inside main().
The problem is:
Advertising failed to start (err -22)
[00:00:09.033,905] <wrn> bt_hci_core: bt_hci_cmd_send_sync: opcode 0x2027 status 0x12
[00:00:09.033,935] <err> bt_id: bt_id_add: Failed to add IRK to controller
[00:00:09.038,665] <wrn> bt_conn: bt_conn_exists_le: Found valid connection in disconnected state
I clearly need to somehow either (a) remove the valid connection so it can restart, or (b) I need to figure out how to restart advertising on a valid connection?
I imagine this is quite straightforward!
[edit: here's a link to my full version of main.c]
Note on the application
I'm using BLE for a rather non-typical application: I'm doing insect tracking, and have a series of high-gain transmitters (at a remote field-site), each rotating, sending their angle, id and time in advertising packets. A BLE receiver on the bee detects these (and their signal strength) and can use this information to triangulate its location (the signal strength peaks when the antennas are pointing at it, for example). This info is stored and read off later, once the bee returns to the hive. To save energy, we need to allow the receiver (on the bee) to be disabled most of the time, so I want to use a much higher duty-cycle of packets from the transmitters (e.g. if the receiver is only on for 6ms, then I need the transmitters to send e.g. every 3ms). I've over simplified the approach, but I think that gives the idea.