Skip to content

9. Wearables

Research

describe what you see in this image

This week was very challenging for me. Electronics topics have been a little difficult to handle, but I am very excited about the idea of creating functional wearables and learning more and more about them.

Main challenges:

  • Trying out and testing different ways of creating circuits for wearables using a microcontroller.

  • Implementing actuators and testing them to achieve movement, sound, and visuals.

  • Creating a functional wearable.

Wearables

Wearables are smart electronic devices that are integrated directly into clothing or worn as accessories, such as watches or bracelets, to monitor health, collect data, or interact with other devices. These devices allow you to measure your heart rate, record your sleep quality, track your physical activity, and control functions such as music or calls through your clothing. They can have different functions, from aesthetic to functional for health and wellness, sports, connectivity, etc.

As we saw in this week's reading, there are three types of actuators that we can test, such as sound, visual, and motion, which we can work with for our wearables through sensors, motors, and other electronic components.

*Material from Lecture class

weekly assignment

Check out the weekly assignment here or login to your NuEval progress and evaluation page.

about your images..delete the tip!!
  1. Remember to credit/reference all your images to their authors. Open source helps us create change faster together, but we all deserve recognition for what we make, design, think, develop.

  2. remember to resize and optimize all your images. You will run out of space and the more data, the more servers, the more cooling systems and energy wasted :) make a choice at every image :)

This image is optimised in size with resolution 72 and passed through tinypng for final optimisation. Remove tips when you don't need them anymore!

get inspired!

Check out and research alumni pages to betetr understand how to document and get inspired

Add your fav alumni's pages as references

References & Inspiration

For this week's assignment, I decided to take inspiration and reference from systems and devices aimed at sports, from sensors that measure temperature, devices that emit light or measure your heart rate, accessories that accompany or help people who exercise and even make their routine more bearable, etc.

One of the practices that caught my attention was that of Marion Guillaud, with her super glove, where she connects a sensor and neopixels to control the lights through movement and achieve various animations.

Another practice that I would like to use as a reference for a wearable project is that of Ainhoa Cadarso, who, together with Ailin Sandlien, designed a bag made of biomaterials that lights up and reacts to its environment using different sensors. I find it quite interesting how biomaterials can also include electronic components, responding to an innovative, practical, and functional design.

Inspiration

One of the projects I took as a reference and inspiration was a wearable device and apparel able to understand the context of each exercise, create personalized workout regimens, and coach you as you exercise—based on your schedule, abilities, and end goal—to maximize the results of each exercise, using a reactive AI-based coaching app. I believe that technology is advancing faster and faster, and we must think carefully about how to use it to benefit the community.

Tools

