Skip to content

Example NimBLE_multi_advertiser.ino not working on nRF52840 #929

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
djdehaan opened this issue Apr 3, 2025 · 11 comments
Closed

Example NimBLE_multi_advertiser.ino not working on nRF52840 #929

djdehaan opened this issue Apr 3, 2025 · 11 comments

Comments

@djdehaan
Copy link

djdehaan commented Apr 3, 2025

I burn the exact script of the multi-advertiser BT5 example with one corrected compile error:
legacyConnectable.setAddress(NimBLEAddress("DE:AD:BE:EF:BA:AD", 1));
on a nRF52840. The nRF is loaded with the provided adafruit bootloader, and is using the n-able platform. When running, 2 devices do appear on a phone. The legacy-one (like the other one) shows "connectable" but is not connectable. After short trying, it keeps not connected. What goes wrong? Who has tried this example on a nRF52840?

I tried the exact same code and the same specifics in the platform.ini on a ESP32S3, and there it works like a charm! So what goes wrong on the nRF52840?

Thanks for any help,
Dirk Jan

@h2zero
Copy link
Owner

h2zero commented Apr 6, 2025

Hello @djdehaan, do you see anything in the logs, phone and nrf?

@djdehaan
Copy link
Author

djdehaan commented Apr 6, 2025

Hi h2zero,

The platform.ini is:

[env:Nim-nrf52840server]
platform = n-able
board = nRF52840_WHX
framework = arduino
monitor_speed = 115200
;upload_protocol = nrfutil
upload_protocol = jlink
lib_deps = 
	h2zero/NimBLE-Arduino@^2.2.3
upload_port = COM9
extra_scripts = 
	pre:build_versioning.py
board_bootloader = adafruit
build_flags = 
	-DUSE_LFRC
	-DNRF52_SERIES
	-DNRF52840_XXAA
  -DCONFIG_NIMBLE_CPP_LOG_LEVEL=5
	-DCORE_DEBUG_LEVEL=5
	-DCONFIG_BT_NIMBLE_EXT_ADV=1
	-DCONFIG_NIMBLE_CPP_ENABLE_RETURN_CODE_TEXT
	-DCONFIG_NIMBLE_CPP_ENABLE_GAP_EVENT_CODE_TEXT
	-DCONFIG_NIMBLE_CPP_ENABLE_ADVERTISEMENT_TYPE_TEXT
 	-DCONFIG_BT_NIMBLE_ROLE_CENTRAL_DISABLED
  -DCONFIG_BT_NIMBLE_ROLE_OBSERVER_DISABLED

The code I use is like this: main.h

#pragma once
#include <Arduino.h>
#include <NimBLEDevice.h>

class _ServerCallbacks : public NimBLEServerCallbacks 
{
  public:
    void onConnect(NimBLEServer* pServer, NimBLEConnInfo& connInfo) override;
    void onDisconnect(NimBLEServer* pServer, NimBLEConnInfo& connInfo, int reason) override;
    void onIdentity	(	NimBLEConnInfo & 	connInfo	)	override;

};

/** Callback class to handle advertising events */
class _AdvCallbacks : public NimBLEExtAdvertisingCallbacks 
{
  public:
    bool m_updatedSR = false;
    void onStopped(NimBLEExtAdvertising* pAdv, int reason, uint8_t instId) override ;
    void onScanRequest(NimBLEExtAdvertising* pAdv, uint8_t instId, NimBLEAddress addr) override;
};

And main.cpp

