nRF52832 unable to indicate

For other supported Arduino products from Adafruit: Shields, accessories, etc.

Moderators: adafruit_support_bill, adafruit

Please be positive and constructive with your questions and comments.
Locked
User avatar
hasff
 
Posts: 5
Joined: Fri Feb 10, 2023 3:25 pm

nRF52832 unable to indicate

Post by hasff »

Hello Adafruit Team,

I bought four of your products, (2)x Adafruit Feather nRF52832 and (2)x Adafruit Feather nRF52840 Express, respectively. I’m not new to programming but I’m new to this. It's very exciting the projects we can do with this technology, especially using BLE abilities!

I successfully implemented a simple program that advertises a random generated number using the environmental sensing service and uv index characteristic. It worked fine but then when I revisited it a few weeks later I ran into some issues.

The code is as follow:

Code: Select all

#include <bluefruit.h>


uint8_t uvindexvalue = 0x0;
#define UUID16_SVC_ENVIRONMENTAL_SENSING 	0x181A
#define UUID16_CHR_UV_INDEX 			0x2A76


BLEService environmental_sensing_service 	= BLEService(UUID16_SVC_ENVIRONMENTAL_SENSING);
BLECharacteristic uv_index_characteristic 	= BLECharacteristic(UUID16_CHR_UV_INDEX);


void setup() {
 
  Serial.begin(115200);
  delay(500);
  Serial.println("Start!");

  Bluefruit.begin();
  Bluefruit.setName("Palm");

  setupESService();
  startAvd();
}

void loop() {

  uvindexvalue = random(0, 11);

  Serial.print("UV Index: ");
  Serial.println(uvindexvalue);

  if (uv_index_characteristic.indicate(&uvindexvalue, sizeof(uvindexvalue))) {

    Serial.print("Updated UV Index: ");
    Serial.println(uvindexvalue);
  }
  else {

    Serial.println("UV Index Indicate not set");
  }

  delay(1000);
}

void startAvd(void) {

  Bluefruit.Advertising.addService(environmental_sensing_service);

  Bluefruit.Advertising.addFlags(BLE_GAP_ADV_FLAGS_LE_ONLY_GENERAL_DISC_MODE);
  Bluefruit.Advertising.addTxPower();
  Bluefruit.Advertising.addName();
  Bluefruit.Advertising.restartOnDisconnect(true);
  Bluefruit.Advertising.setInterval(32, 244);
  Bluefruit.Advertising.setFastTimeout(30);
  Bluefruit.Advertising.start(0);
}

void setupESService(void) {

  environmental_sensing_service.begin();

  uv_index_characteristic.setProperties(CHR_PROPS_INDICATE);
  uv_index_characteristic.setPermission(SECMODE_OPEN, SECMODE_NO_ACCESS);
  uv_index_characteristic.setFixedLen(1);
  uv_index_characteristic.begin();

  uv_index_characteristic.write(&uvindexvalue, sizeof(uvindexvalue));
}
For the development I’m using Arduino IDE on a Windows 10 machine. I also followed the instructions on setting up BSP on Arduino IDE from the following Adafruit guide: https://learn.adafruit.com/bluefruit-nr ... -bsp-setup

On January 22th It was working perfectly. I saved the code right away in a safe place since I was planning to put it all together with other elements, once I solved challenges separately.
On February 6th, I started putting it all together. I usually retest each part one by one, not only to be sure that everything is ok but also to refresh my memory on the projects… and surprisingly this one is not working anymore. It started to display the message “UV Index Indicate not set”, which means it was not successful executing the characteristic indicate action.

So the first question I tried to answer was: “is there any chance that the device got damaged somehow in the process?”. I have another nRF52832 as a backup, it was new and I have never used it before. Updated the bootloader like I did with the previous one and like Adafruit presents at https://learn.adafruit.com/bluefruit-nr ... bootloader , it seemed the guide is a little bit outdated but I was able to follow along. After that I flashed the code and got the same message. I also asked a friend to do the same, new and clean device, he got the same message. I also tested another part of the project, an nRF52832 advertising and a nRF52840 detecting its RSSI, it works perfectly. So I believe that the device is not damaged, as it would also seem the chance of three devices being damaged is low.

