Characteristic.valueUpdated() returns always false

Hi all,
I'm writing bluetooth application that transmits accelerometer data from a peripheral to a central. The peripheral is a xiao nRF52840 sense, and the central a xiao ESP32C3. In general, thanks to code from Klaus_K that I found, the communication works, i.e. the central receives data from the peripheral. However, I'm having troubles with valueUpdated() that either doesn't work, or maybe I didn't understand it correctly.

On the peripheral side, I set up the BLECharacteristic like this:
BLECharacteristic accCharacteristic(BLE_UUID_ACC_CHAR, BLERead | BLENotify, sizeof accData.bytes);
With the definition of a union data structure, the data is sent with
accCharacteristic.writeValue(accData.bytes, sizeof accData.bytes);

On the central side, I create the BLECharacteristic
BLECharacteristic accCharacteristic = peripheral.characteristic(BLE_UUID_ACC_CHAR);

Since the peripheral side is a notification service, I understand that the central has to subscribe to it with
bool sub = accCharacteristic.subscribe();

This returns true on the central, and the peripheral also prints that something has subscribed to the characteristic, so I must conclude that the subscription is working. The peripheral is writing new accelerometer values every second. Now, I thought if I use valueUpdated(), the central will automatically read the new values also every second:

 while (peripheral.connected()) {
    Serial.println(accCharacteristic.valueUpdated());
    if (accCharacteristic.valueUpdated()) {
      accCharacteristic.readValue(accData.bytes, sizeof accData.bytes);
      Serial.println(accData.values[0]);
    }
  }

However, valueUpdated() always prints 0, so new values are never read. If I remove the if-clause, then the central reads correct accelerometer values every loop, i.e. it reads/prints the same value for 1 second, then another value for 1 second (since the peripheral has written new values).

So my question is, if I'm either missing something and this doesn't work as I imagine, or if this could be caused by some incompatibility between the nRF52840 sense and the ESP32C3?

Thanks for any insight anybody might have!

I'm not sure notifications work in the Arduino BLE library. Certainly not the way intended by bluetooth. On my application, I gave up on Arduino, and had to use an esp32 with the esp32 library.

That said, valueUpdated() returns true if the value has been updated since the last time you called it. So, I would expect the if statement to always be false. But I also tried really hard to get this to work, and I lost a lot of data, not getting all of the notifications that actually were sent.

No one responded to my question a few weeks ago. The library is maintained and recently bumped up a version. It would be nice if someone that understands or works on it could chime in.

any insight anybody might have!

Have you tried programing the ESP32 using the Espressif BLE library and not ArduinoBLE.

When the esp 32 is selected as the board, there is a library example which subscribes to a characteristic with notification.

File>Examples>ESP32 BLE Arduino>BLE_client

Thanks for your answers!
@wholybee I see that in the actual if-clause valueUpdated() would always be false with what you describe, thanks for the hint. However, then the print statement before should return true (1) once per second as it should catch the notification update, but this is unfortunately not the case.

@cattledog I'll try the Espressif BLE library for the ESP32 and report back here how it went. So far I only used the ArduinoBLE library.

In general, is the ArduinoBLE library not recommended? I read somewhere else that it had stability issues, and if notifications don't properly work with it, that would be a major downside, at least in my project. I'll probably get some more xiao nRF52840 sense chips, then I could test if it's only a library issue or library+hardware issue.

In general, is the ArduinoBLE library not recommended?

I would not say that, and I have used the Arduino BLE library with a Nano 33 BLE quite successfully, and I have used it to subscribe to notifications, as have others.

My understanding from @wholybee is that they had issues with notifications for long data packets, not the short ones of less than 20 bytes.

I have never used the library (or the esp library) in a long running application, so I can comment about the "stability".

I am new to the ArduinoBLE library so I have no idea if it is stable or recommended. It is a lot smaller than the Espressif library and generally seems easy to use.

My specific problem is that I lose data if it is longer than 16 bytes (not even 20). In theory that data would be split between multiple notifications, and if fact, that does happen, as the peripheral (which is a device I didn't write) works fine if the central uses the Espressif library, and I can confirm multiple notifications are received.

But as to notifications in the ArduinoBLE library in general. I don't even know what notifications in the ArduinoBLE library do. The way they are supposed to work according to the BLE standard and the Espressif library, after you subscribe to a notification, there is no need to ever check if the data is new. When the data changes, you are told that by a notification, and the notification includes up to 20 bytes. It seems that in the Arduino library you can subscribe to a notification, but there is no mechanism to ever receive or do anything with it. Instead, you set up a loop looking for data to change and then read it-bypassing the whole notification process. In my case that is a problem, because if multiple notifications are sent quickly in a row, all the actual notifications (and the 20 bytes in each one) are lost, and when I read the data, all I see is the last 20 bytes. If I am misunderstanding that, I would sure like it better explained to me.

What happens if you skip the notification, and just readValue() in your loop? Don't even bother checking if it was updated, just read it and compare it to the last value read.

@cattledog my application would run for a couple of hours, so stability is something I need to take into consideration. I'll try to test that once the project is further.

@wholybee I didn't know the specifics of notifications. For me, a loop that checks if data has changed and then reading it would work fine, and so far I thought this is how notifications work. I'll check the example @cattledog mentioned.
If I skip the notification, what happens is what I described in my first post, removing the if-clause: the central reads the exact same accelerometer data (looks like they are stored somewhere?), then at some point the peripheral writes new data (only once every second), and so for the next second the central reads the same new values, and so on. The output looks like a staircase.

On another note, from what I read in other posts, it seems that getting the ArduinoBLE to run on the ESP32 was kind of a lucky punch. I only used the ESP32 as this was the only feasible MC I had around to make a central. But my goal is to do everything with a couple of xiao nRF52840 senses (because of their size, integrated IMU and BLE capability). On their page it is written that I need to use ArduinoBLE, so I'm not sure if I have the option of switching everything to the Espressif library...
So looks like for me it's either getting Espressif to run on the xiao, or ditch the notification service with ArduinoBLE (unless it works with 2 "Arduino" devices), or find another tiny MC with IMU and BLE.

Does something like this work? Completely ignoring the whole concept of notifications?

while (peripheral.connected()) {
	currentValue = accCharacteristic.readValue(accData.bytes, sizeof accData.bytes);
	if (currentValue != previousValue) {
		previousValue = currentValue;
		// do some stuff
	}
}

The main downside is that bluetooth will always be active and communicating, so it won't be "low energy" if battery life is important.

When I get time I need to write some simple test cases to better understand how exactly ArduinoBLE handles notifications. But for now, my application is working with Espressif, and I have moved to the hardware side.

In the ESP BLE libraries, notifications are handled by call back functions.

It's not clear to me that the Arduino BLE library events which use call backs can respond to a notification.

@wholybee Your suggestion would work, yes, but as you said, it will probably lose the low energy property like this, which I wouldn't really like to lose.

It will probably take me a couple of weeks until I can do the test with two xiaos (getting other things to work first and then getting more hardware), but I'll update this thread whenever I have more information. I'll also revise if I actually need notifications in the end or not. Many thanks for the inputs from both of you!

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.