nRF52840 as Central and Peripheral concurrent

Developing nRF52840-based devices that needs to act as both BLE Central and Peripheral.  

I've seen examples for the Multi-Link Multi-Role aggregate , the NUS Multilink Star typology, and the Heart Rate Relay.  They all seem to dedicate a single node/device to act as the Central/Peripheral and then have other Peripherals (only) or Centrals (only) connecting to them. 

The idea for my final implementation is to have x number of devices receive commands from a mobile app (similar to how the aggregate example demonstrates).  Just imagine something simple like a solitary LED changing color.  I'd like to let the user pick from a list which light to blink.  I would like to have all my devices be Multi-Role (both Central and Peripherals) and be able to connect to one another to distribute the commands (because the phone can only connect to one peripheral at a time). 

I will not know how many devices the end user will have, it could be two, it could be a hundred. And there would be no dedicated central other than the phone.

I understand the connection limitation of one nRF52840 is 20, however it's also mentioned that each of those 20 could connect to 20 more, and so on and so on. So that one device could connect to 20 and each of those 20 to 20 more ( creating a small network). 

So my questions are: 

  1. Could all my devices be both Central and Peripheral? 
    1. Meaning they'd share the same base code, same device name, same services, etc.
    2. Imagine the heart rate relay, only they are all acting as the relays, make sense?
  2. If this is possible, how do the devices determine who is central to what peripheral?
    1. If I'm looking at the aggregate example, it's listing in the mobile app all the available devices that are connected to the aggregate.
      1. So if I have two aggregate devices, who would be the primary central?
      2. And would they both be able to pass on their lists of devices to the mobile app?

It seems to me this should be rather simple, but I can't find an example that shows this being possible. 

Am I making this more complicated than it needs to be?

If this isn't clear, let me know so I can clarify. 