Next question was: “Why is it not indicating successfully in the code, is there a chance that something in the Adafruit API has changed, Arduino IDE updated it in the background and some configurations are missing?“ I started digging the code, I went to the folder C:\Users\\AppData\Local\Arduino15\packages\adafruit\hardware\nrf52\1.3.0\libraries\Bluefruit 52Lib\src and read the code at BLECharacteristic.cpp.
I also noticed that only bluefruit.h had a later modified date - February 3rd for bluefruit.h and the remaining files January 12th, accordingly.
I’m not aware of any tools that can help debug this so I’m using the old fashion debug technique of printing out values, with the help of Serial.print.

In the BLECharacteristic.cpp, at BLECharacteristic::indicate (https://github.com/adafruit/Adafruit_nR ... 52Lib/src/
BLECharacteristic.cpp at line 894)

Step 1) I added the following print just to be sure that I was in the right place:

Code: Select all

bool BLECharacteristic::indicate(const void* data, uint16_t len) 
{ 
Serial.print("abc "); 
Serial.println(BLE_CONN_HANDLE_INVALID); 
return indicate(BLE_CONN_HANDLE_INVALID, data, len); 
It outputs: “abc 65535” so BLE_CONN_HANDLE_INVALID == 65535

Step 2) Next at line 844:

Code: Select all

bool BLECharacteristic::indicate(uint16_t conn_hdl, const void* data, uint16_t len) 
{ 
Serial.print("abc: "); 
Serial.println(_properties.indicate); 

VERIFY( _properties.indicate ); 
The output is: “abc: 1”, to my knowledge I’m guessing the indicate is correctly active.

Step 3) We already know from step 1) that it will fall in the if statement where it tests: conn_hdl == BLE_CONN_HANDLE_INVALID

So it do this: conn_hdl = Bluefruit.connHandle();

Just to be sure I added the following at bluefruit.cpp (https://github.com/adafruit/Adafruit_nR ... 52Lib/src/
bluefruit.cpp at line 643)

Code: Select all

