0

I want to scan continuously for other Bluetooth devices with my ESP32 using BLE. The scan method only accepts integers larger than 0, such as scan->start(1, false). However I want the results to be more "responsive" and a 1-second scanning duration is too long. This is my sample code:

#include <Arduino.h>
#include <BLEAdvertisedDevice.h>
#include <BLEDevice.h>
#include <BLEScan.h>
#include <string>
#include <iostream>

const int PIN = 2;
const int CUTOFF = -40;
BLEScan* scan;

#define SERVICE_UUID "f5aeb701-4395-4387-b8d4-e1f542b05151"
#define CHARACTERISTIC_UUID "b2bd617f-6f78-45e7-bfdd-3edf29a5661a"

void setup() {
  pinMode(PIN, OUTPUT);
  BLEDevice::init("ESP32 GrooveBrick");
  Serial.begin(9600);
  BLEServer *pServer = BLEDevice::createServer();
  BLEService *pService = pServer->createService(SERVICE_UUID);
  BLECharacteristic *pCharacteristic = pService->createCharacteristic(
    CHARACTERISTIC_UUID,
    BLECharacteristic::PROPERTY_READ | BLECharacteristic::PROPERTY_WRITE);
  pService->start();
  BLEAdvertising *pAdvertising = BLEDevice::getAdvertising();
  pAdvertising->addServiceUUID(SERVICE_UUID);
  pAdvertising->setScanResponse(true);
  pAdvertising->setMinPreferred(0x06);  // functions that help with iPhone connections issue
  pAdvertising->setMinPreferred(0x12);
  scan = BLEDevice::getScan();
  scan->setActiveScan(true);
  /*!< Scan interval. This is defined as the time interval from
    when the Controller started its last LE scan until it begins the subsequent LE scan.
    Range: 0x0004 to 0x4000 Default: 0x0010 (10 ms)
    Time = N * 0.625 msec
    Time Range: 2.5 msec to 10.24 seconds*/
  scan->setInterval(100); //interval (how often there is a scan)
  /*!< Scan window. The duration of the LE scan. LE_Scan_Window
    shall be less than or equal to LE_Scan_Interval
    Range: 0x0004 to 0x4000 Default: 0x0010 (10 ms)
    Time = N * 0.625 msec
    Time Range: 2.5 msec to 10240 msec */
  scan->setWindow(99);  // window (how long the scans are) must be <= interval
  BLEDevice::startAdvertising();
}

void loop() {
  BLEScanResults results = scan->start(1, true);
  int best = CUTOFF;

  std::cout << "Scanning!" << "\n";
  for (int i = 0; i < results.getCount(); i++) {
    BLEAdvertisedDevice device = results.getDevice(i);
    std::cout << "Found BT-device: " << device.getName() << " RSSI: " << std::to_string(device.getRSSI()) << "\n";
    int rssi = device.getRSSI();
    if (rssi > best) {
      best = rssi;
    }
  }
  digitalWrite(PIN, best > CUTOFF ? HIGH : LOW);
  scan->clearResults();   // delete results fromBLEScan buffer to release memory
}
2
  • Did you ever resolve this issue? Commented Mar 28, 2023 at 13:44
  • Hi, IIRC I never solved this.. sry Commented Mar 28, 2023 at 14:24

2 Answers 2

2

You can't using the callback from that function, but what you can do is add you own callback that will receive every new radio event.

Add this to your init code:

BLEDevice::setCustomGapHandler(custom_handler);

and this before it:

static void it_gap_cb(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t *param)
{
    switch (event)
    {
        case ESP_GAP_BLE_SCAN_RESULT_EVT:
            if (param->scan_rst.search_evt == ESP_GAP_SEARCH_INQ_RES_EVT)
            {
                // This event is triggered every time a new device is found, and contains the advertised data.
                // We should avoid processing or printing anything here to avoid hardware congestion
                // log_i("ESP_GAP_BLE_SCAN_RESULT_EVT");

                if (param->scan_rst.ble_adv != NULL)
                {
                    //this makes sure that there is data to be processed
                }
            }
            break;
        default:
            // log_i("Event %d unhandled", event);
            break;
    }
}
0

the simplest solution is this: add this line:

BLEDevice::getScan()->stop();

Example:

#include <BLEDevice.h>
#include <BLEUtils.h>
#include <BLEScan.h>
#include <Arduino.h>


class MyAdvertisedDeviceCallbacks : public BLEAdvertisedDeviceCallbacks {
  void onResult(BLEAdvertisedDevice advertisedDevice) {
    // Hole die Service-Daten vom beworbenen Gerät
    //std::string serviceData = advertisedDevice.getServiceData();
    std::string deviceName = advertisedDevice.getName();
    if (!deviceName.empty() && deviceName.find("Drone_") != std::string::npos) { // Verwende .empty() anstelle von !
    Serial.println("Scan-Ergebnis gefunden:");

    // Ausgabe des Gerätetyps und der RSSI-Signalstärke
    Serial.print("Gerätename: ");
    Serial.println(advertisedDevice.getName().c_str());
    Serial.print("Signalstärke (RSSI): ");
    Serial.println(advertisedDevice.getRSSI());
    }

    BLEDevice::getScan()->stop();
  }
};

void setup() {
  Serial.begin(115200);
  delay(3000); // 1 Sekunde warten
  Serial.println("Startet kontinuierlichen BLE-Scan...");

  // BLE initialisieren
  BLEDevice::init("");
  

  // BLE-Scan konfigurieren
  BLEScan* pBLEScan = BLEDevice::getScan();
  pBLEScan->setAdvertisedDeviceCallbacks(new MyAdvertisedDeviceCallbacks());
  pBLEScan->setActiveScan(true); // Aktives Scannen für genauere RSSI-Werte
  pBLEScan->setInterval(32);    // Scan-Intervall in 0.625ms-Einheiten
  pBLEScan->setWindow(32);       // Scan-Fenster in 0.625ms-Einheiten
  
}

void loop() {
  // Starte den Scan ohne zeitliche Begrenzung und bereinige die Ergebnisse direkt danach
  BLEDevice::getScan()->start(0.1, true); // kurzer Scan, um wiederholte Ergebnisse zu ermöglichen

  //int deviceCount = BLEDevice::getScan()->getResults().getCount();
  //Serial.print("Anzahl gefundener Geräte: ");
  //Serial.println(deviceCount);


  BLEDevice::getScan()->clearResults();    // Bereinige die Ergebnisse sofort für den nächsten Scan
}

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.