/**
 *  NimBLE Multi Advertiser Demo:
 *
 *  Demonstrates the Bluetooth 5.x extended advertising capabilities.
 *
 *  This demo will advertise 2 advertisements, and extended scannable instance
 *  and a connectable legacy instance. They will advertise for 5 seconds then
 *  sleep for 20 seconds. The extended scannable instance will use the scan
 *  request callback to update it's data when a scan response is requested.
 *
 *  Created: on April 9 2022
 *      Author: H2zero
 */

 #include <main.h>
 
 #if !CONFIG_BT_NIMBLE_EXT_ADV
 # error Must enable extended advertising, see nimconfig.h file.
 #endif
 
 #define SERVICE_UUID        "ABCD"
 #define CHARACTERISTIC_UUID "1234"
 
 /** Time in milliseconds to advertise */
 static uint32_t advTime = 25000;
 
 /** Time to sleep between advertisements */
 static uint32_t sleepSeconds = 2;

 uint16_t teller=0;
 
 /** Primary PHY used for advertising, can be one of BLE_HCI_LE_PHY_1M or BLE_HCI_LE_PHY_CODED */
 static uint8_t primaryPhy = BLE_HCI_LE_PHY_1M;
 
 /**
  *  Secondary PHY used for advertising and connecting,
  *  can be one of BLE_HCI_LE_PHY_1M, BLE_HCI_LE_PHY_2M or BLE_HCI_LE_PHY_CODED
  */
 static uint8_t secondaryPhy = BLE_HCI_LE_PHY_1M;

_ServerCallbacks serverCallbacks;
_AdvCallbacks advCallbacks;

 /** Handler class for server events */
void _ServerCallbacks::onConnect(NimBLEServer* pServer, NimBLEConnInfo& connInfo) 
{
  teller++;
  Serial.printf("Client connected: %s\n", connInfo.getAddress().toString().c_str());
}
 
void _ServerCallbacks::onDisconnect(NimBLEServer* pServer, NimBLEConnInfo& connInfo, int reason) 
{
  Serial.printf("Client disconnected\n");
  // if still advertising we won't sleep yet.
  if (!pServer->getAdvertising()->isAdvertising()) {
    Serial.printf("Sleeping for %" PRIu32 " seconds\n", sleepSeconds);
    systemRestart(); // nRF platforms restart then sleep via delay in setup.
  }
} 


void _ServerCallbacks::onIdentity	(	NimBLEConnInfo & 	connInfo	)	
{
  teller++;
  Serial.printf("Client id: %s\n", connInfo.getAddress().toString().c_str());
}

//void _ServerCallbacks::
 
