Hi. I'm working on a project using Nano ESP32s that will turn on LEDs if they get within a certain range of another device with the same name. I am using the bluetooths RSSI as a way to determine their proximity to each other, and I'm using a kalman filter to smooth out some of the noise in that signal. This method does work fairly well for getting the distance pretty close, but the shortest scantime being 1 second is way too slow. I'm working in distances of at most a foot, so a lot of movement can happen in 1 second. Is there any way to scan faster?
/*
Bluetooth Proximity
This example scans for Bluetooth® Low Energy peripherals with a specific name, and then turns on LEDs if within a certain range
The circuit:
- Arduino Nano ESP32
SimpleKalmanFilter(e_mea, e_est, q);
e_mea: Measurement Uncertainty
e_est: Estimation Uncertainty
q: Process Noise
*/
#include <BLEDevice.h>
#include <BLEUtils.h>
#include <BLEScan.h>
#include <BLEAdvertisedDevice.h>
#include <SimpleKalmanFilter.h>
int scanTime = 1; //In seconds
BLEScan* pBLEScan;
const int CUTOFF = -42; // signal strength limit (closer to 0 the closer the devices have to be)
bool flip = true;
const int led = 9; // the PWM pin the LED is attached to
int brightness = 0; // how bright the LED is
int fadeAmount = 5; // how many points to fade the LED by
unsigned long ledTimePrev = 0; // will store last time pin 9 was update
const long ledInterval = 30; // interval at which to fade led
bool inRange = false;
SimpleKalmanFilter bleFilter(4, 4, .1);
const long SERIAL_REFRESH_TIME = 1;
long refreshTime;
class MyAdvertisedDeviceCallbacks: public BLEAdvertisedDeviceCallbacks {
void onResult(BLEAdvertisedDevice advertisedDevice) {
// Serial.printf("Advertised Device: %s \n", advertisedDevice.toString().c_str());
String strName;
strName = advertisedDevice.getName().c_str();
if ( strName == "SS13" ) {
float signal = advertisedDevice.getRSSI();
float estimatedSignal = bleFilter.updateEstimate(signal);
if (millis() > refreshTime) {
refreshTime = millis() + SERIAL_REFRESH_TIME;
}
if (estimatedSignal > CUTOFF) { // device is in range
inRange = true;
} else { // device is out of range
inRange = false;
}
}
}
};
void setup() {
Serial.begin(115200);
Serial.println("Scanning...");
pinMode(LED_RED, OUTPUT);
if (flip) {
brightness = 255;
}
BLEDevice::init("SS13");
BLEDevice::startAdvertising();
pBLEScan = BLEDevice::getScan(); //create new scan
pBLEScan->setAdvertisedDeviceCallbacks(new MyAdvertisedDeviceCallbacks());
pBLEScan->setActiveScan(true); //active scan uses more power, but get results faster
pBLEScan->setInterval(100);
pBLEScan->setWindow(99); // less or equal setInterval value
}
void loop() {
BLEScanResults foundDevices = pBLEScan->start(scanTime, false);
fadeLED(LED_RED);
pBLEScan->clearResults(); // delete results fromBLEScan buffer to release memory
}
void fadeLED(int l) {
unsigned long currentMillis = millis();
if (currentMillis - ledTimePrev >= ledInterval) {
// save the last time you blinked the LED
ledTimePrev = currentMillis;
if (flip) {
if (inRange && brightness > 0) { // if in range and less than max, increase
brightness = brightness - fadeAmount;
} else if (!inRange && brightness < 255) { // if out of range and greater than 0, decrease
brightness = brightness + fadeAmount;
}
} else {
if (inRange && brightness < 255) { // if in range and less than max, increase
brightness = brightness + fadeAmount;
} else if (!inRange && brightness > 0) { // ir out of range and greater than 0, decrease
brightness = brightness - fadeAmount;
}
}
// set brightness
analogWrite(l, brightness);
}
}