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
}
dda
1,5951 gold badge12 silver badges17 bronze badges
asked Sep 25, 2022 at 13:23
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;
 }
}
ocrdu
1,7953 gold badges12 silver badges24 bronze badges
answered Jul 22, 2023 at 17:16
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
}
answered Oct 26, 2024 at 16:02

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.