Hi there,
Awesome… 
Glad you got it going, on the Nrf52840 sense , there is a way to tell if the USB is plugged in,
1. XIAO nRF52840 (Adafruit / Nordic BSP)
Because the nRF52840 features a hardware VBUS regulator/detector, you can directly inspect the Nordic SoftDevice register to check for 5V presence (wall adapter, power bank, or PC host):
bool isUsbPluggedIn = (NRF_POWER->USBREGSTATUS & POWER_USBREGSTATUS_VBUSDETECT_Msk);
- Charging Pin (
P0.17 / Pin 23):
bool isCharging = (digitalRead(23) == LOW); // Active LOW from onboard BQ25101
2. XIAO ESP32-S3 (ESP32 Board Package)
The ESP32-S3 uses an internal USB_SERIAL_JTAG PHY. To read raw 5V USB power presence without needing a data host:
- Direct PHY Hardware Check:
#include "hal/usb_serial_jtag_ll.h"
bool isUsbPluggedIn = usb_serial_jtag_ll_phy_is_pad_valid();
- Data Host Connection Check (CDC Serial):
This is the same patch for the ESP32S3 Xiao
#include "hal/usb_serial_jtag_ll.h"
// Check for 5V USB presence on ESP32-S3
String getUsbStatusESP32S3() {
bool usbPower = usb_serial_jtag_ll_phy_is_pad_valid();
if (usbPower) {
if (Serial) {
return "USB In - Data Host Connected";
} else {
return "USB In - Power Only (Charger)";
}
} else {
return "USB Unplugged (Battery)";
}
}
Here is the code I tested it with , keeps the BLE connection, You can plug & unplug USB or Power bank and get the status over BLE..
connected , charging, idle, disconnected from it. 
/*
=============================================================================
Project: XIAO nRF52840 BLE USB & Battery Power Monitor
Target HW: Seeed Studio XIAO nRF52840 / XIAO nRF52840 Sense
BSP / Core: Seeed nRF52 mbed-enabled core / Adafruit nRF52 BSP
Framework: Arduino / Adafruit Bluefruit nRF52 Library
Description:
Monitors 5V VBUS state via direct nRF52840 hardware power registers
(POWER_USBREGSTATUS) and battery charging status via the onboard BQ25101
charge pin. Transmits real-time status updates over BLE via Custom UUID
characteristic notifications.
Onboard Hardware Mapping:
- LED_BLUE : Pin 12 (P0.06) - Active LOW (Blink = Adv, Solid = Connected)
- PIN_CHG : Pin 23 (P0.17) - Active LOW (Low = Charging, High = Idle/Battery)
- VBUS : Direct HW Register (NRF_POWER->USBREGSTATUS)
BLE Configuration:
- Device Name : XIAO-USB-Mon
- Service : Custom 128-bit [F0DEBC9A-7856-3412-7856-341278563412]
- Char (read/notify) : Custom 128-bit [F1DEBC9A-7856-3412-7856-341278563412]
=============================================================================
*/
#include <bluefruit.h>
// Onboard Pin Definitions for XIAO nRF52840
#define BLUE_LED LED_BLUE // Pin 12 (P0.06)
#ifndef PIN_CHG
#define PIN_CHG 23 // Pin P0.17 (Charge status, Active LOW)
#endif
#define LED_ON LOW
#define LED_OFF HIGH
// Custom 128-bit Service and Characteristic UUIDs
const uint8_t USB_SERVICE_UUID[16] = {
0xF0, 0xDE, 0xBC, 0x9A, 0x78, 0x56, 0x34, 0x12,
0x78, 0x56, 0x34, 0x12, 0x78, 0x56, 0x34, 0x12
};
const uint8_t USB_CHAR_UUID[16] = {
0xF1, 0xDE, 0xBC, 0x9A, 0x78, 0x56, 0x34, 0x12,
0x78, 0x56, 0x34, 0x12, 0x78, 0x56, 0x34, 0x12
};
BLEDis bledis;
BLEService usbService = BLEService(USB_SERVICE_UUID);
BLECharacteristic usbStatusChar = BLECharacteristic(USB_CHAR_UUID);
String lastStatusStr = "";
// Connection Callback: Turn Blue LED SOLID when connected
void connect_callback(uint16_t conn_handle) {
(void) conn_handle;
digitalWrite(BLUE_LED, LED_ON);
Serial.println(F("[BLE] Central Connected!"));
}
// Disconnection Callback: Turn Blue LED OFF & resume advertising
void disconnect_callback(uint16_t conn_handle, uint8_t reason) {
(void) conn_handle;
(void) reason;
digitalWrite(BLUE_LED, LED_OFF);
Serial.println(F("[BLE] Central Disconnected. Resuming advertising..."));
}
void startAdv(void) {
Bluefruit.Advertising.addFlags(BLE_GAP_ADV_FLAGS_LE_ONLY_GENERAL_DISC_MODE);
Bluefruit.Advertising.addTxPower();
// Custom Service in primary payload, Device Name in Scan Response
Bluefruit.Advertising.addService(usbService);
Bluefruit.ScanResponse.addName();
// Auto-restart advertising quickly if link drops
Bluefruit.Advertising.restartOnDisconnect(true);
Bluefruit.Advertising.setInterval(32, 244); // 20ms fast / 152.5ms slow
Bluefruit.Advertising.setFastTimeout(30);
Bluefruit.Advertising.start(0);
Serial.println(F("[BLE] Advertising started successfully!"));
}
void setup() {
pinMode(BLUE_LED, OUTPUT);
digitalWrite(BLUE_LED, LED_OFF);
pinMode(PIN_CHG, INPUT_PULLUP);
// Initialize Serial logging
Serial.begin(115200);
uint32_t startTime = millis();
while (!Serial && (millis() - startTime < 3000)); // Non-blocking 3s timeout for battery operation
Serial.println(F("\n--- XIAO nRF52840 BLE USB Monitor ---"));
// Prevent BSP from overriding our LED control
Bluefruit.autoConnLed(false);
Bluefruit.begin();
Bluefruit.setTxPower(4);
Bluefruit.setName("XIAO-USB-Mon");
Bluefruit.Periph.setConnectCallback(connect_callback);
Bluefruit.Periph.setDisconnectCallback(disconnect_callback);
// Device Information Service (Required for standard GAP discovery)
bledis.setManufacturer("Seeed Studio");
bledis.setModel("XIAO nRF52840");
bledis.begin();
// Custom USB Service setup
usbService.begin();
usbStatusChar.setProperties(CHR_PROPS_READ | CHR_PROPS_NOTIFY);
usbStatusChar.setPermission(SECMODE_OPEN, SECMODE_OPEN);
usbStatusChar.setMaxLen(32);
usbStatusChar.begin();
startAdv();
}
String getUsbStatus() {
// Direct hardware check on nRF52840 VBUS power status bit
bool usbPower = (NRF_POWER->USBREGSTATUS & POWER_USBREGSTATUS_VBUSDETECT_Msk);
bool isCharging = (digitalRead(PIN_CHG) == LOW);
if (!usbPower) {
return "USB Unplugged (Battery)";
} else if (isCharging) {
return "USB In - Charging";
} else {
return "USB In - Charged / Idle";
}
}
void loop() {
// Non-blocking Blue LED blink while advertising (waiting for connection)
if (!Bluefruit.connected()) {
static uint32_t lastBlink = 0;
if (millis() - lastBlink >= 300) {
lastBlink = millis();
digitalWrite(BLUE_LED, !digitalRead(BLUE_LED));
}
}
// Poll hardware USB and Charging status
String currentStatusStr = getUsbStatus();
// Send update only when physical power status changes
if (currentStatusStr != lastStatusStr) {
lastStatusStr = currentStatusStr;
Serial.print(F("[STATUS CHANGE] "));
Serial.println(currentStatusStr);
usbStatusChar.write(currentStatusStr.c_str(), currentStatusStr.length());
if (Bluefruit.connected() && usbStatusChar.notifyEnabled()) {
usbStatusChar.notify(currentStatusStr.c_str(), currentStatusStr.length());
Serial.println(F("[BLE] Sent Notification update to client."));
}
}
delay(20);
}
sketch_aug11a_BLE_report_USB.zip (1.9 KB)
HTH
GL
PJ 
And, Do us a solid and mark it as the solution so others can Find it Fast! 