Hello esben1703,
So I did a bit more digging and found out that part of the problem you are having is down to the fact that when a connection occurs the BLE will stop advertising. The other part is that your code currently "hangs" in the while connected loop.
To overcome this I used something called an Event Handler. These are used to, as the name indicates, handle certain events when they happen by executing functions. You can look into these more in the BLE library
I tested this using the following code for the Peripheral (on a Nano 33 Sense) which just switches the LED every 100ms and updates the characteristics to match:
#include <ArduinoBLE.h>
BLEService ledService("19B10000-E8F2-537E-4F6C-D104768A1214"); // BLE LED Service
BLEByteCharacteristic switchCharacteristic("19B10001-E8F2-537E-4F6C-D104768A1214", BLERead | BLENotify);
const int ledPin = LED_BUILTIN; // pin to use for the LED
unsigned long last_time = 0;
void ConnectHandler(BLEDevice central) {
// central connected event handler
Serial.print("Connected event, central: ");
Serial.println(central.address());
BLE.advertise();
}
void DisconnectHandler(BLEDevice central) {
// central disconnected event handler
Serial.print("Disconnected event, central: ");
Serial.println(central.address());
BLE.advertise();
}
void setup() {
Serial.begin(9600);
while (!Serial)
;
// set LED pin to output mode
pinMode(ledPin, OUTPUT);
// begin initialization
if (!BLE.begin()) {
Serial.println("starting BLE failed!");
while (1)
;
}
BLE.setEventHandler(BLEConnected, ConnectHandler);
BLE.setEventHandler(BLEDisconnected, DisconnectHandler);
// set advertised local name and service UUID:
BLE.setLocalName("LED");
BLE.setAdvertisedService(ledService);
// add the characteristic to the service
ledService.addCharacteristic(switchCharacteristic);
// add service
BLE.addService(ledService);
// set the initial value for the characeristic:
switchCharacteristic.writeValue(0);
// start advertising
BLE.advertise();
Serial.println("BLE LED Peripheral");
}
void loop() {
unsigned long current_time = millis();
BLE.poll();
if(current_time - last_time > 100){
last_time = current_time;
//Sensor Code/Functions would go here
if (!switchCharacteristic.value()) {
switchCharacteristic.writeValue(1);
Serial.println("LED on");
digitalWrite(ledPin, HIGH);
} else {
switchCharacteristic.writeValue(0);
Serial.println("LED off");
digitalWrite(ledPin, LOW);
}
}
}
Then the central code (on a Nano 33 IoT) look like this:
#include <ArduinoBLE.h>
void listenLed(BLEDevice peripheral) {
// connect to the peripheral
Serial.println("Connecting ...");
if (peripheral.connect()) {
Serial.println("Connected");
} else {
Serial.println("Failed to connect!");
return;
}
// discover peripheral attributes
Serial.println("Discovering attributes ...");
if (peripheral.discoverAttributes()) {
Serial.println("Attributes discovered");
} else {
Serial.println("Attribute discovery failed!");
peripheral.disconnect();
return;
}
// retrieve the LED characteristic
BLECharacteristic ledCharacteristic = peripheral.characteristic("19b10001-e8f2-537e-4f6c-d104768a1214");
if (!ledCharacteristic) {
Serial.println("Peripheral does not have LED characteristic!");
peripheral.disconnect();
return;
}
if (!ledCharacteristic.subscribe()) {
Serial.println("Subscription failed!");
peripheral.disconnect();
return;
}
while (peripheral.connected()) {
if (ledCharacteristic.valueUpdated()) {
byte v = 0;
ledCharacteristic.readValue(v);
Serial.print("LED Value: ");
Serial.println(v);
}
}
Serial.println("Peripheral disconnected");
}
void setup() {
Serial.begin(9600);
while (!Serial);
// configure the button pin as input
// initialize the BLE hardware
BLE.begin();
Serial.println("BLE Central - LED control");
// start scanning for peripherals
BLE.scanForUuid("19b10000-e8f2-537e-4f6c-d104768a1214");
}
void loop() {
// check if a peripheral has been discovered
BLEDevice peripheral = BLE.available();
if (peripheral) {
// discovered a peripheral, print out address, local name, and advertised service
Serial.print("Found ");
Serial.print(peripheral.address());
Serial.print(" '");
Serial.print(peripheral.localName());
Serial.print("' ");
Serial.print(peripheral.advertisedServiceUuid());
Serial.println();
if (peripheral.localName() != "LED") {
return;
}
// stop scanning
BLE.stopScan();
listenLed(peripheral);
// peripheral disconnected, start scanning again
BLE.scanForUuid("19b10000-e8f2-537e-4f6c-d104768a1214");
}
}
Now I didn't actually have two IoT's on hand but this does work with one IoT and my phone using nRF Connect (a great app for testing BLE stuff). I was able to get the IoT and phone to subscribe to the changes of the LED state.
However, this does occasionally crash. This is I think in part due to a yet to be fixed bug in the Sense which causes its BLE Module to crash sometimes when it disconnects and means it has to be reset manually.
Anyway, I hope that helps, I put a comment where I think your sensor code would go. Obviously, this set up would be sensing all the time if you know how many centrals you will need you can use the event handler to count before starting. Let me know if you have any questions
Thanks
Matt