Thank you!

  • Hello,

    Please share which SDK you are trying or familiar with. You can take a look at BLE_relay_Example from our old SDK(if you are familiar with nRF5 SDK). This example will give an idea on how to implement both advertising and central role simultaneously. 

    Could all my devices be both Central and Peripheral? 
    1. Meaning they'd share the same base code, same device name, same services, etc.
    2. Imagine the heart rate relay, only they are all acting as the relays, make sense?

    It is possible to switch between the central and peripheral role but I am not sure how you are implementing this. Like how you trigger the switching?

    If this is possible, how do the devices determine who is central to what peripheral?
    1. If I'm looking at the aggregate example, it's listing in the mobile app all the available devices that are connected to the aggregate.
      1. So if I have two aggregate devices, who would be the primary central?
      2. And would they both be able to pass on their lists of devices to the mobile app?

    Will there be multiple central devices at a time? If so you need to come up with some algorithm which filter the peripherals they want to connect based on some ID or using some BLE services which alert the Central.

    I understand the connection limitation of one nRF52840 is 20, however it's also mentioned that each of those 20 could connect to 20 more, and so on and so on. So that one device could connect to 20 and each of those 20 to 20 more ( creating a small network

    Can you point me from where you read this?. Just for my clarity, I wanted to know whether they mentioned anything about data throughput in such connections.

    Kind Regards,

    Abhijith

  • Sorry for the delayed response. I wanted to go back thru some of the examples and try to build some test code. 

    Please share which SDK you are trying or familiar with.

    I'm using the nRF5 SDK 17.0.2 (S140 SoftDevice v7.2.0) 

    Can you point me from where you read this?. Just for my clarity, I wanted to know whether they mentioned anything about data throughput in such connections.

    https://infocenter.nordicsemi.com/index.jsp?topic=%2Fsdk_nrf5_v17.0.2%2Findex.html

    Will there be multiple central devices at a time? If so you need to come up with some algorithm which filter the peripherals they want to connect based on some ID or using some BLE services which alert the Central.

    yes, there will be multiple multirole devices. I am currently using the device name as the filter.

    It is possible to switch between the central and peripheral role but I am not sure how you are implementing this. Like how you trigger the switching?

    Here's a diagram I hope will clarify what I'm trying to do:

    Let's say I have 3 identical devices, Device A, B, & C. They have the same code, same name, same services, same everything.  For this example let's say Device A will be connected to the Phone and act as a Central to other devices. It will create a list of it's connected devices and pass it to the phone (the same way the aggregate example does). 

    void app_aggregator_on_central_connect(const ble_gap_evt_t *ble_gap_evt, connected_device_info_t *con_dev_info)
    {
        uint16_t conn_handle = ble_gap_evt->conn_handle;
        
        // Update local device list
        device_connected(conn_handle, con_dev_info);
        
        // Send info to central device (if connected)
        tx_command_payload[0] = AGG_BLE_LINK_CONNECTED;
        tx_command_payload[1] = ble_gap_evt->conn_handle >> 8;
        tx_command_payload[2] = ble_gap_evt->conn_handle & 0xFF;
        tx_command_payload[3] = con_dev_info->dev_type & 0xFF;
        tx_command_payload[4] = 0; //Button state
        tx_command_payload[5] = 1; // LED state;
        tx_command_payload[6] = 0xFF; // Color R
        tx_command_payload[7] = 0xFF; // Color G
        tx_command_payload[8] = 0xFF; // Color B
        tx_command_payload[9] = 0; // RSSI
        tx_command_payload[10] = con_dev_info->phy; // PHY
        if(strlen(con_dev_info->dev_name) <= MAX_ADV_NAME_LENGTH)
        {
            memcpy(&tx_command_payload[11], con_dev_info->dev_name, strlen(con_dev_info->dev_name));
            tx_command_payload_length = 11 + strlen(con_dev_info->dev_name);
        }
        else 
        {
            tx_command_payload_length = 11;
        }
        cmd_buffer_put(tx_command_payload, tx_command_payload_length);
    }

    static uint16_t device_list_search(uint16_t conn_handle)
    {
        for(int i = 0; i < MAX_NUMBER_OF_LINKS; i++)
        {
            if(m_link_info_list[i].conn_handle == conn_handle) return i;
        }
        return BLE_CONN_HANDLE_INVALID;
    }
    
    static uint16_t device_list_find_available()
    {
        return device_list_search(BLE_CONN_HANDLE_INVALID);
    }
    
    static void device_connected(uint16_t conn_handle, connected_device_info_t *con_dev_info)
    {
        if(device_list_search(conn_handle) == BLE_CONN_HANDLE_INVALID)
        {
            uint16_t new_device_index;
            new_device_index = device_list_find_available();
            if(new_device_index != 0xFFFF)
            {
                uint32_t device_name_length;
                m_link_info_list[new_device_index].conn_handle = conn_handle;
                m_link_info_list[new_device_index].device_type = con_dev_info->dev_type; 
                m_link_info_list[new_device_index].button_state = 0; 
                m_link_info_list[new_device_index].led_state = 1; 
                m_link_info_list[new_device_index].led_color[0] = 0xFF;
                m_link_info_list[new_device_index].led_color[1] = 0xFF;
                m_link_info_list[new_device_index].led_color[2] = 0xFF;
                device_name_length = (strlen(con_dev_info->dev_name) > MAX_ADV_NAME_LENGTH) ? MAX_ADV_NAME_LENGTH : strlen(con_dev_info->dev_name);
                memcpy(m_link_info_list[new_device_index].adv_name, con_dev_info->dev_name, device_name_length);
                for(int i = device_name_length; i < MAX_ADV_NAME_LENGTH; i++) m_link_info_list[new_device_index].adv_name[i] = ' ';
                m_link_info_list[new_device_index].adv_name[MAX_ADV_NAME_LENGTH - 1] = 0;
                m_link_info_list[new_device_index].rf_phy = con_dev_info->phy;
                m_link_info_list[new_device_index].last_rssi = 0;
                m_schedule_device_list_print = true;
            }
            else m_error_flags |= 1 << APP_AGG_ERROR_LINK_INFO_LIST_FULL;
        }
        else m_error_flags |= 1 << APP_AGG_ERROR_CONN_HANDLE_CONFLICT;
    }
    

    In this way Device A only creates the list of devices connected directly to it. So in the diagrams above it would only pass Device B & C, or it would only pass Device C. Correct?

    I would like to forward the additional device lists thru each corresponding device until it reaches Device A and then passes the list along to the phone (as the Central List shows in the diagram above).

    The phone should receive the list and should be able to send commands back to each device individually. For example I want to use the phone to blink a light on Device X. How would I go about this?

    Is it simply a matter of somehow merging the lists as it goes thru each device?

    Is there an example that shows how to forward information thru multiple devices to reach the Central/Phone?

    Would it require creating a new client / server service?

    Any direction would be appreciated. Thx.

    Please let me know if anything was unclear so I can try to explain further.

    As an aside:

    So if I have two aggregate devices, who would be the primary central?

    While testing with 3+ devices (based on the Nordic Aggregate example) I observed the order in which the devices connect (central to peripheral) seem to happen at random, either because 

    1.  the device was the first to scan / advertise or...
    2.  it had previously made a connection

    SO it just seems to be "luck of the draw". Whoever get's there first, gets to be in charge.

  • Hello,

    Sorry for the long response time. I was on my vacation for the last few days.

    littleboteng said:
    For this example let's say Device A will be connected to the Phone and act as a Central to other devices. It will create a list of it's connected devices and pass it to the phone (the same way the aggregate example does). 

    Device A will be acting as Central for both B&C while it will be peripheral to the Phone. Is this right? If so, it is possible. The example I pointed in my last reply is a good starting point, where the device works as both central and peripheral at a time.

    From the image I can see that most devices have multiple connection and will also act as both central and peripheral. In this case you need to think about the data throughput which is the number of packets which can be transmitted in one connection event.
    The link you provided is pointing to the index page please use the copy url tab in the page in order point to the correct page.

    Kind Regards,

    Abhijith

  • Thank you for all your help. 

    I was able to get the devices working as both Central and Peripheral without any issues. 

    Since I was saving information for each of the devices in the central, it was consuming a lot of memory.  Due to the memory constraints, I decided it would be best to pursue a different approach. It was suggested I could use mesh, but my devices are in close proximity to one another, so instead I will simply use a beaconing method.  

    Thanks again, to everyone on the Nordic Team Slight smile

  • Hi  I'm searching for a solution which is similar to your question. I also follow ble_aggregator example as a reference. However, I'm still confused on how the central device handles multiple peripheral devices and then acts as a peripheral one to send data to a phone app. Searching solution for several days, seems very few people work on a nRF52 acts both peripheral and central device.

    Please advise!

Related