Tools

  • Arduino UNO
  • Arduino IDE -[Tinkercad] (https://www.tinkercad.com/dashboard) -[Chat GPT] (https://chatgpt.com/)

Neopixels

For actuator 1, I started by using neopixels, a button, and a buzzer to see how they behaved and how I could add them to my project.

Library

  • Two images side-by-side

describe what you see in this image describe what you see in this image

Schematic

First test to make sure the Neopixels responded to the code. I wanted them to last 30 seconds and be able to be turned on with a button to make it easier for the current to pass through the Neopixels. I also wanted to see how the button behaved when held down.

I asked Chat GPT for a code for LEDs to turn on every 30 seconds and restart when the button is held down

#include <Adafruit_NeoPixel.h>

// ----------------------------
// CONFIGURACIÓN DE HARDWARE
// ----------------------------
#define PIN_PIXELS 1      // D7 en Xiao RP2040
#define NUM_PIXELS 3

#define PIN_BOTON 6       // D4 en Xiao RP2040

Adafruit_NeoPixel pixels(NUM_PIXELS, PIN_PIXELS, NEO_GRB + NEO_KHZ800);

// ----------------------------
// VARIABLES DEL CONTROL
// ----------------------------
bool running = false;
unsigned long startTime = 0;
int ledIndex = 0;

// Para detectar presión larga
unsigned long botonTiempoInicio = 0;
bool botonEnCurso = false;

void resetTimer() {
running = false;
ledIndex = 0;
pixels.clear();
pixels.show();
Serial.println("REINICIADO");
}

void setup() {
Serial.begin(115200);

pixels.begin();
pixels.clear();
pixels.show();

pinMode(PIN_BOTON, INPUT_PULLUP);
}

void loop() {

bool boton = (digitalRead(PIN_BOTON) == LOW);

// ------------------------------------
// DETECTAR INICIO DE PRESIÓN
// ------------------------------------
if (boton && !botonEnCurso) {
    botonEnCurso = true;
    botonTiempoInicio = millis();
}

// ------------------------------------
// DETECTAR FIN DE PRESIÓN
// ------------------------------------
if (!boton && botonEnCurso) {
    unsigned long duracion = millis() - botonTiempoInicio;

    // Toque corto (<600 ms)
    if (duracion < 600) {
    running = true;
    ledIndex = 0;
    pixels.clear();
    pixels.show();
    startTime = millis();
    Serial.println("INICIADO");
    }

    botonEnCurso = false;
}

// ------------------------------------
// PRESIÓN LARGA = REINICIAR
// ------------------------------------
if (botonEnCurso && (millis() - botonTiempoInicio > 2000)) {
    resetTimer();
    botonEnCurso = false;
    delay(200);
    return;
}

// ------------------------------------
// TEMPORIZADOR: ENCENDER LED CADA 30s
// ------------------------------------
if (running) {
    unsigned long elapsed = millis() - startTime;

    // 30000 ms = 30 segundos
    if (elapsed >= (unsigned long)((ledIndex + 1) * 30000)) {

    pixels.setPixelColor(ledIndex, pixels.Color(0, 0, 150));
    pixels.show();

    ledIndex++;

    // Si ya se encendieron todos → detener
    if (ledIndex >= NUM_PIXELS) {
        running = false;
        Serial.println("TERMINADO");
   }
    }
  }
}

Code adding a buzzer

#include <Adafruit_NeoPixel.h>

// Pines
#define PIN_BUTTON 4
#define PIN_BUZZER 7
#define PIN_NEOPIXEL 2
#define NUM_PIXELS 5

// Temporizador
unsigned long lastStepTime = 0;
bool timerRunning = false;
int currentLED = 0;

// NeoPixels
Adafruit_NeoPixel pixels(NUM_PIXELS, PIN_NEOPIXEL, NEO_GRB + NEO_KHZ800);

void setup() {
pinMode(PIN_BUTTON, INPUT_PULLUP);   // Botón con pull-up interna
pinMode(PIN_BUZZER, OUTPUT);

pixels.begin();
pixels.clear();
pixels.show();
}

void loop() {
// Leer botón (LOW = presionado)
bool pressed = (digitalRead(PIN_BUTTON) == LOW);

// Iniciar el temporizador con un solo toque
if (pressed && !timerRunning) {
    timerRunning = true;
    lastStepTime = millis();
    currentLED = 0;
    pixels.clear();
    pixels.show();
    delay(250);   // Debounce simple
}

if (timerRunning) {
    unsigned long now = millis();

    // Cada 30 segundos: encender LED + beep corto
    if (now - lastStepTime >= 30000) {
    lastStepTime = now;

    if (currentLED < NUM_PIXELS) {
        // Encender el LED actual
        pixels.setPixelColor(currentLED, pixels.Color(0, 150, 0));
        pixels.show();

        // Beep corto
        tone(PIN_BUZZER, 1000, 150);

        currentLED++;
    }

    // Si ya llegó al último LED
    if (currentLED == NUM_PIXELS) {
        // Beep largo
        tone(PIN_BUZZER, 800, 800);

        delay(900);

        // Reiniciar
        timerRunning = false;
        currentLED = 0;
        pixels.clear();
        pixels.show();
    }
    }
}
}

PIR sensor + LED + BUZZER

For actuator 2, I decided to experiment and use a PIR motion sensor, an LED, and a buzzer just to see what could be achieved.

Schematic

This actuator was difficult to achieve because I had to make several adjustments to the sensor to get it to recognize movement.

The code I used for this actuator was:

    int pir_pin = 2;
int led_pin = 3;
int buzzer_pin = 4;
void setup() 
{
pinMode(pir_pin, INPUT);
pinMode(led_pin, OUTPUT);
pinMode(buzzer_pin, OUTPUT);
Serial.begin(9600);
}
void loop() 
{
if(digitalRead(pir_pin) == HIGH)
{
    digitalWrite(led_pin, HIGH);
    digitalWrite(buzzer_pin, HIGH);
    Serial.println("¡Intrusos!");
}
else
{
    digitalWrite(led_pin, LOW);
    digitalWrite(buzzer_pin, LOW);
    Serial.println("Modo vigilante");
}
}

Process and workflow

For this wearable project, I wanted to make a headband that would act as a timer, designed for athletes who need a device that is not necessarily their cell phone. I thought of a headband, but during the process I realized that the user would not see the LEDs, so I decided to add sound so that it could be worn on either the head or the arm. This way, there would be two ways to signal when 30 seconds had passed, either with color or with sound.

The main idea is that once it is turned on with the button, the 30-second timer for an exercise starts until 4 LEDs light up, and once that series is finished, the band emits a long sound that alerts the user that the series is over and the count starts again.

#include <Adafruit_NeoPixel.h>
#include "hardware/watchdog.h"

#define PIN_NEOPIXEL 7
#define NUM_PIXELS 5

#define PIN_BUZZER 2
#define PIN_BUTTON 0

Adafruit_NeoPixel pixels(NUM_PIXELS, PIN_NEOPIXEL, NEO_GRB + NEO_KHZ800);

unsigned long lastTrigger = 0;
const unsigned long interval = 30000UL; // 30 segundos

const unsigned long longPressTime = 3000UL; // 3 segundos para reiniciar
bool buttonPressed = false;
unsigned long pressStart = 0;

void setup() {
pixels.begin();
pixels.clear();
pixels.show();

pinMode(PIN_BUZZER, OUTPUT);
pinMode(PIN_BUTTON, INPUT_PULLUP);

// Asegurar buzzer apagado
digitalWrite(PIN_BUZZER, LOW);
}

void loop() {
unsigned long currentMillis = millis();

// --- Lógica de activación cada 30 segundos ---
if (currentMillis - lastTrigger >= interval) {
    lastTrigger = currentMillis;

    // Encender neopixels azul
    for (int i = 0; i < NUM_PIXELS; i++) {
    pixels.setPixelColor(i, pixels.Color(0, 0, 150));
    }
    pixels.show();

    // bip corto
    tone(PIN_BUZZER, 2000, 150);
    delay(200);

    // apagar neopixels
    pixels.clear();
    pixels.show();
}

// --- Lectura del botón ---
bool buttonState = digitalRead(PIN_BUTTON) == LOW; // LOW = presionado

if (buttonState && !buttonPressed) {
    buttonPressed = true;
    pressStart = currentMillis;
}

// Si suelta el botón
if (!buttonState && buttonPressed) {
    buttonPressed = false;
}

// --- Detectar pulsación larga ---
if (buttonPressed && (currentMillis - pressStart >= longPressTime)) {
    // Reiniciar usando watchdog
    watchdog_enable(1, 1); // reset inmediato
    while (1); // esperar reinicio
}
}

How it works

  • Press the button once.

  • The timer starts.

  • Every 30 seconds one LED turns on and the buzzer emits a short beep (150 ms).

  • When the fifth LED turns on the buzzer emits a long beep (800 ms) and everything restarts automatically.

Since this code and connections did not work for me and I had Lilypad sewable components, I decided to use them, making a circuit with more connections, but it proved effective.

// Pines
const int leds[] = {D1, D2, D3, D4};
const int numLeds = 4;

const int buzzer = D7;
const int buttonPin = D0;

// Tiempos
unsigned long interval = 30000; // 30 segundos

void setup() {
// Configurar LEDs
for (int i = 0; i < numLeds; i++) {
    pinMode(leds[i], OUTPUT);
    digitalWrite(leds[i], LOW);
}

// Configurar buzzer
pinMode(buzzer, OUTPUT);

// Botón con pull-up interno
pinMode(buttonPin, INPUT_PULLUP);
}

void loop() {

// Esperar a que el botón se presione
if (digitalRead(buttonPin) == LOW) {

    delay(50); // Anti-rebote

    // *** CICLO DE 30 SEG POR LED ***
    for (int i = 0; i < numLeds; i++) {

    digitalWrite(leds[i], HIGH);  // Prende LED

    tone(buzzer, 2000, 150);      // Beep corto más fuerte (2 kHz)
    delay(150);

    delay(interval);              // Esperar 30 segundos
    }

    // *** BEEP FINAL LARGO ***
    tone(buzzer, 1800, 1500); // 1.5 segundos
    delay(1500);

    // Apagar todos los leds al terminar
    for (int i = 0; i < numLeds; i++) {
    digitalWrite(leds[i], LOW);
    }

    // Pequeña pausa antes de permitir reiniciar
    delay(500);
}
}

This schematic 1 was obtained by..

This tutorial 2 was created using..

footnote fabrication files

Fabrication files are a necessary element for evaluation. You can add the fabrication files at the bottom of the page and simply link them as a footnote. This was your work stays organised and files will be all together at the bottom of the page. Footnotes are created using [ ^ 1 ] (without spaces, and referenced as you see at the last chapter of this page) You can reference the fabrication files to multiple places on your page as you see for footnote nr. 2 also present in the Gallery.


Results

---

---

Fabrication files


  1. File: xxx 

  2. File: xxx