Hi All,
I am hoping someone can give me a steer in the right direction. I am just trying to make some decisions on the best approach to design a 1 to Many BLE relationship, Boron (Central Device) to Argons (Peripheral Devices). At a high level, when our boron devices identifies a certain sensor based event it scans and connects to a designated argon. Once connected it sends a command and awaits acknowledgement. It continues sending command to argon until acknowledged. After ACK is received, it returns to normal operation.
While all this is happening, one or more argons are cycling through sleep for x seconds, they wakeup and wait for a set period for a potential targeted connection from the central Boron. If a connection is established the Boron will send a command for the argon to execute, after executing it will wait for a short period of time to see if an additional command comes from the central device. If this does not happen then the device disconnects and returns to sleep.
I have attempted to illustrate this workflow in the attached diagram, apologies that it is not laid out very well.
IMPLEMENTATION
At present I am planning on using Ricks “BleSerialPeripheralRK.h” library for my Argon Peripherals. I will attach the device numbers to advertised data and this can be used to enable the central Boron to target a specific peripheral to connect to. This seems to be working when tested with an android app.
For the central boron I am trying to use some code from the particle docs:
https://docs.particle.io/tutorials/device-os/bluetooth-le/#uart-central
Actual code below. When I try to load this to a Boron it gets stuck in a cycle where it tries to connect to cell (green flash) then tries to connect to cloud (rapid cyan flash) then just when I would expect to see breathing cyan, the device resets as if the reset button was pressed.
Questions
- Is using BLE UART a good idea for this use case?
- Does anyone know what I am doing incorrectly with the UART central code below?
- How do I get the central device to scan for a specific peripheral device? Hoping to use device numbers here to connect to correct peripheral?
- Does anyone know what a suitable cycle time is for an argon to wake from sleep, turn on ble and wait for a connection to be established by the central?
Thanks in advance
// This example does not require the cloud so you can run it in manual mode or
// normal cloud-connected mode
// SYSTEM_MODE(MANUAL);
// These UUIDs were defined by Nordic Semiconductor and are now the defacto standard for
// UART-like services over BLE. Many apps support the UUIDs now, like the Adafruit Bluefruit app.
const BleUuid serviceUuid("6E400001-B5A3-F393-E0A9-E50E24DCCA9E");
const BleUuid rxUuid("6E400002-B5A3-F393-E0A9-E50E24DCCA9E");
const BleUuid txUuid("6E400003-B5A3-F393-E0A9-E50E24DCCA9E");
const size_t UART_TX_BUF_SIZE = 20;
const size_t SCAN_RESULT_COUNT = 20;
BleScanResult scanResults[SCAN_RESULT_COUNT];
BleCharacteristic peerTxCharacteristic;
BleCharacteristic peerRxCharacteristic;
BlePeerDevice peer;
uint8_t txBuf[UART_TX_BUF_SIZE];
size_t txLen = 0;
const unsigned long SCAN_PERIOD_MS = 2000;
unsigned long lastScan = 0;
void onDataReceived(const uint8_t* data, size_t len, const BlePeerDevice& peer, void* context) {
for (size_t ii = 0; ii < len; ii++) {
Serial.write(data[ii]);
}
}
void setup() {
Serial.begin();
BLE.on();
peerTxCharacteristic.onDataReceived(onDataReceived, &peerTxCharacteristic);
}
void loop() {
if (BLE.connected()) {
while (Serial.available() && txLen < UART_TX_BUF_SIZE) {
txBuf[txLen++] = Serial.read();
Serial.write(txBuf[txLen - 1]);
}
if (txLen > 0) {
// Transmit the data to the BLE peripheral
peerRxCharacteristic.setValue(txBuf, txLen);
txLen = 0;
}
}
else {
if (millis() - lastScan >= SCAN_PERIOD_MS) {
// Time to scan
lastScan = millis();
size_t count = BLE.scan(scanResults, SCAN_RESULT_COUNT);
if (count > 0) {
for (uint8_t ii = 0; ii < count; ii++) {
// Our serial peripheral only supports one service, so we only look for one here.
// In some cases, you may want to get all of the service UUIDs and scan the list
// looking to see if the serviceUuid is anywhere in the list.
BleUuid foundServiceUuid;
size_t svcCount = scanResults[ii].advertisingData().serviceUUID(&foundServiceUuid, 1);
if (svcCount > 0 && foundServiceUuid == serviceUuid) {
peer = BLE.connect(scanResults[ii].address());
if (peer.connected()) {
peer.getCharacteristicByUUID(peerTxCharacteristic, txUuid);
peer.getCharacteristicByUUID(peerRxCharacteristic, rxUuid);
// Could do this instead, but since the names are not as standardized, UUIDs are better
// peer.getCharacteristicByDescription(peerTxCharacteristic, "tx");
}
break;
}
}
}
}
}
} ```