Try to set up 2 Initiators with Channel Sounding

I’m currently working on a setup with two Initiators and one Reflector using the Channel Sounding sample.
My goal is to get distance measurements either simultaneously or, if not possible, automatically alternating between the two initiators (without manual reset).

At the moment, I’ve:

  • Flashed the iniator sample on two different dev kits ( which are my two initiators)

  • Adjusted the prj.conf files to include what seemed relevant for multiple connections (see below).

  • Flashed one reflector device with its own configuration.

Everything builds and flashes correctly, and both initiators can measure distance — but only one at a time.
If one initiator is connected, the other cannot start measuring unless I reset the first one.

I would like some guidance on what modifications might be required (either in the main.c of the initiator or reflector, or in the configuration files) to allow both initiators to perform measurements without manual reset.

Here are my current configurations:

#
# Copyright (c) 2024 Nordic Semiconductor ASA
#
# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
#
#Initiators

CONFIG_NCS_SAMPLES_DEFAULTS=y
CONFIG_DK_LIBRARY=y

CONFIG_BT=y
CONFIG_BT_SMP=y
CONFIG_BT_CENTRAL=y
CONFIG_BT_MAX_CONN=2
CONFIG_BT_BONDABLE=n

CONFIG_BT_GATT_CLIENT=y
CONFIG_BT_GATT_DYNAMIC_DB=y

CONFIG_BT_CHANNEL_SOUNDING=y
CONFIG_BT_RAS=y
CONFIG_BT_RAS_RREQ=y

CONFIG_BT_SCAN=y
CONFIG_BT_SCAN_FILTER_ENABLE=y
CONFIG_BT_SCAN_UUID_CNT=1

# The Ranging Profile recommends a MTU of at least 247 octets.
CONFIG_BT_L2CAP_TX_MTU=498
CONFIG_BT_BUF_ACL_TX_SIZE=502
CONFIG_BT_BUF_ACL_RX_SIZE=502
CONFIG_BT_ATT_PREPARE_COUNT=3
CONFIG_BT_CTLR_DATA_LENGTH_MAX=251

# This reduces RAM usage. Additional RAM is needed to support optional
# features such as mode 3 or multiantenna. Change or remove these if
# using those features
CONFIG_BT_RAS_MODE_3_SUPPORTED=n
CONFIG_BT_RAS_MAX_ANTENNA_PATHS=1
CONFIG_BT_CTLR_SDC_CS_MAX_ANTENNA_PATHS=1
CONFIG_BT_CTLR_SDC_CS_NUM_ANTENNAS=1
CONFIG_BT_CTLR_SDC_CS_STEP_MODE3=n
CONFIG_BT_CTLR_SDC_CS_ROLE_INITIATOR_ONLY=y

# Disabling the CS Test command reduces flash usage
CONFIG_BT_CTLR_CHANNEL_SOUNDING_TEST=n

# This allows CS and ACL to use different PHYs
CONFIG_BT_TRANSMIT_POWER_CONTROL=y
CONFIG_BT_CTLR_TX_PWR_PLUS_4=y
# CONFIG_BT_CTLR_TX_PWR_PLUS_8=y

# This improves the performance of floating-point operations
CONFIG_FPU=y
CONFIG_FPU_SHARING=y

CONFIG_CBPRINTF_FP_SUPPORT=y

CONFIG_BT_CS_DE=y
CONFIG_BT_CS_DE_512_NFFT=y

#
# Copyright (c) 2024 Nordic Semiconductor ASA
#
# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
#

CONFIG_NCS_SAMPLES_DEFAULTS=y
CONFIG_DK_LIBRARY=y

CONFIG_BT=y
CONFIG_BT_PERIPHERAL=y
CONFIG_BT_SMP=y
CONFIG_BT_DEVICE_NAME="Nordic CS Reflector"
CONFIG_BT_MAX_CONN=2
CONFIG_BT_GAP_AUTO_UPDATE_CONN_PARAMS=n
CONFIG_BT_BONDABLE=n

CONFIG_BT_CTLR_SDC_CS_COUNT=2
CONFIG_BT_MAX_PAIRED=2
CONFIG_BT_CTLR_SDC_PERIPHERAL_COUNT=2

# The Ranging Profile recommends a MTU of at least 247 octets.
CONFIG_BT_L2CAP_TX_MTU=498
CONFIG_BT_BUF_ACL_TX_SIZE=502
CONFIG_BT_BUF_ACL_RX_SIZE=502
CONFIG_BT_CTLR_DATA_LENGTH_MAX=251
CONFIG_BT_CTLR_PHY_2M=y

