Hi there,
So, Thanks but I only added what was missing , may still need adjustments it was late so I pushed it out and wasn’t able to test it but i will today.
HTH
GL PJ
seems like a super fit for Xiao device for sure
EDIT
Like this
and everything appears to be in order but you will need to test .

this code (bypasses the halt if no DRV is connected)
// ===============================================================
// CalmBand — DRV2605 BLE Haptics with "SensorNode-style" UI
// Board : Seeed XIAO nRF52840 Sense + Dev Expansion (SSD1306 I2C)
// Features: DRV2605 RTP metronome/heartbeat, BLE control,
// OLED status (B=BLE, M=Motor active), RGB status LED (active-LOW),
// buzzer beeps, auto re-advertise after disconnect.
// Rev : 2025-10-09
// ===============================================================
#include <Arduino.h>
#include <Wire.h>
#include <ArduinoBLE.h>
#include <U8x8lib.h>
#include "Adafruit_DRV2605.h"
// ---------------- Build info banner ----------------
#define REVISION "CalmBand UI REV A"
static void printBuildInfo() {
String filename = String(__FILE__);
int lastSlash = filename.lastIndexOf('/');
if (lastSlash == -1) lastSlash = filename.lastIndexOf('\\');
String sketchName = filename.substring(lastSlash + 1);
Serial.println("\n=== Build Info ===");
Serial.println("Sketch : " + sketchName);
Serial.println("Version : " + String(REVISION));
Serial.println("Compiled : " + String(__DATE__) + " " + String(__TIME__));
Serial.println("==================\n");
}
// ---------------- Pins & board setup ----------------
// Button on XIAO D1 (active-low, internal pullup)
#ifndef D1
#define D1 1
#endif
#define BUTTON_PIN D1
// Buzzer on expansion base (adjust if different)
#define BUZZER_PIN A3
// Prefer core-defined RGB if available (active-LOW on XIAO nRF52840 Sense)
#ifndef LEDR
// Fallback pins if your core doesn’t define LEDR/G/B:
#define LEDR D10
#define LEDG D9
#define LEDB D8
#endif
// Active-LOW LEDs on XIAO
#define LED_ACTIVE_LOW 1
// Device name shown in BLE
#define BLE_NAME "CalmBand"
// ---------------- OLED ----------------
U8X8_SSD1306_128X64_NONAME_HW_I2C oled(U8X8_PIN_NONE);
// ---------------- DRV2605 ----------------
Adafruit_DRV2605 drv;
// ---------------- BLE service & characteristics ----------------
BLEService hapticsService("12345678-1234-1234-1234-1234567890ab");
BLEByteCharacteristic modeChar ("12345678-1234-1234-1234-1234567890ac", BLERead | BLEWrite); // 0=metronome,1=heartbeat
BLEByteCharacteristic powerChar("12345678-1234-1234-1234-1234567890ad", BLERead | BLEWrite); // 0..100
BLEUnsignedShortCharacteristic onMsChar ("12345678-1234-1234-1234-1234567890ae", BLERead | BLEWrite); // ms
BLEUnsignedShortCharacteristic offMsChar("12345678-1234-1234-1234-1234567890af", BLERead | BLEWrite); // ms
BLEByteCharacteristic activeChar("12345678-1234-1234-1234-1234567890b0", BLERead | BLEWrite); // 0/1
// ---------------- App state ----------------
uint8_t gMode = 0; // 0=metronome, 1=heartbeat
uint8_t gPower = 60; // 0..100 (maps to RTP 0..127)
uint16_t gOnMs = 150; // metronome ON
uint16_t gOffMs = 850; // metronome OFF
bool gActive = false; // running?
// Button debounce
bool lastBtn = HIGH;
bool toggled = false;
unsigned long lastDebounce = 0;
const unsigned long debounceMs = 30;
// Pattern scheduler
unsigned long tNow = 0;
unsigned long tNext = 0;
enum Phase { IDLE, MET_ON, MET_OFF, HB_BEAT1_ON, HB_GAP, HB_BEAT2_ON, HB_REST };
Phase phase = IDLE;
enum BleState { BLE_ADV, BLE_CONN, BLE_DISC };
BleState bleState = BLE_ADV;
unsigned long discShownUntil = 0;
const unsigned long DISC_FLASH_MS = 1000;
// ---------------- Small helpers ----------------
static inline void ledWrite(uint8_t pin, bool on) {
// `on` means "light should be ON"
if (LED_ACTIVE_LOW) digitalWrite(pin, on ? LOW : HIGH);
else digitalWrite(pin, on ? HIGH : LOW);
}
static inline void setLED(bool r, bool g, bool b) {
ledWrite(LEDR, r);
ledWrite(LEDG, g);
ledWrite(LEDB, b);
}
static inline void ledBlue() { setLED(false, false, true); }
static inline void ledGreen() { setLED(false, true, false); }
static inline void ledRed() { setLED(true, false, false); }
static inline void ledOff() { setLED(false, false, false); }
// Buzzer tones
static void startSound() {
tone(BUZZER_PIN, 890); delay(220); noTone(BUZZER_PIN); delay(20);
tone(BUZZER_PIN, 800); delay(220); noTone(BUZZER_PIN); delay(20);
tone(BUZZER_PIN, 800); delay(220); noTone(BUZZER_PIN); delay(20);
tone(BUZZER_PIN, 990); delay(420); noTone(BUZZER_PIN); delay(20);
}
static void beepConnected() { tone(BUZZER_PIN, 880); delay(250); noTone(BUZZER_PIN); }
static void beepDisconnected() { delay(200); tone(BUZZER_PIN, 480); delay(300); noTone(BUZZER_PIN); }
// DRV helpers
static void drvBeginRTP() {
drv.setMode(DRV2605_MODE_REALTIME);
drv.selectLibrary(6);
drv.useERM();
}
static inline uint8_t mapPower(uint8_t p) {
if (p > 100) p = 100;
return (uint8_t)((p * 127) / 100);
}
static inline void vibOn() { drv.setRealtimeValue(mapPower(gPower)); }
static inline void vibOff() { drv.setRealtimeValue(0); }
static void startMetronome() { phase = MET_ON; tNext = millis(); }
static void startHeartbeat() { phase = HB_BEAT1_ON; tNext = millis(); }
static void stopAll() { vibOff(); phase = IDLE; }
// BLE writes
static void applyBLEWritesIfAny() {
if (modeChar.written()) gMode = modeChar.value();
if (powerChar.written()) gPower = powerChar.value();
if (onMsChar.written()) gOnMs = onMsChar.value();
if (offMsChar.written()) gOffMs = offMsChar.value();
if (activeChar.written()) gActive = activeChar.value() != 0;
}
static void pushBLEStateToChars() {
modeChar.writeValue(gMode);
powerChar.writeValue(gPower);
onMsChar.writeValue(gOnMs);
offMsChar.writeValue(gOffMs);
activeChar.writeValue(gActive ? 1 : 0);
}
// Button (active-low)
static void handleButtonToggle() {
bool reading = digitalRead(BUTTON_PIN);
if (reading != lastBtn) {
lastDebounce = millis();
lastBtn = reading;
}
if ((millis() - lastDebounce) > debounceMs) {
if (reading == LOW && !toggled) {
gActive = !gActive;
activeChar.writeValue(gActive ? 1 : 0);
toggled = true;
if (!gActive) stopAll();
} else if (reading == HIGH) {
toggled = false;
}
}
}
// Pattern loops
const uint16_t HB_INTERBEAT_GAP_MS = 150;
static void loopMetronome() {
tNow = millis();
switch (phase) {
case MET_ON:
vibOn();
tNext = tNow + gOnMs;
phase = MET_OFF;
break;
case MET_OFF:
if ((long)(tNow - tNext) >= 0) {
vibOff();
tNext = tNow + gOffMs;
phase = MET_ON;
}
break;
default: break;
}
}
static void loopHeartbeat() {
tNow = millis();
switch (phase) {
case HB_BEAT1_ON:
vibOn();
tNext = tNow + gOnMs;
phase = HB_GAP;
break;
case HB_GAP:
if ((long)(tNow - tNext) >= 0) {
vibOff();
tNext = tNow + HB_INTERBEAT_GAP_MS;
phase = HB_BEAT2_ON;
}
break;
case HB_BEAT2_ON:
if ((long)(tNow - tNext) >= 0) {
vibOn();
tNext = tNow + gOnMs;
phase = HB_REST;
}
break;
case HB_REST:
if ((long)(tNow - tNext) >= 0) {
vibOff();
tNext = tNow + gOffMs;
phase = HB_BEAT1_ON;
}
break;
default: break;
}
}
// ---------------- OLED UI ----------------
static bool oledInited = false;
static bool flagBLE = false; // shows "B"
static bool flagMOTOR = false; // shows "M"
static void oledBanner(bool connected, bool advertising) {
if (!oledInited) return;
oled.clear();
// Title
oled.setFont(u8x8_font_7x14_1x2_r);
oled.drawString(2, 0, "CalmBand");
// Big “label” in middle (like your node number)
oled.setFont(u8x8_font_inb33_3x6_r);
oled.drawString(5, 2, "H"); // just a big monogram “H” for Haptics
// Flags column
oled.setFont(u8x8_font_7x14_1x2_r);
oled.drawString(9, 2, flagBLE ? "B" : " ");
oled.drawString(9, 5, flagMOTOR ? "M" : " ");
// Status bottom line
oled.setFont(u8x8_font_chroma48medium8_r);
if (connected) oled.drawString(2, 7, "Connected ");
else if (advertising) oled.drawString(2, 7, "Advertising ");
else oled.drawString(2, 7, "Idle ");
}
static void oledRefreshFlags() {
if (!oledInited) return;
oled.setFont(u8x8_font_7x14_1x2_r);
oled.drawString(9, 2, flagBLE ? "B" : " ");
oled.drawString(9, 5, flagMOTOR ? "M" : " ");
}
// ---------------- Setup / Loop ----------------
void setup() {
Serial.begin(115200);
delay(50);
Serial.println();
Serial.println(F("CalmBand power-up..."));
printBuildInfo();
pinMode(BUTTON_PIN, INPUT_PULLUP);
pinMode(BUZZER_PIN, OUTPUT);
pinMode(LEDR, OUTPUT);
pinMode(LEDG, OUTPUT);
pinMode(LEDB, OUTPUT);
ledBlue(); // start as advertising look
// OLED init
oled.begin();
oled.setFlipMode(1);
oledInited = true;
oled.clear();
oled.setFont(u8x8_font_chroma48medium8_r);
oled.drawString(0, 0, "Power ON");
// Power on sound
startSound();
// DRV2605
Wire.begin();
if (!drv.begin()) {
Serial.println(F("ERROR: DRV2605 not found! Halt."));
oled.drawString(0, 6, "DRV2605 ERROR");
//while (1) { delay(10); }
}
drvBeginRTP();
vibOff();
// BLE
if (!BLE.begin()) {
Serial.println(F("ERROR: BLE init failed"));
oled.drawString(0, 6, "BLE ERROR");
while (1) { delay(10); }
}
BLE.setLocalName(BLE_NAME);
BLE.setDeviceName(BLE_NAME);
BLE.setAdvertisedService(hapticsService);
hapticsService.addCharacteristic(modeChar);
hapticsService.addCharacteristic(powerChar);
hapticsService.addCharacteristic(onMsChar);
hapticsService.addCharacteristic(offMsChar);
hapticsService.addCharacteristic(activeChar);
BLE.addService(hapticsService);
pushBLEStateToChars();
BLE.advertise();
bleState = BLE_ADV;
flagBLE = false;
flagMOTOR = false;
oledBanner(false, true);
Serial.println(String("BLE advertising as \"") + BLE_NAME + "\"");
}
static void updateBleLedAndOled(bool connectedJustNow, bool disconnectedJustNow) {
if (connectedJustNow) {
bleState = BLE_CONN;
flagBLE = true;
ledGreen();
beepConnected();
oledBanner(true, false);
return;
}
if (disconnectedJustNow) {
bleState = BLE_DISC;
flagBLE = false;
ledRed();
beepDisconnected();
discShownUntil = millis() + DISC_FLASH_MS;
oledBanner(false, false);
return;
}
if (bleState == BLE_DISC) {
if ((long)(millis() - discShownUntil) >= 0) {
bleState = BLE_ADV;
ledBlue();
oledBanner(false, true);
}
}
}
void loop() {
BLEDevice central = BLE.central();
static bool wasConnected = false;
bool isConnected = central && central.connected();
bool connectedJustNow = ( isConnected && !wasConnected);
bool disconnectedJustNow = (!isConnected && wasConnected);
applyBLEWritesIfAny();
updateBleLedAndOled(connectedJustNow, disconnectedJustNow);
wasConnected = isConnected;
// Button toggles motor active
handleButtonToggle();
flagMOTOR = gActive;
oledRefreshFlags();
// Start/stop state machine
if (!gActive) {
stopAll();
} else if (phase == IDLE) {
if (gMode == 0) startMetronome();
else startHeartbeat();
}
// Run active pattern
if (gActive) {
if (gMode == 0) loopMetronome();
else loopHeartbeat();
}
// Re-advertise “heartbeat” already handled by BLE library; if you want
// explicit stop/start after disconnect, you can do:
// if (bleState == BLE_ADV && !BLE.connected()) { /* still advertising */ }
}
HTH
GL PJ