uint16_t AdafruitBluefruit::connHandle(void) 
{ 
Serial.print("I was here! "); 
Serial.println(_conn_hdl); 
return _conn_hdl;
The output: “I was here! 65535”, in conclusion the conn_hdl == BLE_CONN_HANDLE_INVALID will continue to be true. And for some reason _conn_hdl is BLE_CONN_HANDLE_INVALID from the start.

So we have a new question: “why _conn_hdl has this value and when it becomes like that?”

At the moment I can try to dig more and try to find an answer to the above question… But it doesn’t feel like I will find any answer or at least one with a meaning for my limited knowledge about the subject. And also… I had this working a few days ago.


So Adafruit Team, I was wondering if there was any chance that this problem can be related somehow with Adafruit api or even Nordic api, some update that added some kind of an extra step to setting things up? I also noticed those red messages present in several pages of Adafruit guide which made me wonder.
Also do you have any suggestion/advice on how to fix this? Or to find some clues to help solve the problem?

In advance thank you for your time Adafruit Team!

User avatar
hathach
 
Posts: 1269
Joined: Tue Apr 23, 2013 1:02 am

Re: nRF52832 unable to indicate

Post by hathach »

Thank you for using Adafruit product

> So we have a new question: “why _conn_hdl has this value and when it becomes like that?”
For your question, the indicate() message can be sent directly to 1 of the centrals if you specify its connection handle (conn_hdl). with BLE_CONN_HANDLE_INVALID, it will send indicate to all currently connected central, and that is normal use case. Hope this helps to explain thing a bit. For API check out its header here https://github.com/adafruit/Adafruit_nR ... tic.h#L179

> The output is: “abc: 1”, to my knowledge I’m guessing the indicate is correctly active.

_properties.indicate = 1 is only the properties of your characteristic, in this case, it has capacity to send indicate message. To be able to send it, it must be enabled by central device, which you could check out with indicateEnabled() function (with and without specific connection handle) https://github.com/adafruit/Adafruit_nR ... #L166-L167

> At the moment I can try to dig more and try to find an answer to the above question… But it doesn’t feel like I will find any answer or at least one with a meaning for my limited knowledge about the subject. And also… I had this working a few days ago

BLE is relatively sophisticated, although we/Adafruit try to make it as simple as possible, a learning curve is still required. But we can help you to troubleshoot your issue, would you mind explain provide more info
- Which device you use to test with nrf52: iOS/Android and its OS version. Which app you use to test e.g Adafruit Bluefruit
- Which steps you do on the central to enable indicate. indicate must be enabled for every new connection. You could skip this if device is both enabled and paired previously.
- Enable Debug Log level to 2 (or 1). It will print more information which can be useful for analysis. Then upload both your compile log and serial log as txt files for analysis

User avatar
hasff
 
Posts: 5
Joined: Fri Feb 10, 2023 3:25 pm

Re: nRF52832 unable to indicate

Post by hasff »

Thank you for the reply hathach. Like I mentioned I’m new to this aspect of programming so all of this really helps and I appreciate your time!

I was not aware of that behavior and I was assuming that “BLE_CONN_HANDLE_INVALID” meant that something very bad happened. Is there any place where we can see the meaning of those messages? I didn’t have much luck when I Googled it.
Also something that was reinforcing the idea that something was not ok was noticing that when calling the “indicate” method it was returning false, misleading me and I ended up focusing on the wrong place to find a solution for the problem. Why does it return False in this situation?

At this moment, the central device is a computer, I’m using web bluetooth to read the values from the device. I found out that when calling requestDevice the options needed to include also the “optionalServices” option.

JavaScript code:

Code: Select all

let options = {
    filters: [
        { "name": deviceName }
    ],
    optionalServices: ['environmental_sensing'] // was missing  
};

console.log('Requesting BLE device info...');
return navigator.bluetooth.requestDevice(options).then(
device => { 
    bluetoothDeviceDetected = device;
}).catch(error => {
    console.log('Request device error: ' + error)
});
After the change it worked again and thanks to you since you clarified the behavior at feather side!

This is actually a small part of the project, what I am trying to accomplish is like a checkpoint system. To simplify this text I will refer to nRF52832 and nRF52840 Express as 832 and 840 accordingly.
nRF52832: https://www.adafruit.com/product/3406
nRF52840 Express: https://www.adafruit.com/product/4062
What we’re trying to create is an employee tracking setup to make sure employees are in certain areas every so often. So the idea is to have at least 26 checkpoints (26 individual 832’s spread across the premises advertising their presence) and when an employee (carrying 1 of five individual 840’s) reaches that checkpoint, at a distance of 2 feets for a minimum period of 5 seconds (using for the effect the measure of RSSI), the 840 should indicate that it detected a specific checkpoint (a specific 832). Since it will be far from the computer I was thinking of using another 840’s to act like relays, making a path to the computer. In the computer I want not only to detect the reached checkpoints but also to have information about the battery level of each device, so the computer should send from time to time a “command” that should propagate through the entire net of 840’s and 832’s and get back the responses.

I was able to do the code to detect proximity (RSSI) between the checkpoint (832) and the employee (840). I was able to indicate from employee 840 to PC that information also. I haven't done the code for the relays yet since I still haven’t figured out how to configure a relay (840) to act as a central and accept indications from employees (840), but I will get there. Do you have any suggestions for an appropriate example from Adafruit that I can look at?

My doubts come from a video that I saw from a lady on youtube explaining about BLE theory. The lady explained BLE has 6 types of operations: command, request/response, notification, indication/confirmation. And I’m trying to map them out and figure which one is better for which situation.

So my questions at the moment are:
1) When 840 indicates to the computer, according to the BLE theory it should have a confirmation from the client (computer). Is it possible for us to explicitly receive and handle that confirmation at 840 side? Maybe with a callback? My idea is that employee 840 should keep the record of the event and indicate the event of reaching a checkpoint till the computer learns about it or it should be “smashed” in case the same checkpoint is reached later on and we didn’t have confirmation yet of the previous one having arrived at the computer.


