Many-to-one sensor collector topology, which BLE sample is better to modify?

Hi, 

1) I want to collect sensor data using BLE like the following topology, the sensor devices are battery-powered, which sample in the NCS is suitable to modify?

2) Does NUS central/peripheral can do many-to-one topology in this usage? or need to use BLE mesh?

Parents
  • Hello,

    I think the peripheral/central_uart samples is a good starting point for this. I wrote an answer to a similar question just a couple of weeks ago. It was in a private ticket, but I'll paste it here:

    -------------

    I am not aware of any official samples that will connect to multiple peripherals, but it is indeed possible. To get started, I would use the peripheral and central sample that are closest to what you want to use. E.g. the peripheral_uart and central_uart are good starting points. 

    While it is not official, a colleague of mine has a multi-nus sample, which is basically a central that can connect to multiple peripherals. You can have a look at it for inspiration:

    https://github.com/NordicMatt/multi-NUS/tree/master

    You can see that it has some functions for sending messages to one particular peripheral, or multiple. But in theory, all you need to do is to do some changes in prj.conf of the central_uart sample:

    CONFIG_BT_MAX_CONN=20
    CONFIG_BT_MAX_PAIRED=20
    CONFIG_BT_CONN_CTX=y

    This will allow it to connect to up to 20 devices. Then your app needs to keep track of how many connections it has, and resume scanning if the maximum is not reached. You don't need CONFIG_BT_MAX_PAIRED if you are not going to use pairing (encryption). 

    Another thing that you need to do is to look at the way that the central_uart sample keeps track of the connection pointer, bt_conn *default_conn. In the connected() callback, which triggers when the device enters a connection. This particular example sets the default_conn pointer in it's scan_connecting() callback, but you can do it in the connected() callback. And in your case, you need to have an array of bt_conn pointers. As many as the maximum number of simultaneous connections. Then set them using bt_conn_ref() when you enter a new connection, and unset them using bt_conn_unref() when you disconnect. 

    It may also be a good idea to have this conn pointer as an input in the function that you use to send data, like the bt_nus_client_send(). This sample in particular doesn't do that, because it assumes only one connection, and this is set in the nus_client parameter, but you can see how it uses the conn pointer inside bt_nus_client_send():

    	err = bt_gatt_write(nus_c->conn, &nus_c->rx_write_params);

    So that you send the message to the intended peripheral. You can see how it is done in the multi-nus example (link to github above).

    -------------

    So there is a description on how to make the central have multiple concurrent connections. When sending data the other way, you can look at the conn* pointer in the callback to see what device the data is coming from. 

    Also, in general, Bluetooth Mesh is probably not the solution you are looking for. It will work, but the power consumption is a lot higher than in a BLE application. So since you mentioned that they will be battery powered, I recommend using normal BLE.

    Best regards,

    Edvin

  • Hi,

    1) Does the github multi-nus sample base on ncs v2.6.1 central_uart project to modify? There are many differences compared to v2.6.1 sample except multi-nus functions.

    2) I am still failed to port multi-nus to v2.9.0 central_uart project, it can't connect one peripheral for more than 5s, the central will crash. Is there any other Connection Context Library sample for reference?

    add 

        struct bt_nus_client *nus_client = bt_conn_ctx_alloc(&conns_ctx_lib, conn);
    to connected() cause central crash. The RTT log as the following,
    00> [00:00:00.016,021] <inf> fs_nvs: 2 Sectors of 4096 bytes
    00> [00:00:00.016,021] <inf> fs_nvs: alloc wra: 0, fd0
    00> [00:00:00.016,052] <inf> fs_nvs: data wra: 0, 1c
    00> [00:00:00.016,174] <inf> bt_sdc_hci_driver: SoftDevice Controller build revision: 
    00>                                             2d 79 a1 c8 6a 40 b7 3c  f6 74 f9 0b 22 d3 c4 80 |-y..j@.< .t.."...
    00>                                             74 72 82 ba                                      |tr..             
    00> [00:00:00.020,080] <inf> bt_hci_core: HW Platform: Nordic Semiconductor (0x0002)
    00> [00:00:00.020,111] <inf> bt_hci_core: HW Variant: nRF52x (0x0002)
    00> [00:00:00.020,172] <inf> bt_hci_core: Firmware: Standard Bluetooth controller (0x00) Version 45.41337 Build 3074452168
    00> [00:00:00.020,812] <inf> bt_hci_core: No ID address. App must call settings_load()
    00> [00:00:00.020,843] <inf> central_uart: Bluetooth initialized
    00> [00:00:00.021,606] <inf> bt_hci_core: Identity: F2:76:DA:88:7F:67 (random)
    00> [00:00:00.021,636] <inf> bt_hci_core: HCI: version 6.0 (0x0e) revision 0x106b, manufacturer 0x0059
    00> [00:00:00.021,667] <inf> bt_hci_core: LMP: version 6.0 (0x0e) subver 0x106b
    00> [00:00:00.022,888] <inf> central_uart: Scan module initialized
    00> [00:00:00.027,709] <inf> central_uart: Scanning successfully started L913
    00> [00:00:00.178,436] <inf> central_uart: Filters matched. Address: C1:69:8A:90:CB:FC (random) connectable: 0
    00> [00:00:00.282,379] <inf> central_uart: Connected: C1:69:8A:90:CB:FC (random)
    00> [00:00:00.287,261] <err> central_uart: Stop LE scan failed (err 0)
    00> [00:00:00.483,978] <inf> central_uart: MTU exchange done
    00> [00:00:00.583,892] <err> bt_smp: pairing failed (peer reason 0x3)
    00> [00:00:00.584,136] <wrn> central_uart: Security failed: C1:69:8A:90:CB:FC (random) level 1 err 4 
    00> [00:00:00.584,350] <wrn> central_uart: Pairing failed conn: C1:69:8A:90:CB:FC (random), reason 4 
    00> [00:00:01.283,813] <inf> central_uart: Service discovery completed
    00> [00:00:01.285,034] <inf> central_uart: Scanning successfully started L492
    00> [00:00:01.383,819] <err> os: ***** USAGE FAULT *****
    00> [00:00:01.383,819] <err> os:   Illegal use of the EPSR
    00> [00:00:01.383,850] <err> os: r0/a1:  0x20002650  r1/a2:  0x20010450  r2/a3:  0x00000000
    00> [00:00:01.383,850] <err> os: r3/a4:  0x00000000 r12/ip:  0x20010464 r14/lr:  0x0002f739[0m
    00> [00:00:01.383,880] <err> os:  xpsr:  0x60000000
    00> [00:00:01.383,880] <err> os: Faulting instruction address (r15/pc): 0x00000000
    00> [00:00:01.383,911] <err> os: >>> ZEPHYR FATAL ERROR 35: Unknown error on CPU 0
    00> [00:00:01.383,941] <err> os: Current thread: 0x200025b0 (unknown)
    00> [00:00:01.662,384] <err> os: Halting system
  • Can you please zip and send the entire central application that you are testing?

    BR,
    Edvin

  • Hi,

    The key difference is in gatt_discover(), the NCS v2.9.0 is

    	err = bt_gatt_dm_start(conn,
    			       BT_UUID_NUS_SERVICE,
    			       &discovery_cb,
    			       &nus_client);

    the multi-NUS version is,

     
    	err = bt_gatt_dm_start(conn,
    					BT_UUID_NUS_SERVICE,
    					&discovery_cb,
    					nus_client);
    the multi-NUS version does not have the address-of operator before nus_client, 
    so how to fix multi-NUS sample to run in NCS v2.9.0?
    I attached the project on the following,
  • Hello,

    I ran the sample that you attached just now, and this is what it prints over UART:

    *** Booting nRF Connect SDK v2.9.0-7787b2649840 ***
    *** Using Zephyr OS v3.7.99-1f8f3dc29142 ***
    felix multi-nus central
    Starting Bluetooth Central UART example
    central : Connected CE:20:8F:A0:A2:4D (random), number: 0
    num_nus_conns = 3, L687
    NUS Client module initializedService discovery completed
    Scanning successfully started L514
    ctx->data = 0x2000a0e8
    nus=0x2000a0e8
    i = 0
    central : Connected E3:4A:AE:AC:E6:6E (random), number: 1
    num_nus_conns = 3, L687
    NUS Client module initializedService discovery completed
    Scanning successfully started L514
    ctx->data = 0x2000a0e8
    nus=0x2000a12c
    ctx->data != nus
    ctx->data = 0x2000a12c
    nus=0x2000a12c
    i = 1
    

    Then the two devkits programmed with the default peripheral_uart prints this:

    *** Booting My Application v2.9.0-0a85ae2bebaa ***
    *** Using nRF Connect SDK v2.9.0-7787b2649840 ***
    *** Using Zephyr OS v3.7.99-1f8f3dc29142 ***
    Starting Nordic UART service example
    00
    

    *** Booting My Application v2.9.0-0a85ae2bebaa ***
    *** Using nRF Connect SDK v2.9.0-7787b2649840 ***
    *** Using Zephyr OS v3.7.99-1f8f3dc29142 ***
    Starting Nordic UART service example
    00
    

    So apparently, it does pass the check "if (ctx->data == nus)"

    James168 said:
    the multi-NUS version does not have the address-of operator before nus_client, 

    The reason for this is that in the multinus application, the nus_client is declared as a pointer, so it already points to the address. 

    Do you not see the same log?

    Best regards,

    Edvin

  • I don't notice they are declared for different type, one is non-pointer,

    static struct bt_nus_client nus_client;
    the other is pointer,
    struct bt_nus_client *nus_client = bt_conn_ctx_get(&conns_ctx_lib, conn);
    I have no problem for this issue now.
  • Hi,

    The first peripheral_uart after reset failed to reconnect to central_uart.

    *** Booting nRF Connect SDK v2.9.0-7787b2649840 ***
    *** Using Zephyr OS v3.7.99-1f8f3dc29142 ***
    Starting Bluetooth Central UART example
    ********** bt_scan_start, err=0, L967
    Scanning successfully started
    central : Connected C1:69:8A:90:CB:FC (random), connected number: 1
    NUS Client module initialized
    ********** bt_scan_stop, L711
    Stop LE scan failed (err 0)
    gatt_discover(), err=0, L623
    ********** bt_scan_start, err=0, L502
    ctx->data = 0x2000a0e8
    nus=0x2000a0e8
    i = 0
    discovery_complete(), err=0, L565
    central : Connected F1:75:4A:A8:7E:11 (random), connected number: 2
    NUS Client module initialized
    ********** bt_scan_stop, L711
    Stop LE scan failed (err 0)
    gatt_discover(), err=0, L623
    ********** bt_scan_start, err=0, L502
    ctx->data = 0x2000a0e8
    nus=0x2000a12c
    ctx->data != nus
    ctx->data = 0x2000a12c
    nus=0x2000a12c
    i = 1
    discovery_complete(), err=0, L565
    central : Disconnected C1:69:8A:90:CB:FC (random), connected num: 1

    C1:69:8A:90:CB:FC connects to central (line 6~line 15), then F1:75:4A:A8:7E:11 connects to central (line 16~line28). press the reset button of C1:69:8A:90:CB:FC, it disconnects (line 29), but it can't reconnect to central.

    I attach the project as the following, just add some debug message.

    central_uart_v290_multi_nus_250311_reconnect_fail.7z

Reply
  • Hi,

    The first peripheral_uart after reset failed to reconnect to central_uart.

    *** Booting nRF Connect SDK v2.9.0-7787b2649840 ***
    *** Using Zephyr OS v3.7.99-1f8f3dc29142 ***
    Starting Bluetooth Central UART example
    ********** bt_scan_start, err=0, L967
    Scanning successfully started
    central : Connected C1:69:8A:90:CB:FC (random), connected number: 1
    NUS Client module initialized
    ********** bt_scan_stop, L711
    Stop LE scan failed (err 0)
    gatt_discover(), err=0, L623
    ********** bt_scan_start, err=0, L502
    ctx->data = 0x2000a0e8
    nus=0x2000a0e8
    i = 0
    discovery_complete(), err=0, L565
    central : Connected F1:75:4A:A8:7E:11 (random), connected number: 2
    NUS Client module initialized
    ********** bt_scan_stop, L711
    Stop LE scan failed (err 0)
    gatt_discover(), err=0, L623
    ********** bt_scan_start, err=0, L502
    ctx->data = 0x2000a0e8
    nus=0x2000a12c
    ctx->data != nus
    ctx->data = 0x2000a12c
    nus=0x2000a12c
    i = 1
    discovery_complete(), err=0, L565
    central : Disconnected C1:69:8A:90:CB:FC (random), connected num: 1

    C1:69:8A:90:CB:FC connects to central (line 6~line 15), then F1:75:4A:A8:7E:11 connects to central (line 16~line28). press the reset button of C1:69:8A:90:CB:FC, it disconnects (line 29), but it can't reconnect to central.

    I attach the project as the following, just add some debug message.

    central_uart_v290_multi_nus_250311_reconnect_fail.7z

Children
  • You are getting the scan_connecting_error() callback, meaning that it attempted to reconnect to the device, but failed. Not exactly sure why this happens, but you can start scanning again inside this callback:

    static void scan_connecting_error(struct bt_scan_device_info *device_info)
    {
        int err;
    	LOG_WRN("Connecting failed");
        err = bt_scan_start(BT_SCAN_TYPE_SCAN_ACTIVE);
        if (err) {
            printk("started to scan again. Ret: %d\n", err);
        }
    }

    That fixed it for me, at least.

    Oh, and I see that you experimented with logging. By default, this sample uses RTT logging, in case you were not aware. So if you open an RTT terminal, such as JLink RTT Viewer (Part of the JLink bundle from Segger.com), and connect to your board, you should see the log. You need to reconnect the RTT viewer every time you recompile and flash the board, because it needs to look for the new location of the RTT buffer in RAM. 

    Best regards,

    Edvin

  • To add bt_scan_start() to callback function scan_connecting_error() still fail to reconnect sometime, and the original multi-NUS sample has the same error even modify scan_connectiing_error(). 

    The connect context library seems unstable.

  • Yes, I noticed. Not sure whether it is the peripheral not picking up the connection requests, or if it is the scheduling of the scanning/connecting that fails. I will try to capture a sniffer trace to see if I can find anything on air. I'll do it later today if I have time. If not, tomorrow. 

    Best regards,

    Edvin

  • Sorry, I was unable to go into the office today. I will look into it next week.

    I'm sorry for the inconvenience.

    Best regards,

    Edvin

Related