/** Callback class to handle advertising events */
void _AdvCallbacks::onStopped(NimBLEExtAdvertising* pAdv, int reason, uint8_t instId)  
{
  /* Check the reason advertising stopped, don't sleep if client is connecting */
  Serial.printf("Advertising instance %u stopped\n", instId);
  switch (reason) {
    case 0:
        Serial.printf(" client connecting\n");
        return;
    case BLE_HS_ETIMEOUT:
        Serial.printf("Time expired - sleeping for %" PRIu32 " seconds\n", sleepSeconds);
        break;
    default:
        break;
  }
  systemRestart(); // nRF platforms restart then sleep via delay in setup.
}
 
 
void _AdvCallbacks::onScanRequest(NimBLEExtAdvertising* pAdv, uint8_t instId, NimBLEAddress addr) 
{
  Serial.printf("Scan request for instance %u\n", instId);
  // if the data has already been updated we don't need to change it again.
  if (!m_updatedSR) {
      Serial.printf("Updating scan data\n");
      NimBLEExtAdvertisement sr;
      sr.setServiceData(NimBLEUUID(SERVICE_UUID), std::string("Hello from scan response!"));
      pAdv->setScanResponseData(instId, sr);
      m_updatedSR = true;
  }
}


 void setup() {
 #ifndef ESP_PLATFORM
     delay(sleepSeconds * 1000); // system ON sleep mode for nRF platforms to simulate the esp deep sleep with timer wakeup
 #endif
     Serial.begin(115200);
 
     /** Initialize NimBLE and set the device name */
     NimBLEDevice::init("Multi advertiser");
     NimBLEDevice::setDefaultPhy(primaryPhy, secondaryPhy);
     NimBLEDevice::setPower(8); // Set the power level to maximum (9dBm)
   
     /** Create a server for our legacy advertiser */
     NimBLEServer* pServer = NimBLEDevice::createServer();
     pServer->setCallbacks(&serverCallbacks);
 
     NimBLEService*        pService = pServer->createService(SERVICE_UUID);
     NimBLECharacteristic* pCharacteristic =
         pService->createCharacteristic(CHARACTERISTIC_UUID,
                                        NIMBLE_PROPERTY::READ | NIMBLE_PROPERTY::WRITE | NIMBLE_PROPERTY::NOTIFY);
 
     pCharacteristic->setValue("Hello World");
 
     /** Start the service */
     pService->start();
 
     /** Create our multi advertising instances */
 
     /** extended scannable instance advertising on coded and 1m PHY's. */
     NimBLEExtAdvertisement extScannable(primaryPhy, secondaryPhy);
 
     /** Legacy advertising as a connectable device. */
     NimBLEExtAdvertisement legacyConnectable;
 
     /** Optional scan response data. */
     NimBLEExtAdvertisement legacyScanResponse;
 
     /** As per Bluetooth specification, extended advertising cannot be both scannable and connectable */
     extScannable.setScannable(false);
     extScannable.setConnectable(true);
 
     /** Set the initial data */
     extScannable.setServiceData(NimBLEUUID(SERVICE_UUID), std::string("Scan me!"));
 
     /** Enable the scan response callback, we will use this to update the data. */
     extScannable.enableScanRequestCallback(true);
 
     /** Optional custom address for this advertisment. */
     legacyConnectable.setAddress(NimBLEAddress("DE:AD:BE:EF:BA:AD", 1));
 
     /** Set the advertising data. */
     legacyConnectable.setName("Legacy");
     legacyConnectable.setCompleteServices16({NimBLEUUID(SERVICE_UUID)});
 
     /** Set the legacy and connectable flags. */
     legacyConnectable.setLegacyAdvertising(true);
     legacyConnectable.setConnectable(true);
 
     /** Put some data in the scan response if desired. */
     legacyScanResponse.setServiceData(NimBLEUUID(SERVICE_UUID), "Legacy SR");
 
     /** Get the advertising ready */
     NimBLEExtAdvertising* pAdvertising = NimBLEDevice::getAdvertising();
 
     /** Set the callbacks to handle advertising events */
     pAdvertising->setCallbacks(&advCallbacks);
 
     /**
      *  Set instance data.
      *  Up to 5 instances can be used if configured in menuconfig, instance 0 is always available.
      *
      *  We will set the extended scannable data on instance 0 and the legacy data on instance 1.
      *  Note that the legacy scan response data needs to be set to the same instance (1).
      */
     if (pAdvertising->setInstanceData(0, extScannable) && pAdvertising->setInstanceData(1, legacyConnectable) &&
         pAdvertising->setScanResponseData(1, legacyScanResponse)) {
         /**
          *  NimBLEExtAdvertising::start takes the advertisement instance ID to start
          *  and a duration in milliseconds or a max number of advertisements to send (or both).
          */
         if (pAdvertising->start(0, advTime) && pAdvertising->start(1, advTime)) {
             Serial.printf("Started advertising\n");
         } else {
             Serial.printf("Failed to start advertising\n");
         }
     } else {
         Serial.printf("Failed to register advertisement data\n");
     }
 }
 
 void loop() 
 {
  Serial.printf("%d ", teller);
 }

The logging on the monitor shows this

I NimBLEDevice: BLE Host Task Started
I NimBLEDevice: NimBle host synced.
D NimBLEDevice: >> setPower: 8
D NimBLEDevice: TX power set to 8 dBm

D NimBLEService: >> start(): Starting service: UUID: 0xabcd, handle: 0x0000
D NimBLEService: Adding 1 characteristics for service UUID: 0xabcd, handle: 0x0000
D NimBLEService: << start()
primary service
           uuid 0x1800
         handle 1
     end_handle 5
