Hi there,
And Welcome Here…
So what you have won’t reliably “auto-reconnect” on Android without an app. Two key points why, then a drop-in fix:
Why it never reconnects
- Android does not auto-reconnect to arbitrary BLE peripherals just because they’re “paired.” It’ll reconnect on its own only for certain system-managed profiles (e.g., HID keyboards/mice), or when an app on the phone actively reconnects in the background. Pairing alone doesn’t create an OS watchdog.
- Your sketch relies on
restartOnDisconnect(true), which should restart advertising—but some library/version combos are picky. A bullet-proof pattern is to explicitly restart advertising indisconnect_callback()and never block boot on USB serial.
Minimal code fixes (keeps your logic)
- Don’t stall on
while (!Serial)—that can delay init and advertising. - Explicitly call
startAdv()indisconnect_callback()(don’t depend solely onrestartOnDisconnect). - Keep fast advertising running long enough to be seen again (or just keep it “fast” indefinitely if you want aggressive reconnect).
The “While Serial” will block EVERYTHING if No Usb is plugged in , IE battery only. Won’t run unless You comment that out.![]()
#include <bluefruit.h>
#define LED_PIN D2
void startAdv(void);
void setup() {
Serial.begin(115200);
// Do NOT block waiting for USB; we want immediate advertising
// while (!Serial) {/* no wait */}
pinMode(LED_PIN, OUTPUT);
digitalWrite(LED_PIN, HIGH); // light ON when not connected
Bluefruit.begin();
Bluefruit.setName("XIAO_nRF52840");
Bluefruit.setTxPower(0); // -20 was very low; 0 dBm is a sane default
Bluefruit.Periph.setConnectCallback(connect_callback);
Bluefruit.Periph.setDisconnectCallback(disconnect_callback);
// Conservative: we’ll explicitly restart in the disconnect callback
Bluefruit.Advertising.restartOnDisconnect(false);
startAdv();
Serial.println("BLE Peripheral started. Ready for connection…");
}
void loop() {
// nothing
}
void connect_callback(uint16_t conn_handle) {
digitalWrite(LED_PIN, LOW); // OFF when connected
Serial.println("Connected");
}
void disconnect_callback(uint16_t conn_handle, uint8_t reason) {
digitalWrite(LED_PIN, HIGH); // ON when disconnected/out of range
Serial.print("Disconnected, reason=0x"); Serial.println(reason, HEX);
// Be explicit: immediately resume advertising so the phone can find us again
startAdv();
}
void startAdv(void) {
Bluefruit.Advertising.clearData();
Bluefruit.ScanResponse.clearData();
Bluefruit.Advertising.addFlags(BLE_GAP_ADV_FLAGS_LE_ONLY_GENERAL_DISC_MODE);
Bluefruit.Advertising.addTxPower();
Bluefruit.ScanResponse.addName();
// Keep advertising easy to catch — either keep "fast" or make slow modest
Bluefruit.Advertising.setInterval(32 /*20ms*/, 80 /*50ms*/);
Bluefruit.Advertising.setFastTimeout(0); // never drop to slow (optional)
// If you prefer slow after a while, use:
// Bluefruit.Advertising.setFastTimeout(60);
// Bluefruit.Advertising.setInterval(160 /*100ms*/, 244 /*152.5ms*/);
Bluefruit.Advertising.start(0); // advertise forever
}
Well, now If you truly want AUTO-Reconnect with ZERO app.
Two robust options:
- Run as a BLE HID device (keyboard/mouse). Android’s system manages those and will reconnect in the background. Adafruit’s Bluefruit nRF52 library has HID examples—light goes off when HID connected, back on when not.
- Write a tiny Android background service (Tasker/MacroDroid or a simple app) that reconnects to the GATT peripheral. That’s how most BLE gadgets do it.
HTH
GL
PJ
The MIT AI2 app inventor for App I use on Android 15 (moto RaZr +) BLE to Nrf52840 Sense. It works this way, My app scans BLE I can connect to my_chioce device. then Disconnect , the PAIR for it. Keep in mind the firmware doesn’t have any bonding or pairing code in it(nrf52840) side. The phone Remembers the connection because I did the pairing, it doesn’t auto connect BUT when I scan in my app its first Always in the list and connects fast when I pick it. once connected I get 3 notify’s (motion,FALL,Battery) Can Lock and Unlock the device.
![]()