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
}
-
Did you ever resolve this issue?NobbysNutz– NobbysNutz03/28/2023 13:44:48Commented Mar 28, 2023 at 13:44
-
Hi, IIRC I never solved this.. sryPhilipp– Philipp03/28/2023 14:24:14Commented Mar 28, 2023 at 14:24
2 Answers 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;
}
}
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
}