How does BLE Notifiy work with Arduino BLE 33?

Hi there,

I'm trying to learn how to use BLE on the Arduino BLE 33 and have made it pretty far using different examples, but now I'm stuck understanding the BLE Notify feature.

My goal is to read sensors out and update new values to an Android App by notify (so not with polling from the android app)
As far as I understand a charactersitic can support different functions. I have declared my characteristic as BLERead and BLENotify.

I can set values to that characteristic, but I'm never receiving an event that a value was updated on the Android App (I also have tested Apps like "BLE Scanner").

I suspect I need to do something to trigger the notify event on the Arduino side.

Does anybody have an example on how that works?

Thank you very much in advance.

Here is a minmal example of my code:

  #include <ArduinoBLE.h>
  #include <api/deprecated-avr-comp/avr/dtostrf.h>
  BLEService t4Service("e2e65ffc-5687-4cbe-8f2d-db76265f269f");
  BLEIntCharacteristic insideTempCharacteristic("478e24cf-5e0c-451d-b220-02aacd43f0c1", BLERead | BLENotify);

  BLEDescriptor insideTempDescriptor("9a3fb830-bab7-46ec-969c-64279fd85391", "insideTemp");

  uint8_t SensorInside[8] = { 0x28, 0xAA, 0xCF, 0xF5, 0x53, 0x14, 0x01, 0x26 };
  // Setup a oneWire instance to communicate with any OneWire devices
  OneWire oneWire(ONE_WIRE_BUS);
  // Pass our oneWire reference to Dallas Temperature.
  DallasTemperature sensors(&oneWire);


//Variables for Temperature
int tempInside
long lastUpdate;


void setup() 
{
  Serial.begin(9600);
    if (!BLE.begin()) 
    {
      Serial.println("Starting BLE failed!");
      while (1);
    }
    BLE.setLocalName("T4");

    insideTempCharacteristic.addDescriptor(insideTempDescriptor);    
    BLE.setAdvertisedService(t4Service);
    t4Service.addCharacteristic(insideTempCharacteristic);
    BLE.addService(t4Service);
    BLE.advertise();
}

void loop() 
{ 
  if (millis() > lastUpdate + 5000){
    lastUpdate = millis();
    readSensors();
  }
  BLEDevice central = BLE.central();
    if (central) {
      if (central.connected()){
        insideTempCharacteristic.writeValue(tempInside);
      }
  }
  
} 

void readSensors(){
  sensors.requestTemperatures();
  tempInside = (int)sensors.getTempC(SensorInside);
}
1 Like

On the peripheral side you need to create a BLE characteristic with the BLENotify flag set and you need to write to the characteristic.

On the client side you will need to subscribe to the BLEcharacteristic. The BLECharacteristic class in the ArduinoBLE library has a function for that.

Some BLE apps have a separate button for continuous reading that likely uses the subscribe feature for that. You could test this by having two characteristics (one with notify and one without) and see what the app interface will show you.

About your code, you should place a millis() interval around the part that writes to the characteristic or use an update flag to ensure the write is only done when you have new data or at an fixed interval. Otherwise the notify is useless. It would trigger all the time and force clients that use this feature to update continuously and not in a sensible interval.

1 Like

Hello Klaus_K,

thank you very much for helping me.
I learned from your post that there is no other function to call on the Arduino side.
Then I started to debug again and found my problem in the Android App.

In order to enable notification you need to write to the description of that characteristic. And this wrinting needs to be finished before reading a data of a charactersitic. My Android code did that synchronously. After having added Queues to make it asynchronously, it works perfectly now :slight_smile:

1 Like