Thanks,
Not sure if I am running out of memory or if it is a timing issue. I haven’t managed to get my jlink debug running yet, but that is a story for another post.
Powered via USB for testing, has a regulated 5v supply in the field, not battery powered.
Setup calls the startScanner function which contains the standard Bluefruit settings for an Observer.
The callback needs to run as fast as possible so the only function there is to move the received packet into a queue for later processing, increment the counter, then end.
Loop firstly checks if we have any new scans from the callback to process, dequeue, then process.
Secondly we check those processed scans to link the scans and responses together as a single object, some sensors store data in the scan others store it in the response. The packet is then forwarded to the packetCheck function for decode the Manufactorer Data depending on the sensor type.
Lastly the loop checks every 10 seconds if the callback Count has increased, there are multple sensors we should be catching multiple scans each second.
There are other files managing decoding the different sensor types, global settings, and serializing to JSON to send to the data logger.
void setup()
{
#ifdef DEBUG_LOCAL
Serial.begin(115200);
#endif
Serial1.begin(57600); // Serial1 to send data to the Logger ESP32
// delay(10); // for nrf52840 with native usb
DEBUG_PRINTLN("BLE Scan to Serial");
DEBUG_PRINTLN("------------------------------------\n");
startScanner();
}
void loop()
{
if (callbackQueueItemCount() > 0)
{
// DEBUG_PRINT("Callback Queue Depth: ");
// DEBUG_PRINT(callbackQueueItemCount());
// DEBUG_PRINTLN();
ble_gap_evt_adv_report_t report = callbackDequeue();
scan_callback_process(&report);
return;
}
// uint32_t startTime = micros();
// Process packets from the queue
// only process if there are 2 or more packets in queue
if (queueItemCount() >= 2)
{
BlePacket sensorBLEPacket;
BlePacket packet = dequeuePacket();
BlePacket packet2 = dequeuePacket();
{
if (packet.ScanResponse == 0 && packet2.ScanResponse == 0)
{ // process packet and return packet2 to the start of the queue
// DEBUG_PRINT("Scan & Scan ");
if (packet.deviceNameLength > 0)
{
sensorBLEPacket = packet;
}
queueInsertStart(packet2);
memset(&packet2, 0, sizeof(packet2));
}
else if (packet.ScanResponse == 0 && packet2.ScanResponse == 1)
{ // merge packet and packer 2 then process
// DEBUG_PRINT("Scan & Response ");
if (packet.AddressString == packet2.AddressString)
{
if (packet.deviceNameLength > 0 || packet2.deviceNameLength > 0) // Or
{
sensorBLEPacket = mergePacket(packet, packet2);
}
else
{
sensorBLEPacket = emptyPacket; // Clear the packet
}
}
else
{
sensorBLEPacket = packet;
}
}
else
{ // drop packet and return packet2 to the start of the queue
sensorBLEPacket = emptyPacket; // Clear the packet
}
if (sensorBLEPacket.deviceNameLength > 0)
{
packetCheck(sensorBLEPacket);
}
memset(&packet, 0, sizeof(packet));
memset(&packet2, 0, sizeof(packet2));
memset(&sensorBLEPacket, 0, sizeof(sensorBLEPacket));
}
}
else
{
uint32_t checkTime = millis();
if (checkTime == lastCheckTime)
{
return;
}
lastCheckTime = checkTime;
if (checkTime % 10000 == 0) // Every 10 seconds
{
DEBUG_PRINT("Total Time :");
DEBUG_PRINT(millis());
DEBUG_PRINT(" Queue Depth: ");
DEBUG_PRINT(queueItemCount());
DEBUG_PRINT(" Callback Queue Depth: ");
DEBUG_PRINT(callbackQueueItemCount());
DEBUG_PRINT(" Callback Count: ");
DEBUG_PRINT(callbackCount);
DEBUG_PRINT(" Scanner Running: ");
DEBUG_PRINT(Bluefruit.Scanner.isRunning());
DEBUG_PRINTLN();
if (callbackLastCount == callbackCount)
{
DEBUG_PRINTLN("*** Scanner Stopped - Restarting ***");
startScanner();
}
callbackLastCount = callbackCount;
}
}
}
void startScanner()
{
// Initialize Bluefruit with maximum connections as Peripheral = 0, Central = 1
// SRAM usage required by SoftDevice will increase dramatically with number of connections
Bluefruit.begin(0, 1);
Bluefruit.setTxPower(0); // Check bluefruit.h for supported values
/* Set the device name */
Bluefruit.setName("Bluefruit52");
/* Set the LED interval for blinky pattern on BLUE LED */
Bluefruit.setConnLedInterval(250); // Only for testing
// Bluefruit.setConnLedInterval(false); // Turn off in Prod
/* Start Central Scanning
* - Enable auto scan if disconnected
* - Filter out packet with a min rssi
* - Interval = 100 ms, window = 50 ms
* - Use active scan (used to retrieve the optional scan response adv packet)
* - Start(0) = will scan forever since no timeout is given
*/
Bluefruit.Scanner.setRxCallback(scan_callback);
Bluefruit.Scanner.restartOnDisconnect(true);
// Bluefruit.Scanner.filterMSD(0xFFFF); // Filter on Manufacturer Specific Data
// Bluefruit.Scanner.filterRssi(-80);
// Bluefruit.Scanner.setInterval(160, 80); // in units of 0.625 ms
Bluefruit.Scanner.setIntervalMS(100, 100);
Bluefruit.Scanner.useActiveScan(true); // Request scan response data
Bluefruit.Scanner.start(0); // 0 = Don't stop scanning after n seconds
DEBUG_PRINTLN("Scanning ...");
}
void scan_callback(ble_gap_evt_adv_report_t *report)
{
// Add the packet to the queue
callbackQueueInsert(report);
callbackCount++;
Bluefruit.Scanner.resume();
}
void callbackQueueInsert(ble_gap_evt_adv_report_t *report)
{
// Check if the queue is full
if ((callbackQueueEnd + 1) % MAX_QUEUE_SIZE == callbackQueueStart)
{
DEBUG_PRINT("Callback Queue Max Depth: ");
DEBUG_PRINT(callbackQueueItemCount());
DEBUG_PRINTLN();
// Queue is full, handle overflow (e.g., discard oldest packet)
callbackDequeue();
}
// Add the packet to the end of the queue
callbackQueue[callbackQueueEnd] = *report;
callbackQueueEnd = (callbackQueueEnd + 1) % MAX_QUEUE_SIZE;
}