My sketch is not generating BLE signals

Hi, Everyone

I have gotten to the point where this sketch compiles and loads but I cannot figure out why I am not seeing it on my 3rd party "nRF Connect" or "Light Blue" and nothing shows in my serial monitor. If someone with more knowledge than I have could look this over and point out what is probably obvious to everyone else, I would greatly appreciate it.

#include <ArduinoBLE.h>
#include <Wire.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_BME280.h>

#define BLE_NAME "Psychrometer"
#define SERVICE_UUID "19B10000-E8F2-537E-4F6C-D104768A1214"
#define TEMPERATURE_UUID "19B10001-E8F2-537E-4F6C-D104768A1214"
#define HUMIDITY_UUID "19B10002-E8F2-537E-4F6C-D104768A1214"
#define PRESSURE_UUID "19B10003-E8F2-537E-4F6C-D104768A1214"

Adafruit_BME280 bme;

BLEService bmeService(SERVICE_UUID);
BLEStringCharacteristic temperatureCharacteristic(TEMPERATURE_UUID, BLERead | BLENotify, 100);
BLEStringCharacteristic humidityCharacteristic(HUMIDITY_UUID, BLERead | BLENotify, 100);
BLEStringCharacteristic pressureCharacteristic(PRESSURE_UUID, BLERead | BLENotify, 100);

void setup() {
  Serial.begin(9600);
  while (!Serial);

  if (!bme.begin()) {
    Serial.println("Could not find BME280 sensor, check wiring!");
    while (1);
  }

  if (!BLE.begin()) {
    Serial.println("Failed to start BLE!");
    while (1);
  }

  BLE.setLocalName(BLE_NAME);
  BLE.setAdvertisedService(bmeService);

  bmeService.addCharacteristic(temperatureCharacteristic);
  bmeService.addCharacteristic(humidityCharacteristic);
  bmeService.addCharacteristic(pressureCharacteristic);

  BLE.addService(bmeService);

  temperatureCharacteristic.writeValue("0");
  humidityCharacteristic.writeValue("0");
  pressureCharacteristic.writeValue("0");

  BLE.advertise();

  Serial.println("BLE peripheral is now active");
}

void loop() {
  BLEDevice central = BLE.central();

  if (central) {
    Serial.print("Connected to central: ");
    Serial.println(central.address());

    while (central.connected()) {
      float temperature = bme.readTemperature();
      float humidity = bme.readHumidity();
      float pressure = bme.readPressure() / 100.0F;

      Serial.print("Temperature: ");
      Serial.print(temperature);
      Serial.println(" °C");

      Serial.print("Humidity: ");
      Serial.print(humidity);
      Serial.println(" %");

      Serial.print("Pressure: ");
      Serial.print(pressure);
      Serial.println(" hPa");

      temperatureCharacteristic.writeValue(String(temperature));
      humidityCharacteristic.writeValue(String(humidity));
      pressureCharacteristic.writeValue(String(pressure));

      delay(1000);
    }

    Serial.print("Disconnected from central: ");
    Serial.println(central.address());
  }
}

What do you see in the serial monitor?

How is wired, powered etc?
Schematics please.

Absolutely nothing. The serial monitor just sits there. Other sketches have worked fine and were found by 3rd party apps but I cannot see what the operative (or inoperative;) differences are. I am inserting a sketch that DOES work and is found by 3rd party apps. This sketch uses UUID 6-bit shortcuts and it is enough different from my posted sketch to elude my ability to compare and contrast. Ultimately, I want the previously posted sketch to be discoverable in the same way the following 6-bit sketch is.

Functioning sketch that is discovered by 3rd party apps written by Rui Santos:.

/*
  Rui Santos
  Complete project details at https://RandomNerdTutorials.com/esp32-ble-server-environmental-sensing-service/
  
  Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files. 
  The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
*/

#include <BLEDevice.h>
#include <BLEServer.h>
#include <BLEUtils.h>
#include <BLE2902.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_BME280.h>

//BLE server name
#define bleServerName "Psychrometer"