characteristic
           uuid 0x2a00
     def_handle 2
     val_handle 3
   min_key_size 0
          flags [READ]
characteristic
           uuid 0x2a01
     def_handle 4
     val_handle 5
   min_key_size 0
          flags [READ]
primary service
           uuid 0x1801
         handle 6
     end_handle 13
characteristic
           uuid 0x2a05
     def_handle 7
     val_handle 8
   min_key_size 0
          flags [INDICATE]
ccc descriptor
           uuid 0x2902
         handle 9
   min_key_size 0
          flags [READ|WRITE]
characteristic
           uuid 0x2b3a
     def_handle 10
     val_handle 11
   min_key_size 0
          flags [READ]
characteristic
           uuid 0x2b29
     def_handle 12
     val_handle 13
   min_key_size 0
          flags [READ|WRITE]
primary service
           uuid 0xabcd
         handle 14
     end_handle 17
characteristic
           uuid 0x1234
     def_handle 15
     val_handle 16
   min_key_size 0
          flags [READ|WRITE|NOTIFY]
ccc descriptor
           uuid 0x2902
         handle 17
   min_key_size 0
          flags [READ|WRITE]
Started advertising
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0

The zero's at the end are repeating until the device reboots as designed in the demo code - showing that it is alive an that there is not a call to the onConnect or anything else. I don't know how to see logging on my phone. I use BLE Scanner, I see the device, I can click CONNECT and the it shows Connected, discovering services..., but after some seconds the status is Disconnected again. When I upload this code to a ESP32S3 it will connect and I can look into the characteristics.

Do you have any idea??

@juricabi
Copy link

juricabi commented Apr 6, 2025

Tried the same, it gives

Image, with legacy advertising everything works, thank you for your efforts.

@djdehaan
Copy link
Author

djdehaan commented Apr 6, 2025

@juricabi:

, with legacy advertising everything works, thank you for your efforts.

you mean, using NimBLEAdvertisement in stead of NimBLEExtAdvertisement?
That is what I also experience. Thanks for showing these loggings.

I found out how and am now also able to see these loggings using nRF connect app! Same result:

Image

@h2zero
Copy link
Owner

h2zero commented Apr 7, 2025

Thanks to both of you for the info, I will have a look to see what could be causing this, I suspect an issue in the stack which is not always easy to find.

@djdehaan
Copy link
Author

djdehaan commented Apr 7, 2025

Maybe relevant: connecting with my phone to the extended advertiser results in exact the same errors and messages.

@djdehaan
Copy link
Author

@h2zero Any luck finding this issue? Would appreciate a fix very much!

@h2zero
Copy link
Owner

h2zero commented Apr 13, 2025

@djdehaan I've been able to reproduce it but I've been too busy with other (paid) work to find the cause yet. Hopefully this week.

@h2zero
Copy link
Owner

h2zero commented Apr 18, 2025

@djdehaan The fix is in the nimble core update PR #891 , you can use this for now but beware that it will change, also the n-able core will be updated soon to better work with this.

@djdehaan
Copy link
Author

@h2zero Great! It indeed solves the problem. I found a way to use this fixed version and now indeed I can connect to the device using extended advertising! For who want to know: i downloaded this version as a lib in the project folder /lib manually

git clone https://github.com/h2zero/NimBLE-Arduino.git
git fetch origin pull/891/head:pr-891
git checkout pr-891

Will that mean that in the next release I can revert back to the platformio lib_deps parameter?

lib_deps = 
	;h2zero/NimBLE-Arduino@^2.2.3

@h2zero
Copy link
Owner

h2zero commented Apr 23, 2025

Closing this as fixed in #891

You are able to reference this in platformio via the commit sha:

lib_deps = https://github.com/h2zero/NimBLE-Arduino#8f32a23

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants