BLE Advertising Stops After Few Minutes (when CPU is idle)

Igor_Pener
Sun, 06 Mar 2022 12:39:20 +0000
Mbed OS

Hi there, I can’t reconnect to my Arduino Nano 33 BLE over Bluetooth® LE after the CPU is idle for about 5-10 minutes. The Arduino has a nRF52840 SoC which has support for low power mode. I suspect that Mbed OS enters sleep/deep sleep mode after some time and is unable to walk up from it. To prevent the system from going into sleep I’ve tried calling sleep_manager_lock_deep_sleep as well as implementing a no-op idle hook and calling rtos::Kernel::attach_idle_hook(&idle_hook) before advertising as suggested here but unfortunately the problem persists. Here’s the minimal code (without any error handling) to replicate the issue:

#include "mbed.h"
#include "BLE.h"
#include "events/EventQueue.h"

using namespace ble;
using namespace mbed;

static uint8_t advData[31] = {
    0x02, 0x01, 0x06, 0x12, 0xFF, 0x4C, 0x00, 0x06,
    0x2D, 0x01, 0xFE, 0x6D, 0x74, 0x72, 0xD9, 0xCC,
    0x05, 0x00, 0x01, 0x00, 0x01, 0x02, 0x08, 0x08,
    0x41, 0x63, 0x6D, 0x65, 0x20, 0x4C, 0x69
};
static events::EventQueue eq;

void advertise() {
    AdvertisingParameters params(
        advertising_type_t::CONNECTABLE_UNDIRECTED,
        adv_interval_t(millisecond_t(20))
    );

    auto &ble = BLE::Instance();
    auto &gap = ble.gap();

    gap.setAdvertisingParameters(LEGACY_ADVERTISING_HANDLE, params);
    gap.setAdvertisingPayload(LEGACY_ADVERTISING_HANDLE, { advData, sizeof(advData) });
    gap.startAdvertising(LEGACY_ADVERTISING_HANDLE);
}

struct EventHandler: public Gap::EventHandler {
    void onDisconnectionComplete(const DisconnectionCompleteEvent &event) override {
        advertise();
    }
};

void onInitComplete(BLE::InitializationCompleteCallbackContext *event) {
    if (!event->error) {
        advertise();
    }
}

void scheduleEvents(BLE::OnEventsToProcessCallbackContext *event) {
    eq.call(&event->ble, &BLE::processEvents);
}

int main() {
    EventHandler handler;

    auto &ble = BLE::Instance();
    auto &gap = ble.gap();

    gap.setEventHandler(&handler);
    ble.onEventsToProcess(scheduleEvents);
    ble.init(onInitComplete);

    eq.dispatch_forever();
}

I’ve used LightBlue® to connect to the Arduino. If I keep connecting/disconnecting every 2-3 minutes the system doesn’t seem to go into sleep mode. However, if I keep it disconnected for 5-10 minutes it’s no longer discoverable. I’m not sure whether this is a bug or maybe a configuration issue. Any help on how to resolve this, i.e. either prevent sleep or properly wake up on BLE activity, would be appreciated.

1 post - 1 participant