Skip to content

THE TECHNIQUE

Breath-Based Interaction Concept

The wearer carries a thin nasal tube similar to those used in medical oxygen systems. When the wearer exhales, the airflow is directed through this tube onto a sound sensor / microphone inside the wearable. The resulting sound becomes the activation signal for the system: - Exhalation present → motor rotates & LEDs pulse - Breathing stops / silence → motor & LEDs stop The motor drives the Sargassum modules, causing the entire structure to gently move in response to the wearer’s breath. Through this motion, the wearable & the body begin to share a synchronized rhythm. What emerges is the sensation of a collective inhaling & exhaling — a quiet state of alignment in which human & artificial organism appear to breathe together, in harmony.

Hardware Assumptions

  • Seeed XIAO RP2040 operates at 3.3V logic level.
  • NeoPixels are powered with 5V & accept 3.3V data.
  • TB6612FNG motor driver logic (VCC) is powered by 3.3V.
  • TB6612FNG motor supply (VM) is powered by an external 5–9V source.
  • DC motor voltage rating matches the VM supply.
  • Sound Sensor V1.4 provides a digital trigger signal (SIG) when sound is detected.
  • All grounds are shared between XIAO, motor driver, NeoPixels, sound sensor, & power supply.
  • Power source can deliver enough current for motor & LEDs.

System Components & Functions

Order Category Component Description Function in System
1 Microcontroller Seeed XIAO RP2040 3.3V compact microcontroller Central control unit managing sound input, LED animation, and motor control
2 Programming Custom Arduino Code Non-blocking structured firmware Coordinates sound trigger, motor ramp behavior, and LED pulsing logic
3 Input Sound Sensor V1.4 (SIG) Microphone with comparator output Detects breath / speech and activates system while sound is present
4 Motor Control TB6612FNG Motor Driver Dual H-bridge driver Controls motor direction and speed via PWM signal
5 Actuation DC Motor Small rotational motor Generates mechanical rotation for movement system
6 Light Output 10× NeoPixel LEDs Individually addressable RGB LEDs Produce soft, pulsating, breathing-like illumination
7 Power – Logic XIAO 3.3V Output On-board voltage regulator Supplies logic voltage to motor driver and sound sensor
8 Power – Motor External Battery / Step-down 5–9V motor supply Provides motor operating voltage via TB6612 VM
9 Motion Transmission Gear Set (various sizes) Laser-cut acrylic gears Converts motor rotation into differentiated motion speeds
10 Motion Interface Rounded Wire Loops Bent metal transfer elements Transfers mechanical movement from gears outward
11 Wiring Jumper Wires / Soldered Connections Electrical connections Connects all electronic components into unified system

THE CODE

#include <Adafruit_NeoPixel.h>

// =====================
// NEOPIXELS
// =====================
#define LED_PIN   D0
#define LED_COUNT 10
Adafruit_NeoPixel strip(LED_COUNT, LED_PIN, NEO_GRB + NEO_KHZ800);

// =====================
// MOTOR (your wiring)
// =====================
#define STBY   D6
#define PWMA   D4
#define AIN1   D7
#define AIN2   D8

// =====================
// SOUND SENSOR V1.4 (SIG)
// =====================
#define SOUND_SIG D2   // SIG -> D2

// If your sensor outputs LOW when sound is detected, set this to LOW.
#define SOUND_ACTIVE_STATE HIGH

// =====================
// SYSTEM STATE
// =====================
bool systemOn = false;

// =====================
// MOTOR RAMP
// =====================
uint8_t motorTargetPWM = 0;
uint8_t motorCurrentPWM = 0;
const uint8_t motorRampStep = 3;
const unsigned long motorRampInterval = 10;
unsigned long lastMotorRampMs = 0;

// =====================
// LED PALETTE
// =====================
uint32_t colorsA[5];
uint32_t colorsB[5];

unsigned long cycleTime[5] = {
  3000,  // Pixel 1
  3500,  // Pixel 2
  4000,  // Pixel 3
  4500,  // Pixel 4
  5000   // Pixel 5
};

void setup() {
  // Motor
  pinMode(STBY, OUTPUT);
  pinMode(PWMA, OUTPUT);
  pinMode(AIN1, OUTPUT);
  pinMode(AIN2, OUTPUT);
  digitalWrite(STBY, HIGH);
  analogWrite(PWMA, 0);

  // Sound sensor signal
  pinMode(SOUND_SIG, INPUT); // if it floats, change to INPUT_PULLDOWN (see note below)

  // LEDs
  strip.begin();
  strip.setBrightness(40);
  strip.show();

  // Color pairs (your palette)
  colorsA[0] = strip.Color(245,240,220); // cream
  colorsB[0] = strip.Color(180,195,210); // dove blue

  colorsA[1] = strip.Color(210,190,180); // beige
  colorsB[1] = strip.Color(200,170,175); // rose

  colorsA[2] = strip.Color(200,170,175); // rose
  colorsB[2] = strip.Color(90,95,105);   // anthracite

  colorsA[3] = strip.Color(90,95,105);   // anthracite
  colorsB[3] = strip.Color(245,240,220); // cream

  colorsA[4] = strip.Color(245,240,220); // cream
  colorsB[4] = strip.Color(180,195,210); // dove blue
}

// Sound present -> ON, silence -> OFF
void handleSoundTrigger() {
  int sig = digitalRead(SOUND_SIG);
  systemOn = (sig == SOUND_ACTIVE_STATE);
}

void handleMotor() {
  motorTargetPWM = systemOn ? 25 : 0;

  unsigned long now = millis();
  if (now - lastMotorRampMs < motorRampInterval) return;
  lastMotorRampMs = now;

  if (motorCurrentPWM < motorTargetPWM) motorCurrentPWM += motorRampStep;
  if (motorCurrentPWM > motorTargetPWM) motorCurrentPWM -= motorRampStep;

  digitalWrite(AIN1, HIGH);
  digitalWrite(AIN2, LOW);
  analogWrite(PWMA, motorCurrentPWM);
}

void handleLEDs() {
  if (!systemOn) {
    strip.clear();
    strip.show();
    return;
  }

  unsigned long now = millis();

  for (int i = 0; i < 5; i++) {
    float phase = (float)(now % cycleTime[i]) / (float)cycleTime[i];
    float t = (sin(phase * TWO_PI - HALF_PI) + 1.0f) * 0.5f;

    uint32_t c1 = colorsA[i];
    uint32_t c2 = colorsB[i];

    uint8_t r = (uint8_t)(((c1 >> 16) & 255) + ((((c2 >> 16) & 255) - ((c1 >> 16) & 255)) * t));
    uint8_t g = (uint8_t)(((c1 >> 8)  & 255) + ((((c2 >> 8)  & 255) - ((c1 >> 8)  & 255)) * t));
    uint8_t b = (uint8_t)(( c1        & 255) + ((( c2        & 255) - ( c1        & 255)) * t));

    strip.setPixelColor(i,   r, g, b);     // 1–5
    strip.setPixelColor(i+5, r, g, b);     // 6–10 mirror
  }

  strip.show();
}

void loop() {
  handleSoundTrigger();
  handleMotor();
  handleLEDs();
}

. . . . . . .

©️ Copyright 2024 laura Muth

  • All project & material experiment images are my own & were photographed by me.
  • Other images are credited to the respective artists below.