// Default UUID for Environmental Sensing Service
// https://www.bluetooth.com/specifications/assigned-numbers/
#define SERVICE_UUID (BLEUUID((uint16_t)0x181A))    //  Environmental Sensing Service shortcut

// Temperature Characteristic and Descriptor (default UUID)
// Check the default UUIDs here: https://www.bluetooth.com/specifications/assigned-numbers/
BLECharacteristic temperatureCharacteristic(BLEUUID((uint16_t)0x2A6E), BLECharacteristic::PROPERTY_NOTIFY);
BLEDescriptor temperatureDescriptor(BLEUUID((uint16_t)0x2902));

// Humidity Characteristic and Descriptor (default UUID)
BLECharacteristic humidityCharacteristic(BLEUUID((uint16_t)0x2A6F), BLECharacteristic::PROPERTY_NOTIFY);
BLEDescriptor humidityDescriptor(BLEUUID((uint16_t)0x2902));

// Pressure Characteristic and Descriptor (default UUID)
BLECharacteristic pressureCharacteristic(BLEUUID((uint16_t)0x2A6D), BLECharacteristic::PROPERTY_NOTIFY);
BLEDescriptor pressureDescriptor(BLEUUID((uint16_t)0x2902));

// Create a sensor object
Adafruit_BME280 bme;

// Init BME280
void initBME(){
  if (!bme.begin(0x76)) {
    Serial.println("Could not find a valid BME280 sensor, check wiring!");
    while (1);
  }
}

bool deviceConnected = false;

//Setup callbacks onConnect and onDisconnect
class MyServerCallbacks: public BLEServerCallbacks {
  void onConnect(BLEServer* pServer) {
    deviceConnected = true;
    Serial.println("Device Connected");
  };
  void onDisconnect(BLEServer* pServer) {
    deviceConnected = false;
    Serial.println("Device Disconnected");
  }
};

void setup() {
  // Start serial communication 
  Serial.begin(115200);

  // Start BME sensor
  initBME();

  // Create the BLE Device
  BLEDevice::init(bleServerName);

  // Create the BLE Server
  BLEServer *pServer = BLEDevice::createServer();
  pServer->setCallbacks(new MyServerCallbacks());

  // Create the BLE Service
  BLEService *bmeService = pServer->createService(SERVICE_UUID);

  // Create BLE Characteristics and corresponding Descriptors
  bmeService->addCharacteristic(&temperatureCharacteristic);
  temperatureCharacteristic.addDescriptor(&temperatureDescriptor);
  
  bmeService->addCharacteristic(&humidityCharacteristic);
  humidityCharacteristic.addDescriptor(&humidityDescriptor);

  bmeService->addCharacteristic(&pressureCharacteristic);
  pressureCharacteristic.addDescriptor(&pressureDescriptor);
  
  // Start the service
  bmeService->start();

  // Start advertising
  pServer->getAdvertising()->start();
  Serial.println("Waiting a client connection to notify...");
}

void loop() {
  if (deviceConnected) {
    // Read temperature as Celsius (the default)
    float t = bme.readTemperature();
    // Read humidity
    float h = bme.readHumidity();
    // Read pressure
    float p = bme.readPressure()/100.0F;
    
    //Notify temperature reading
    uint16_t temperature = (uint16_t)t;
    //Set temperature Characteristic value and notify connected client
    temperatureCharacteristic.setValue(temperature);
    temperatureCharacteristic.notify();
    Serial.print("Temperature Celsius: ");
    Serial.print(t);
    Serial.println(" ºC");
   
    //Notify humidity reading
    uint16_t humidity = (uint16_t)h;
    //Set humidity Characteristic value and notify connected client
    humidityCharacteristic.setValue(humidity);
    humidityCharacteristic.notify();   
    Serial.print("Humidity: ");
    Serial.print(h);
    Serial.println(" %");

    //Notify pressure reading
    uint16_t pressure = (uint16_t)p;
    //Set humidity Characteristic value and notify connected client
    pressureCharacteristic.setValue(pressure);
    pressureCharacteristic.notify();   
    Serial.print("Pressure: ");
    Serial.print(p);
    Serial.println(" hPa");
    
    delay(10000);
  }
}

