FluxBench.AIShared project · read-only

BLE UART LED Remote

Seeed XIAO nRF52840·Arduino C++·Updated Jul 27, 2026·by FluxBench TeamIncludes Lab + Schematic

Control an LED over Bluetooth LE from a phone - the first nRF52 demo in the gallery. The XIAO nRF52840 advertises a BLE UART (Nordic UART Service); in the simulator a virtual phone connects about 2 seconds after boot and sends "led on", "blink" and "led off" every 3 seconds, so you can watch the LED react and the serial monitor echo each command without any hardware. On the real board, open Bluefruit Connect or nRF Connect, attach to FluxBench-BLE and type the same commands. Note the nRF52 gotcha the sketch handles for you: Serial needs #include <Adafruit_TinyUSB.h> on this core or the build fails to link.

sketch.ino
// BLE UART LED Remote - control an LED from your phone over Bluetooth LE.
// Board: Seeed XIAO nRF52840 (Adafruit Bluefruit nRF52 API).
// In the FluxBench simulator there is no real radio: a virtual phone connects
// about 2 seconds after Bluefruit.begin() and then sends the demo commands
// "led on", "blink" and "led off" over the BLE UART every 3 seconds, so you
// can watch the whole connect-receive-act flow without hardware.
// On the real board, use a BLE terminal app (Bluefruit Connect / nRF Connect)
// and type the same commands.
#include <bluefruit.h>
#include <Adafruit_TinyUSB.h> // REQUIRED on this core for Serial to link

#define LED_PIN 2 // D2 - external LED through a 330 ohm resistor

BLEUart bleuart; // BLE UART service (Nordic UART Service)
BLEDis bledis;   // Device Information Service

bool wasConnected = false;
bool blinking = false;
bool ledState = false;
unsigned long lastBlink = 0;

void setup() {
  Serial.begin(115200);
  pinMode(LED_PIN, OUTPUT);
  digitalWrite(LED_PIN, LOW);

  Bluefruit.begin();
  Bluefruit.setTxPower(4);
  Bluefruit.setName("FluxBench-BLE");

  bledis.setManufacturer("FluxBench");
  bledis.setModel("XIAO nRF52840");
  bledis.begin();
  bleuart.begin();

  Bluefruit.Advertising.addFlags(BLE_GAP_ADV_FLAGS_LE_ONLY_GENERAL_DISC_MODE);
  Bluefruit.Advertising.addTxPower();
  Bluefruit.Advertising.addService(bleuart);
  Bluefruit.Advertising.addName();
  Bluefruit.Advertising.restartOnDisconnect(true);
  Bluefruit.Advertising.setInterval(32, 244);
  Bluefruit.Advertising.setFastTimeout(30);
  Bluefruit.Advertising.start(0);

  Serial.println("Advertising as FluxBench-BLE ...");
  Serial.println("Connect with a BLE terminal and send: led on / led off / blink");
}

void loop() {
  if (Bluefruit.connected()) {
    if (!wasConnected) {
      wasConnected = true;
      Serial.println("Central connected!");
    }
    while (bleuart.available()) {
      String cmd = bleuart.readStringUntil('\n');
      Serial.print("RX: ");
      Serial.println(cmd);
      if (cmd.equals("led on")) {
        blinking = false;
        ledState = true;
        digitalWrite(LED_PIN, HIGH);
        bleuart.println("OK led is ON");
      } else if (cmd.equals("led off")) {
        blinking = false;
        ledState = false;
        digitalWrite(LED_PIN, LOW);
        bleuart.println("OK led is OFF");
      } else if (cmd.equals("blink")) {
        blinking = true;
        lastBlink = millis();
        bleuart.println("OK blinking");
      } else {
        bleuart.println("? try: led on / led off / blink");
      }
    }
  } else if (wasConnected) {
    wasConnected = false;
    Serial.println("Central disconnected - advertising again");
  }

  if (blinking && millis() - lastBlink >= 250) {
    lastBlink = millis();
    ledState = !ledState;
    digitalWrite(LED_PIN, ledState ? HIGH : LOW);
  }

  delay(20);
}

Built with FluxBench.AI — the AI workbench for embedded projects.