# This reduces RAM usage. Additional RAM is needed to support optional
# features such as mode 3 or multiantenna. Change or remove these if
# using those features
CONFIG_BT_RAS_MODE_3_SUPPORTED=n
CONFIG_BT_RAS_MAX_ANTENNA_PATHS=1
CONFIG_BT_CTLR_SDC_CS_MAX_ANTENNA_PATHS=1
CONFIG_BT_CTLR_SDC_CS_NUM_ANTENNAS=1
CONFIG_BT_CTLR_SDC_CS_STEP_MODE3=n
CONFIG_BT_CTLR_SDC_CS_ROLE_REFLECTOR_ONLY=y

# Disabling the CS Test command reduces flash usage
CONFIG_BT_CTLR_CHANNEL_SOUNDING_TEST=n

# This allows CS and ACL to use different PHYs
CONFIG_BT_TRANSMIT_POWER_CONTROL=y
# CONFIG_BT_CTLR_TX_PWR_PLUS_4=y
CONFIG_BT_CTLR_TX_PWR_PLUS_8=y

CONFIG_BT_CHANNEL_SOUNDING=y
CONFIG_BT_RAS=y
CONFIG_BT_RAS_RRSP=y

Thank you for your help and time

Parents Reply Children
  • Thank you Elfving, I followed your advice and did the BLE course.

    You would need to start a connection with a new one.

    do you mean that I need to create two different initiator applications?

    From what I understand, each initiator would act as a separate central device, and the reflector would be the peripheral.

    Would it be easier instead to have two advertising peripheral devices (i.e., two reflectors) and one initiator that connects to them alternately?

    Thank you for your help, 
    Regards

    Fhar

  • Note that CS roles are independent from Bluetooth roles so you can have a device be central and reflectors as well as peripheral and initiator. This option makes it easier for one moveable battery powered device to work with multiple mains powered (or bigger battery option) devices as all the processing is kept of the smaller device while still allowing one device to set the Bluetooth timing to all nodes. If you have 2+ centrals then the single peripheral will not have control of timing and collisions are likely to occur.

    The Bluetooth stack in the nRF Connect SDK already supports this and we have seen people build such solutions running with concurrent connections already, it's just a question about setting up the timing correctly.

  • Hi Paka, 

    Thank you again for your explaination. I would like to follow the approach now (1 initiator (central) / 2 reflectors(peripherals)), but I’m still struggling a bit with the concrete implementation.

    Would the main changes need to be done primarily in int main() in the main.c of the initiator? For example, should all the Channel Sounding procedures be moved into a loop to alternate between the two reflectors? 

    My initial idea was to scan the reflectors, store them in an array, and then alternate between connecting and disconnecting to perform measurements. However, I’m unsure how and where in the code this should be implemented.

    I’m still new to this type of technology, so I really appreciate any guidance or advice you can give.

    Thank you very much for your time and help!

    Best regards,
    Fhar

  • Hi again Fhar,

    Fhar said:
    do you mean that I need to create two different initiator applications?

    Well, maybe that is something you need. But that was not what I meant. I just meant that if you had one initiator and multiple reflectors then you would need to first connect to reflector A, and do a ranging with that one, then disconnect to that one. Afterwards you can then do the same to reflector B. 

    Entering a connection with one, then starting a connection with another is what I figured would be nicely introduced in the BLE course. 

    Though actually now, like Paka briefly mentioned, there is support for concurrent connections in SDK (given that you use the newest SDK), though the samples are apparently not set-up to take advantage of this yet. I am bit uncertain about how this is done, so the sequential way might still be an idea.

    Fhar said:
    Would the main changes need to be done primarily in int main() in the main.c of the initiator? For example, should all the Channel Sounding procedures be moved into a loop to alternate between the two reflectors? 

    Something like a loop might be an idea. Or a workqueue. Though I think the best first step would be to try to disconnect from the reflector. And then try to reconnect to another one.

    I see that I might have to make a demo of this myself. I'll look into that next week.

    Regards,

    Elfving

  • Hi Elfving,

    Thanks for your advice! I managed to make it work with 1 initiator 2 reflector & 2 initiators and 1 reflector (using the same code) using a loop: I scan and store reflectors’ addresses, then connect sequentially and a function which handles the full Channel Sounding procedure for the current connection—setting security, performing discovery, configuring CS parameters, enabling the procedure, and collecting distance measurements—before disconnecting.

    It works, but I sometimes see stack overflow/semaphore issues. Could you clarify how a workqueue should be used here to avoid this?

    Thank you very much, 

    Fhar

Related