Greetings,

I appreciate your desire for more information but it smacks against my organizational abilities at t6he moment. The specifics are that I am using a Seeeduino ESP32C3 microprocessor attached with I2C to a BME280 environmental sensor. The following sketch works but it uses 6-bit UUID coding (i.e. 0x181A). I can easily see it in both of my 3rd party apps. My desire is to have my previously-posted sketch using standard (random) UUID coding function like the following sketch does. I just do not have the ability to discern the functional difference(s).

/*
  Rui Santos
  Complete project details at https://RandomNerdTutorials.com/esp32-ble-server-environmental-sensing-service/
  
  Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files. 
  The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
*/

#include <BLEDevice.h>
#include <BLEServer.h>
#include <BLEUtils.h>
#include <BLE2902.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_BME280.h>

//BLE server name
#define bleServerName "Psychrometer"

// Default UUID for Environmental Sensing Service
// https://www.bluetooth.com/specifications/assigned-numbers/
#define SERVICE_UUID (BLEUUID((uint16_t)0x181A))    //  Environmental Sensing Service shortcut

// Temperature Characteristic and Descriptor (default UUID)
// Check the default UUIDs here: https://www.bluetooth.com/specifications/assigned-numbers/
BLECharacteristic temperatureCharacteristic(BLEUUID((uint16_t)0x2A6E), BLECharacteristic::PROPERTY_NOTIFY);
BLEDescriptor temperatureDescriptor(BLEUUID((uint16_t)0x2902));

// Humidity Characteristic and Descriptor (default UUID)
BLECharacteristic humidityCharacteristic(BLEUUID((uint16_t)0x2A6F), BLECharacteristic::PROPERTY_NOTIFY);
BLEDescriptor humidityDescriptor(BLEUUID((uint16_t)0x2902));

// Pressure Characteristic and Descriptor (default UUID)
BLECharacteristic pressureCharacteristic(BLEUUID((uint16_t)0x2A6D), BLECharacteristic::PROPERTY_NOTIFY);
BLEDescriptor pressureDescriptor(BLEUUID((uint16_t)0x2902));

// Create a sensor object
Adafruit_BME280 bme;

// Init BME280
void initBME(){
  if (!bme.begin(0x76)) {
    Serial.println("Could not find a valid BME280 sensor, check wiring!");
    while (1);
  }
}

bool deviceConnected = false;

//Setup callbacks onConnect and onDisconnect
class MyServerCallbacks: public BLEServerCallbacks {
  void onConnect(BLEServer* pServer) {
    deviceConnected = true;
    Serial.println("Device Connected");
  };
  void onDisconnect(BLEServer* pServer) {
    deviceConnected = false;
    Serial.println("Device Disconnected");
  }
};

void setup() {
  // Start serial communication 
  Serial.begin(115200);

  // Start BME sensor
  initBME();

  // Create the BLE Device
  BLEDevice::init(bleServerName);

  // Create the BLE Server
  BLEServer *pServer = BLEDevice::createServer();
  pServer->setCallbacks(new MyServerCallbacks());

  // Create the BLE Service
  BLEService *bmeService = pServer->createService(SERVICE_UUID);

  // Create BLE Characteristics and corresponding Descriptors
  bmeService->addCharacteristic(&temperatureCharacteristic);
  temperatureCharacteristic.addDescriptor(&temperatureDescriptor);
  
  bmeService->addCharacteristic(&humidityCharacteristic);
  humidityCharacteristic.addDescriptor(&humidityDescriptor);

  bmeService->addCharacteristic(&pressureCharacteristic);
  pressureCharacteristic.addDescriptor(&pressureDescriptor);
  
  // Start the service
  bmeService->start();

  // Start advertising
  pServer->getAdvertising()->start();
  Serial.println("Waiting a client connection to notify...");
}

