Failed to use BLE.disconnect() to communicate with three argon boards

Hi,

I would like to set up a BLE communication among three argon boards, one receiver and two transmitters.

I put the BLE.disconnect() at here:

void loop()
{
  static uint32_t msLastPrint = 0;
  if (millis() - msLastPrint < UPDATE_PERIOD_MS) return;
  msLastPrint = millis();
  
  if (firstTime == 0)//when firstTime is 0, the peer has no value
    firstTime = 1;
  else
    BLE.disconnect(peer);

  if (BLE.connected())
  {
    Serial.printlnf("flag service == %d", flagService);//flag indicate which service will be connected next.
  }

Questions:
1.It seems that BLE.disconnect(peer) doesn’t work as shown below, as the ''flag service == 1" can be printed out meaning BLE.connected() returns 1.
Not sure why might be the reason. Here flagService == 1 was set after connecting with service 2.

2.For another position for disconnect(), I received repeated data at the same time as shown below.

I am not sure what I can get from this weird output. Does it mean something wrong with the time period?

Thank you for your help.

Where have you peer defined and set?
Where are you connecting to the individual “services”?

Also you are setting firstTime to 1 potentially weven before BLE.connected() ever was true. Hence any subsequent disconnect won’t ever happen again.

I shouldn’t have to say it - as it should be 100% obvious - a better way would be to have a variable wasConnected which would be set when BLE.connected() became true and not just by some arbitrary iteration count. You also only need to disconnect when connected.

something along this line

int wasConnected = 0;

void loop()
{
  static uint32_t msLastPrint = 0;
  if (millis() - msLastPrint < UPDATE_PERIOD_MS) return;
  msLastPrint = millis();
  
  if (BLE.connected())
  {
    Serial.printlnf("flag service == %d", flagService);//flag indicate which service will be connected next.
    if (!wasConnected)             // on first connect
      wasConnected = 5;            // give it 5 iterations
    else if (1 == wasConnected--)  // after last iteration 
      BLE.disconnect(peer);        // disconnect
  }
}
2 Likes

Thanks so much, ScruffR.

Where have you peer defined and set?
Where are you connecting to the individual “services”?

The peer is defined above the setup() as shown below

BleCharacteristic valueCharacteristic;
BleScanResult scanResults[SCAN_RESULT_MAX];
// Peer is defined here
BlePeerDevice peer;

void onDataReceived(const uint8_t *data, size_t len, const BlePeerDevice &peer, void *context);

void setup()
{
  Mesh.off();
  Serial.begin();
  valueCharacteristic.onDataReceived(onDataReceived, NULL);
}

int flagService = 1;//showing whether it is going to connect with service 1 or 2.
int wasConnected = 0;

void loop()
{
  static uint32_t msLastPrint = 0;
  if (millis() - msLastPrint < UPDATE_PERIOD_MS) return;
  msLastPrint = millis();

I modified the else {connecting} into if(!BLE.connected()){connecting} as shown below:

void loop()
{
  static uint32_t msLastPrint = 0;
  if (millis() - msLastPrint < UPDATE_PERIOD_MS) return;
  msLastPrint = millis();

  if (BLE.connected())
  {
    Serial.printlnf("flag service == %d", flagService);//flag indicate which service will be connected next.
    if (!wasConnected)             // on first connect
    wasConnected = 1;            // give it 5 iterations
    else if (1 == wasConnected--)  // after last iteration 
    BLE.disconnect(peer);        // disconnect
  }
  
  //Modified here, previously was **else{...}**
  if (!BLE.connected())
  {

    int count = BLE.scan(scanResults, SCAN_RESULT_MAX);

    for (int ii = 0; ii < count; ii++) {
      uint8_t buf[BLE_MAX_ADV_DATA_LEN];
      size_t len;
      Serial.printlnf("%02x:%02x:%02x:%02x:%02x:%02x"
                     , scanResults[ii].address.addr[0]
                     , scanResults[ii].address.addr[1]
                     , scanResults[ii].address.addr[2]
                     , scanResults[ii].address.addr[3]
                     , scanResults[ii].address.addr[4]
                     , scanResults[ii].address.addr[5]
                     );

      len = scanResults[ii].advertisingData.get(BleAdvertisingDataType::SERVICE_UUID_128BIT_COMPLETE, buf, BLE_MAX_ADV_DATA_LEN);
      if (len > 0) {
        for (size_t jj = 0; jj < len; jj += 16)
        {
          if ((*(BleUuid *)&buf[jj] == serviceUuid_1) && (flagService == 1))
          {
            Serial.printlnf("flag service when service 1 ok== %d", flagService);
            peer = BLE.connect(scanResults[ii].address);
            if (peer.connected()) {
              Serial.println("successfully connected with service 1!");
              valueCharacteristic = peer.getCharacteristicByUUID(BleUuid(valueUuid_1));
              flagService = 2;

              /* Another position I tried before*/
            //   delay(1000);//2s for one transmitter
            //   BLE.disconnect(peer);
      
            //     if (BLE.connected())
            //     Serial.println("still connected");
            //      else
            //     Serial.println("it is disconnected now"); 
            }
            else {
              Serial.println("connection failed with service 1!");
            }
            break; // out of for(jj) loop
          }
          else if ((*(BleUuid *)&buf[jj] == serviceUuid_2) && (flagService == 2))
          {
            peer = BLE.connect(scanResults[ii].address);
            if (peer.connected()) {
              Serial.println("successfully connected with service 2!");
              valueCharacteristic = peer.getCharacteristicByUUID(BleUuid(valueUuid_2));
              flagService = 1;
              
            /*   Another position I tried before */
            //   delay(1000);//2s for one transmitter
            //   BLE.disconnect(peer);
      
            //     if (BLE.connected())
            //     Serial.println("still connected");
            //      else
            //     Serial.println("it is disconnected now");
            }
            else {
              Serial.println("connection failed with service 2!");
            }
            break; // out of for(jj) loop 
          }
          else {
            int u;
            for (u = 0; u < 16; u++)
              Serial.printlnf("%02x %c= %02x", ((BleUuid *)&buf[jj])->full()[u], ((BleUuid *)&buf[jj])->full()[u] == serviceUuid_1.full()[u] ? '=' : '!', serviceUuid_1.full()[u]);
              Serial.printlnf("%02x %c= %02x", ((BleUuid *)&buf[jj])->full()[u], ((BleUuid *)&buf[jj])->full()[u] == serviceUuid_2.full()[u] ? '=' : '!', serviceUuid_2.full()[u]);
              
              Serial.println("not the same UUID");
          }
        }
      }
      else {
        Serial.printlnf("len == %d", len);
      }
    }
  }
}

The reason for doing so is:
When the BLE is disconnected, the next step should be rescanning and reconnect a new service

But the result now seems that the BLE.disconnect() doesn't work, as one service is always connected. As shown below, over around 3 mins, service 2 was always connected.

I shouldn’t have to say it - as it should be 100% obvious - a better way would be to have a variable was connected which would be set when BLE.connected() became true and not just by some arbitrary iteration count. You also only need to disconnect when connected

Thanks for the suggestion. I tried to put BLE.disconnect() under BLE.connected() condition. But the results were kind of similar to one of the problems I posted. In this case, the BLE.disconnect() was working, but another weird output showed up:

For service 2, this statement passed
else if ((*(BleUuid *)&buf[jj] == serviceUuid_2) && (flagService == 2))
But failed to connect to service 2 leading to print:
connection failed with service 2!

The code for this part is shown below

else if ((*(BleUuid *)&buf[jj] == serviceUuid_2) && (flagService == 2))
          {
            peer = BLE.connect(scanResults[ii].address);
            if (peer.connected()) {
              Serial.println("successfully connected with service 2!");
              valueCharacteristic = peer.getCharacteristicByUUID(BleUuid(valueUuid_2));
              flagService = 1;
              
            //   delay(1000);//2s for one transmitter
            //   BLE.disconnect(peer);
      
            //     if (BLE.connected())
            //     Serial.println("still connected");
            //      else
            //     Serial.println("it is disconnected now");
            }
            else {
              // This line was printed out when I put BLE.disconnect() under BLE.connected() condition
              Serial.println("connection failed with service 2!");
            }

Thank you for your time and help.

Your first code snippet that should show where peer is defined obviously comes from a peripheral code but you are using it in the second snippet which obviously comes from the central device.
So one hasn't got anything to do with the other and you are not showing where peer would be set (I asked for both defined and set).

And I'll repeat my statment from another discussion with you: Add more Serial.print() statements to know what is happening where and when
e.g.

  • is BLE.disconnect() executed at all?
  • what is wasConnected doing over time?
  • may it be that you immediately reconnect after a disconnect?
  • what are the return values of all the function calls and what can you learn from the,?
  • ...

Debugging steps should be taken before asking others to solve your problems.

1 Like

Thanks so much, ScruffR!

Your first code snippet that should show where peer is defined obviously comes from a peripheral code but you are using it in the second snippet which obviously comes from the central device.
So one hasn’t got anything to do with the other and you are not showing where peer would be set (I asked for both defined and set ).

Can I ask why the first snippet is considered from a peripheral code? As both the first and second snippets are from my central code.

What I want to show is that the peer is defined in the first snippet and set in the second snippet, as peer = BLE.connect(scanResults[ii].address);

Does this make sense for peer define and set?

And I’ll repeat my statment from another discussion with you: Add more Serial.print() statements to know what is happening where and when

Thanks so much for clarifying what I should think! Before, I randomly added some print functions, such as after BLE.disconnect(). Then I found I still didn't know why I got some weird outputs like what I posted, so I deleted them. I SHOULD think more clear about each function performance.

By the way, can I say that the println()s in loop() and in onDataReceived() are executed at a different rate? That is why I didnt see the entire printing outcomes from loop(). And saw their(print() in loop() and print() in onDataReceived()) interleaving instead.

So would it be better if I comment out print() in onDataReceived() to debug the problem in loop()?

Thank you so much for your time and help!

Sorry, my bad :blush:
The presence of onDataReceived() led me to believe so as from experience with I2C and SPI slave devices this would inidcate a slave device.

However, it's usually best to post the entire code in one block to prevent confusion.
If the code is too long and you are using Web IDE you can use the SHARE THIS REVISION feature to post a link to a snapshot of your project.

The actual data output happens asynchronous to your print statments. The application calls only place the data into a buffer and the hardware interface pushes them out independently from your code.
Additionally onDataReceived will be called asynchronously too.

1 Like

Thanks, ScruffR!

Can I ask some clues for the same weird output(below) I mentioned before, I don’t know what is going wrong here.

In the case below, for the same variable, wasConnected, its value changed 5 times at the same time, not sure why. In this case, service 2 is connected.

But for the case that service 1 is connected, everything is normal as shown below.

The code for the print line is shown below:

void loop()
{
  // I am not sure whether this makes sense. what I want to do here is that only 
  // when at least one service has been connected, give update_period_ms 
  // time for the connected service.
  // gather data until exceed updat_period_ms
  if (bothConnected != -1) 
  {
    // Log.info("bothConnected == %d", bothConnected);
    static uint32_t msLastPrint = 0;
    if ((millis() - msLastPrint < UPDATE_PERIOD_MS)) return;
    msLastPrint = millis();  
  }
  
//   Serial.printlnf("both Connected == %d",bothConnected);
//   Serial.printlnf("flagservice 1 == %d", flagService1);
//   Serial.printlnf("flagservice 2 == %d", flagService2);
  
  if (BLE.connected())
  {
    Log.info("before wasConnected == %d",wasConnected);

    if (!wasConnected)             // on first connect
    {
        wasConnected = 5;            // give it 5 iterations
        Serial.printlnf("wasConnected on first connect is %d", wasConnected);
    }
    else if (1 == wasConnected--)  // after last iteration 
    {
        // Log.info("flag service 1 == %d", flagService1);
        // Log.info("flag service 2 == %d", flagService2);
   
        if (flagService1 == 1)
        BLE.disconnect(peers[0]);        // disconnect
        else if(flagService2 == 1 )
        BLE.disconnect(peers[1]);
        
        Serial.printlnf("wasConnected is %d", wasConnected);
        
        if (!BLE.connected())
        {
          Log.info("BLE is disconnected ");  
        }else{
          Log.info("BLE is still connected");
        }
    }
  }
  
  if (bothConnected == 1)
  {
    bothConnected = -1;
  }
  
// Try to connect to a service
  if (!BLE.connected())
  {
    int count = BLE.scan(scanResults, SCAN_RESULT_MAX);
    ...

Secondly, I found that after BLE.disconnect(), there is always around 8s for the next connection for the other service. I am not sure whether my understanding is correct that I cannot change this time, 8s. Would it be possible to accomplish it within ms? Because I would like to build up a real-time system.

Thirdly, for the peripheral boards, it sometimes blinks red SOS with 10 blinks in between which means Assertion failure. Then I reflashed the boards(two peripherals), the problem is still there.

I have a 6mins record about it but didn’t find the way to share here.

Thank you for your time and help!

The program seems to be running for almost 19 seconds before that happens, it would be interesting to know what happend during the lead-up to that.
Secondly, while the timestamp suggests it's all happening at the same time, the millis counter suggests that there were several iterations of loo() as there are aprox. 10ms beteween each decrement.

Add some more log statements logging out the set of variables that influence the behaviour and code flow to see which branches are executed when and why.

1 Like

Thanks so much, ScruffR.

I have added more log.info() statements and tried hard to reduce the waiting time after disconnection. Now it is 5s as shown below.

The context for the two lines that highlighted above is shown below:

  if (BLE.connected())
  {
    // Log.info("connected");
    // Serial.println("connected");
    Log.info("before wasConnected == %d",wasConnected);
    if (!wasConnected)             // on first connect
    {
        wasConnected = 5;            // give it 5 iterations
        Log.info("wasConnected on first connect is %d", wasConnected);
        // Serial.printlnf("wasConnected on first connect is %d", wasConnected);
    }
    else if (1 == wasConnected--)  // after last iteration 
    {
        // Log.info("flag service 1 == %d", flagService1);
        // Log.info("flag service 2 == %d", flagService2);
        
        if (flagService1 == 1)
        {
            BLE.disconnect(peers[0]);        // disconnect
            Log.info("service 1 is disconnected");
            wasFound = 0;
            Log.info("wasFound is set to 0 for service 1 disconnection");
        }
        
        else if(flagService2 == 1 )
        {
            BLE.disconnect(peers[1]);
            Log.info("service 2 is disconnected");
            wasFound = 0;
            Log.info("wasFound is set to 0 for service 2 disconnection");
        }
        
        Log.info("wasConnected is %d", wasConnected);// should be 1
        
        // check whether BLE is disconnected
        if (!BLE.connected())
        {
          // Highlighted in red 
          Log.info("BLE is disconnected ");  
        }
        else
        {
          Log.info("BLE is still connected");
        }
    }
  }
  
//   if (BLE.connected() && bothConnected)
  if (bothConnected == 1) // when service 1 and 2 have been connected once
  {
    bothConnected = -1;
    Log.info("bothConnected reset to -1");
  }
  
//   if(!BLE.connected() || bothConnected == 0)
  if (!BLE.connected())
  {
    int count = BLE.scan(scanResults, SCAN_RESULT_MAX);
    
    // Highlighted in red.
    Log.info("count == %d", count);
    for (int ii = 0; ii < count; ii++) 
    {

It seems weird that after printing out ''BLE is disconnected", it waited for around 5s for the next printline, “count == %d”. And there is no other branch in between.

I was thinking maybe this line:
BLE.scan(scanResults, SCAN_RESULT_MAX);
requires some time, such as 5s? If that is the case, would that be possible to still accomplish a real-time system without such long delay using argon boards via BLE?

Any suggestions would be appreciated.

Currently you’d probably be better of with mesh as this is meant to support parallel connections.
In some future release BLE will also support up to three (maybe more) parallel connections.

However, when you know your clients, why would you need to scan over and over?

1 Like

Thanks, ScruffR.

At the moment, I only have three argon boards, thought that probably BLE might be enough.
And also, after reading an introduction about mesh, Introduction to Bluetooth Meshes | Thoughtworks

I got an idea that for a device in mesh, it could be a client and a server at the same time. But does it mean that it could be a server for multiple clients and a client for multiple servers? Would this make the design more complex due to the high flexibility?

However, when you know your clients, why would you need to scan over and over?

I have thought it before, but not sure whether it is correct for BLE communication.

So can I just ask for a clarification?

I have stored peer1 and peer2 for service 1 and 2 in peers[2]
Can I just directly use
if (peers[0].connected())
after disconnecting service 2 for example.

Thanks for your time and help!

A mesh network doesn't really promote the concept of servers and clients - all devices are called nodes and can fullfill their tasks as needed. If your logic wants to "introduce" a server and client concept, you can do that as you see fit, but that doesn't inherently have anything to do with the mesh network.

Your idea about peers is correct in priciple.
Why not just try it?

3 Likes

Thanks so much, ScruffR.

I stored the addresses for service 1 and 2, now I need to wait for 3s for connection after the first connection for service 1 and 2 as shown below.

The related code:

        Log.info("Try to connect to service 2");
        peers[1] = BLE.connect(adder2);
  
        if (peers[1].connected()) 
        {
              Log.info("successfully connected with service 2!");

I thought the line peers[1] = BLE.connect(adder2); might be the reason to cause 3s delay.

I was wondering whether there is further action I could try to reduce the connection time.

And for mesh, would that be a problem, i.e. the delay for connection.

Thank you for your time and help.

No, because the devices stay connected.

1 Like