Hier möchte ich ein Sketch zu Bluetooth Ortung vorstellen. Hiermit lässt sich ein versteckte iBeacon finden. Esp32 scannt nach Bluetooth LE Geräten. Wenn ein Bluetooth Gerät mit bestimmten Namen gefunden wird, wird eine Verbindung aufgebaut. Esp32 frag 10 Mal pro Sekunde nach der Signalstärke RSSI. Ein Messwertfilter filtert die Ausreißer im RSSI Wert. Auf der LCD-Anzeige wird ein Mittelwert 2 Mal pro Sekunde erneuert.
Arduino Sketch für esp32 mit Ausgabe über serielle Schnittstelle
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 |
/* nRF51822 iBeacon Suchgerät mit RSSI Anzeige ESP32 Sucht nach einem iBeacon mit bestimmten Namen, Paart und misst RSSI 10 mal pro Sekunde. Gleitender Mittelwert Filter (running average) für RSSI glättet Ausreißer. Michael Dworkin http://esp32-server.de/ Based on Neil Kolban example */ #include <BLEDevice.h> static boolean Verbinde = false; // Phasen static boolean Verbunden = false; static boolean Suche = true; int scanTime = 10; // In Bluetooth Scanzeit in secunden String BuetoothName = "RDL51822"; // Bluetooth Name des iTags #define FilterFaktor 0.2 // running average Filter Einstellung float val_f; // 0,05 erhöht die Verspätung bei Änderung, macht aber das Wert stabiler int zeler=1; static BLEAddress *pServerAddress; static BLEClient* pClient; static BLEAdvertisedDevice* myDevice; static BLERemoteCharacteristic* pRemoteCharacteristic; BLEScan* pBLEScan ; class MyAdvertisedDeviceCallbacks: public BLEAdvertisedDeviceCallbacks { void onResult(BLEAdvertisedDevice advertisedDevice) // passiert wenn BLE Device ( beacon ) gefunden wurde { Serial.print(advertisedDevice.getAddress().toString().c_str()); // ibeacon Adresse anzeigen if (advertisedDevice.haveName()) if (advertisedDevice.getName() == BuetoothName.c_str()) // ibeacon Adresse Vergleichen { Serial.print(" gefunden " + BuetoothName); // wenn überwache Adresse gefunden wurde BLEDevice::getScan()->stop(); // Scanvorgang beenden myDevice = new BLEAdvertisedDevice(advertisedDevice); Verbinde = true; Suche = false; } Serial.println(""); } }; class MyClientCallback : public BLEClientCallbacks { void onConnect(BLEClient* pclient) { Serial.println("Verbunden"); Verbunden = true; Verbinde = false; } void onDisconnect(BLEClient* pclient) { Verbunden = false; Verbinde = false; Suche = true; Serial.println("Verbindung verloren"); } }; void setup() { Serial.begin(115200); Serial.println(""); Serial.println("Starte RSSI Meter für " + BuetoothName); BLEDevice::init(""); pBLEScan = BLEDevice::getScan(); pBLEScan->setAdvertisedDeviceCallbacks(new MyAdvertisedDeviceCallbacks()); pBLEScan->setActiveScan(true); pBLEScan->setInterval(1349); pBLEScan->setWindow(449); pBLEScan->start(scanTime); } void loop() { if (Suche) pBLEScan->start(scanTime); if (Verbinde == true) { Serial.print("Verbinde mit "); Serial.println(myDevice->getAddress().toString().c_str()); pClient = BLEDevice::createClient(); pClient->setClientCallbacks(new MyClientCallback()); pClient->connect(myDevice); } if (Verbunden) // Gepaart { delay(100); // RSSI alle 100 mS abfragen // ----------------- Messwert Filter ------------------ val_f = pClient->getRssi() * FilterFaktor + val_f * (1 - FilterFaktor); if (!zeler) // Ausgabe jeder 5 durchlauf (2x pro Sekunde) { Serial.println(int(round(val_f))); // Runden und Ganze Zahl bilden zeler = 5; } else zeler--; } } |
iBeacon Suchgerät mit OLED Display
Das Display ist ein 128X64 1,3 Zoll OLED LCD mit I2C Schnittstelle.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 |
#include <BLEDevice.h> static boolean Verbinde = false; // Phasen static boolean Verbunden = false; static boolean Suche = true; int scanTime = 10; // In Bluetooth Scanzeit in secunden String BuetoothName = "RDL51822"; // Bluetooth Name des iTags #define FilterFaktor 0.1 // running average Filter Einstellung float val_f; // 0,05 erhöht die Verspätung bei Änderung, macht aber das Wert stabiler int zeler = 1; static BLEAddress *pServerAddress; static BLEClient* pClient; static BLEAdvertisedDevice* myDevice; static BLERemoteCharacteristic* pRemoteCharacteristic; BLEScan* pBLEScan ; #include <SPI.h> #include <Wire.h> #include "Adafruit_GFX.h" #include "Adafruit_SH1106.h" #include <Fonts/FreeSans12pt7b.h> #include <Fonts/FreeMonoBold24pt7b.h> #define OLED_SDA 12 #define OLED_SCL 14 Adafruit_SH1106 display(OLED_SDA, OLED_SCL); class MyAdvertisedDeviceCallbacks: public BLEAdvertisedDeviceCallbacks { void onResult(BLEAdvertisedDevice advertisedDevice) // passiert wenn BLE Device ( beacon ) gefunden wurde { Serial.print(advertisedDevice.getAddress().toString().c_str()); // ibeacon Adresse anzeigen if (advertisedDevice.haveName()) if (advertisedDevice.getName() == BuetoothName.c_str()) // ibeacon Adresse Vergleichen { Serial.print(" gefunden " + BuetoothName); // wenn überwache Adresse gefunden wurde // Ausschaltverzögerung zurücksetzen BLEDevice::getScan()->stop(); // Scanvorgang beenden myDevice = new BLEAdvertisedDevice(advertisedDevice); Verbinde = true; Suche = false; display.clearDisplay(); display.setCursor(0, 32 + 6); display.println("Gefunden"); display.display(); } Serial.println(""); } }; class MyClientCallback : public BLEClientCallbacks { void onConnect(BLEClient* pclient) { Serial.println("Verbunden"); Verbunden = true; Verbinde = false; display.setFont(&FreeMonoBold24pt7b); } void onDisconnect(BLEClient* pclient) { Verbunden = false; Verbinde = false; Suche = true; Serial.println("Verbindung verloren"); display.setFont(&FreeSans12pt7b); } }; void setup() { Serial.begin(115200); Serial.println(""); Serial.println("Starte RSSI Meter für " + BuetoothName); display.begin(SH1106_SWITCHCAPVCC, 0x3C); // initialize with the I2C addr 0x3D (for the 128x64) display.clearDisplay(); display.display(); display.setTextColor(WHITE); display.setCursor(0, 32 + 6); display.setFont(&FreeSans12pt7b); display.println("START"); display.display(); BLEDevice::init(""); pBLEScan = BLEDevice::getScan(); pBLEScan->setAdvertisedDeviceCallbacks(new MyAdvertisedDeviceCallbacks()); pBLEScan->setActiveScan(true); pBLEScan->setInterval(1349); pBLEScan->setWindow(449); pBLEScan->start(scanTime); } void loop() { if (Suche) { display.clearDisplay(); display.setCursor(0, 32 + 6); display.println("Suche"); display.display(); pBLEScan->start(scanTime); } if (Verbinde == true) { Serial.print("Verbinde mit "); Serial.println(myDevice->getAddress().toString().c_str()); pClient = BLEDevice::createClient(); pClient->setClientCallbacks(new MyClientCallback()); pClient->connect(myDevice); } if (Verbunden) // Gepaart { delay(100); // RSSI alle 100 mS abfragen // ----------------- Messwert Filter ------------------ val_f = pClient->getRssi() * FilterFaktor + val_f * (1 - FilterFaktor); if (!zeler) // Ausgabe jeder 5 durchlauf (2x pro Sekunde) { Serial.println(int(round(val_f))); // Runden und Ganze Zahl bilden display.clearDisplay(); display.setCursor(10, 44); display.println(int(round(val_f))); display.display(); zeler = 5; } else zeler--; } } |