void loop() {
  if (deviceConnected) {
    // Read temperature as Celsius (the default)
    float t = bme.readTemperature();
    // Read humidity
    float h = bme.readHumidity();
    // Read pressure
    float p = bme.readPressure()/100.0F;
    
    //Notify temperature reading
    uint16_t temperature = (uint16_t)t;
    //Set temperature Characteristic value and notify connected client
    temperatureCharacteristic.setValue(temperature);
    temperatureCharacteristic.notify();
    Serial.print("Temperature Celsius: ");
    Serial.print(t);
    Serial.println(" ºC");
   
    //Notify humidity reading
    uint16_t humidity = (uint16_t)h;
    //Set humidity Characteristic value and notify connected client
    humidityCharacteristic.setValue(humidity);
    humidityCharacteristic.notify();   
    Serial.print("Humidity: ");
    Serial.print(h);
    Serial.println(" %");

    //Notify pressure reading
    uint16_t pressure = (uint16_t)p;
    //Set humidity Characteristic value and notify connected client
    pressureCharacteristic.setValue(pressure);
    pressureCharacteristic.notify();   
    Serial.print("Pressure: ");
    Serial.print(p);
    Serial.println(" hPa");
    
    delay(10000);
  }
}

Your documentation of the project is really tiny. Hard to say much from that.

It's reading the sensors and prints to serial monitor. Does the data look okey?

Add

void setup() {
  Serial.begin(9600);
  while (!Serial);
Serial.println("I'm alive!!!!");

What is your issue with using the long format uuid coding with the ESP32 libraries and syntax.

Although ArduinoBLE.h is designed to work with the ESP32, I have always been more successful using the ESP32 package when using that MCU.

//#include <ArduinoBLE.h>

#include <BLEDevice.h>
#include <BLEServer.h>
#include <BLEUtils.h>
#include <BLE2902.h>

You are on to something! I do not have anything printing in the serial monitor except the following message:

16:29:43.819 -> ESP-ROM:esp32c3-api1-20210207

This is obviously the timestamp and some internal code that I do not grock.

This would suggest to me a problem in the void setup() such that the dcode doesn't complete, or even start. I am even more befuddled now.

Greetings! My issue with using the long-format UUID code is that I seem to think I can simply plug and play the long-format code over the 6-bit code and everything will continue to work. It doesn't! One problem is with the strings I wish to print. The 0x181A codes have their own string associated with them - as long as I want that particular string. I just don't know much regarding UUID in general and I am trying to create a simple project to better understand everything.

I agree with your assessment regarding the ArduinoBLE.h folder but, when I replace it, the code crashes. Probably due to specific commands that are not cross-compatible.

The bottom line is that the 6-bit code sends data and can be found by 3rd party apps. The long-form UUID sketch compiles and "runs" but nothing is broadcast and nothing is displayed in the serial monitor.

I appreciate any light you may be able to shed on this.

Greetings (good morning),

Well, that was a unique senior moment. Last night, I couldn't get the sketch to run. Now, in the morning, I must have corrected something. I can now see the device name (Psychrometer), and data readouts for the temperature, humidity, and pressure in my nRF Connect but it displays a UUID instead of the characteristic's string name (i.e. "Temperature.")

Please look at my nRF Connect screenshot and tell me, if you can, what is necessary to broadcast the string names.

In all the time that I've used nRFConnect, I don't recall it every showing characteristic or service names except maybe Device Information. I don't think those are broadcast. I think it would just be displaying the names of predefined GATT characteristics. Whenever we've written apps to display BLE data, the text names were not broadcast, but generated internal to the app.
e.g., 180D is the Heart Rate service, so that's what the app would show.

Hi, thanks for that information. I have been misunderstanding this whole time. Am I correct in assuming that if the UUID being broadcast matches a listed UUID in my app, the app will associate the string data it has internally with the UUID that matches it? In other words, strings are not sent, but UUIDs are, and they are associated by their matching definitions upon detection by the app?

Also, thank you for your patience with me and my abysmal learning curve.

I think I understand what you're asking and that's correct.

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