2) Since there will be a path of relays where the messages have to travel… I’m not sure which type of operation is best suitable for the effect: indication/confirmation or request/response?
The idea I’ve got is that the request/response model is more like an “active action” and on the other hand indication/confirmation acts more like a “passive action” and probably could be beneficial in terms of energy consumption.


3) Is it possible to end up having relays in a situation of a circular message exchange? E.g. Since the radio signals don’t have a specific direction, relay A indicates to relay B the message X and then relay B indicates to relay A the same message, and this goes forever.
If that is the case, would using a strategy of including a message exchange counter in the message be a good approach or would something else that I am not aware of be better?
I was also thinking of each 840 having a unique name and accepting only indications from specific relays, but using this approach means that we have to place each device on the field with a specific physical order and if for some reason one device is moved or switched place with another it ends up breaking the logical chain and so breaking the entire system.


4) And after all, for what I am trying to accomplish do you think using 832 and 840 is a good choice or there are better options?
Someone on this forum told the person I’m working with this project that 832 and 840 were good options but at the time the project was not as clear to me as it is now.

Thank you in advance for your time and patience hathach and Adafruit Team!

User avatar
hathach
 
Posts: 1269
Joined: Tue Apr 23, 2013 1:02 am

Re: nRF52832 unable to indicate

Post by hathach »

> I was not aware of that behavior and I was assuming that “BLE_CONN_HANDLE_INVALID” meant that something very bad happened. Is there any place where we can see the meaning of those messages? I didn’t have much luck when I Googled it.

I am glad you figured it out the missing service information. Indeed the parameter is not too clear, however it is how the lower level sdk API from Nordic defined.

> I was able to do the code to detect proximity (RSSI) between the checkpoint (832) and the employee (840). I was able to indicate from employee 840 to PC that information also. I haven't done the code for the relays yet since I still haven’t figured out how to configure a relay (840) to act as a central and accept indications from employees (840), but I will get there. Do you have any suggestions for an appropriate example from Adafruit that I can look at?

Here is an example with an 52840 working as dual role (both central and peripheral) https://github.com/adafruit/Adafruit_nR ... leuart.ino

> command, request/response, notification, indication/confirmation. And I’m trying to map them out and figure which one is better for which situation.

command/request/response required central to initiate the data, for your application the notification and indication work best since it can be initiated by the device. The only difference between notification and indication is like TCP/UDP packet, whereas notification is like UDP sent from device and does not expect any confirmation in return. it is more suitable to something like sensor where the data appear regularly and occasion missing one is not an issue at all, it is probably skip it than trying to listen for reponse and retry. Indication behaves more like TCP which central must confirm, and peripheral must see the confirmation before calling it a success. Depending on your application, you should pick suitable one.

2) as mention above, request/response is from central, it is like central do an active read() on an attritubte.

3) It is totally possible, but there is way to address this, e.g when relaying an message, the relaying central add its unique ID (or your assigned ID) as part of the message and when getting an message, it will do nothing if the message has its ID in the payload. and/or you could increasea and time-to-live count to payload, which is included each time it is relayed. Since you know the amount of central, you could put some hard limit on how many time a message is relayed (totaly implementation dependent).

4) Maybe, and maybe not, there is also other RF tech like zigbee, sub 1Ghz etc but I am not entirely sure. Since you are already doing some work with BLE, maybe you could do some small scale testing with simpler scenario before committing more time and effort to this route.

User avatar
Franklin97355
 
Posts: 23903
Joined: Mon Apr 21, 2008 2:33 pm

Re: nRF52832 unable to indicate

Post by Franklin97355 »


Locked
Please be positive and constructive with your questions and comments.

Return to “Other Arduino products from Adafruit”