Nano 33 IoT BLE communication auto connect

I want to BLE communication to connect automatically.
However, if the power is turned on again after the power supply is interrupted, the connection is not made.

Is there something wrong with my code?

central code:

BLEService batteryService("1101");
BLEUnsignedCharCharacteristic batteryLevelChar("1101", BLERead | BLEWrite);

char buf[20];

void setup() {
  Serial.begin(9600);

  pinMode(LED_BUILTIN, OUTPUT);
  if(!BLE.begin()) {
    Serial.println("Starting BLE Failed!");
    while(1);
  }

  BLE.setLocalName("BatteryMonitor");
  BLE.setAdvertisedService(batteryService);
  batteryService.addCharacteristic(batteryLevelChar);
  BLE.addService(batteryService);

  BLE.advertise();
  Serial.println("Bluetooth Device Active, Waiting for Connections...");
}

void loop() {
  BLEDevice central = BLE.central();

  if(central) {
    Serial.print("Connected to Central: ");
    Serial.println(central.address());
    digitalWrite(LED_BUILTIN, HIGH);

    while(central.connected()) {
      int battery = analogRead(A0);
      int batteryLevel = map(battery, 0, 1023, 0, 100);

      Serial.print("Battery Level % is now : ");
      Serial.println(batteryLevel);
      batteryLevelChar.writeValue(batteryLevel);
      delay(400);
    }
  }

  digitalWrite(LED_BUILTIN, LOW);
  Serial.print("Disconnected from Central: ");
  Serial.println(central.address());
} 

peripheral code:


void setup() {
  Serial.begin(9600);
  Serial1.begin(9600);
  BLE.begin();
  Serial.println("BLE Central - BatteryMonitor");
  BLE.scanForUuid("1101");
}

void loop() {
  BLEDevice peripheral = BLE.available();
  if (peripheral) {
    if (peripheral.localName() != "BatteryMonitor") {
      return;
    }
    BLE.stopScan();
    controlLed(peripheral);   
  }
}

void controlLed(BLEDevice peripheral) {

  Serial.println("Connecting...");
  if (peripheral.connect()) {
    Serial.println("Connected");
  } else {
    Serial.println("Failed to connect!");
    return;
  }

  Serial.println("Discovering attributes ...");
  if (peripheral.discoverAttributes()) {
    Serial.println("Attributes discovered");
  } else {
    Serial.println("Attribute discovery failed!");
    peripheral.disconnect();
    return;
  }

  BLECharacteristic ledCharacteristic = peripheral.characteristic("1101");

  if (!ledCharacteristic) {
    Serial.println("Peripheral does not have LED characteristic!");
    peripheral.disconnect();
    return;
  } else if (!ledCharacteristic.canWrite()) {
    Serial.println("Peripheral does not have a writable LED characteristic!");
    peripheral.disconnect();
    return;
  }

  while (ledCharacteristic.canRead()) {
    ledCharacteristic.read();
    if (ledCharacteristic.valueLength() > 0) {

      printData(ledCharacteristic.value(), ledCharacteristic.valueLength());

    }
  }
}

void printData(const unsigned char data[], int length) {
  for (int i = 0; i < length; i++) {
    unsigned char b = data[i];
    Serial.println(b, DEC);
    Serial1.println(b, DEC);

  }
}

Yes, in your peripheral code you stop scanning when you found a peripheral. When you disconnect, you need to enable scanning again. Otherwise BLE.available will not return any new peripherals including the one it just disconnected from.

Regarding your UUIDs, the second U stands for unique. Your service and characteristic have the same UUID the must not be the same.
If you create a service and characteristic defined by the Bluetooth SIG you can use 16-bit UUIDs, otherwise you must use 128-bit random UUIDs. You can use a online UUID generator to create your UUIDs or write a script yourself.

As a tip, always confirm that the peripheral device is working first. Use a generic BLE app on your smartphone. If everything (connecting, read, write, disconnect, ...) works, test everything with the central sketch. In the current case, I suspect you can connect again after the connection is lost with a BLE app.
I like BLE Scanner on iOS, but there are many others on iOS and Android. EFR Connect and nRF Connect are useful as well. Each app has something they do better than the rest. Try a few.

Thanks for your kindness.
After seeing the answer, I have two more questions.

  1. Could I simply delete BLE.stopscan to enable scanning again?
    if not, should I add like if(!peripheral) inside the loop?

  2. If you change the UUID of characteristic, do I need to scan the changed UUID for BLE.scanForUuid()
    And should I put the changed UUID in BLECharacteristic ledCharacteristic = peripheral.characteristic()?

In your central sketch, in loop() controlLED() is a blocking call. It will only returns when the connection is lost. You can call scan just after that.

Yes, when you change the UUIDs you need to scan for the UUIDs your device is advertising.

Have a look around in the forum. There are more examples I and others have posted with different tricks to make the code easier to read and avoid the blocking nature of your current code. You should try to make your code run loop as often as possible. This way you can extend the code to do something useful.

Does it matter if other loops are added other than void loop?(ex. void controlLed/void printData)

Is it advantageous to put all the code inside a void loop?

The loop() function is part of the Arduino framework and called for you continuously. Ideally you should just call high level functions from within loop to keep it clean and simple.

Modern compilers will optimize the code for you better than most programmers can. Use functions to structure your code. Avoid long functions with lot of logic as much as possible. Make the code easy to read and understand and do not worry about the overhead of calling functions. Give your functions and variable good names and make sure the function only do what the names says. e.g., if you have a function called readSensor make it read the sensor values and not print the values to a display in the same function. Store the values and have a separate function display the values.
Try using only high level functions in loop. e.g.,

loop()
{
  readSensors();
  calculateValues();
  updateDisplay();
  printData();
  updateBLE();
}

This will make it easier for your and others to read, understand and maintain your code.