Proyecto de Hardware · 2026
Un amiguito tipo tamagotchi que mide tu pulso y reacciona a cómo te sientes.
01
Lumina mide tu ritmo cardíaco y te dice, con expresiones animadas y sonidos, si estás tranquilo o si necesitas respirar profundo.
Parte oxímetro, parte tamagotchi. :B
Lumina es una maquina de estados y es en base a tu pulso, y esta basado en Healthline.com
Fig. 01 — Vista frontal del dispositivo Lumina terminado
Todos los componentes fueron elegidos pensando en tamaño mínimo y precio razonable. El costo total del proyecto ronda los $8–10 USD.
| Componente | Función | Cant. | Precio |
|---|---|---|---|
| ESP32 | Microcontrolador principal, WiFi/BT integrado, ESP32 generico | 1 | $9.56 |
| OLED 0.96" SSD1306 | Pantalla que muestra la cara animada de Lumina y los BPM | 1 | $5.36 |
| MAX30102 (GY-MAX30102) | Sensor de pulso cardíaco por luz infrarroja | 1 | $3.69 |
| Buzzer Pasivo 3.8kHz | Feedback sonoro — pitido con cada latido detectado | 1 | $3.46 |
| Push Button | Interacción del usuario ( reset) | 20 | $9.56 |
| PCB Custom | PCB diseñada a medida para todo el sistema | 1 | ~$1.00 |
| TOTAL ESTIMADO | ~$31.63 | ||
El ESP32-C3 Super Mini fue elegido por su tamaño ultra compacto y porque corre el mismo código Arduino que cualquier ESP32 estándar. El bus I2C permite conectar la pantalla y el sensor en solo 2 pines de datos, dejando el resto libre.
| Componente | Voltaje Operativo | Fuente | Notas |
|---|---|---|---|
| ESP32 | 3.3V / 5V | USB-C / batería LiPo | Regulador interno a 3.3V |
| OLED SSD1306 | 3.3V | Pin 3V3 del ESP32 | No conectar a 5V — puede dañar el panel |
| MAX30102 | 3.3V | Pin 3V3 del ESP32 | I2C a 3.3V, velocidad Fast (400kHz) |
| Buzzer Pasivo | 3.3V | GPIO D5 | Controlado por PWM (función tone()) |
ensamblaje
Todo el sistema comparte la alimentación de 3.3V del ESP32. El bus I²C (SDA/SCL) conecta en paralelo la pantalla OLED y el sensor de pulso — sin conflicto porque tienen direcciones I²C distintas (0x3C y 0x57).
Cableado y componentes del sistema
Dispositivo ensamblado, vista lateral
firmware
El firmware corre en Arduino (framework ESP32). El loop principal lee el sensor, aplica un filtro de plausibilidad, promedia con un búfer circular de 6 muestras y despacha el estado emocional — todo sin usar delay(), para que la pantalla nunca se congele.
Loop principal — no bloqueante void loop() { long irValue = particleSensor.getIR(); Sin dedo → modo standby if (irValue < 50000) { estadoActual = DESCONECTADO; beatAvg = 0; } else { if (checkForBeat(irValue) == true) { long delta = millis() - lastBeat; lastBeat = millis(); beatsPerMinute = 60 / (delta / 1000.0); Filtro de plausibilidad: solo valores humanos reales if (beatsPerMinute >= 45 && beatsPerMinute <= 145) { rates[rateSpot++] = (byte)beatsPerMinute; rateSpot %= RATE_SIZE; // Buffer circular long total = 0; for (byte x = 0; x < RATE_SIZE; x++) total += rates[x]; beatAvg = total / RATE_SIZE; // Promedio suavizado Activar buzzer — tono según estado emocional buzzerActivo = true; tiempoBuzzerEncendido = millis(); if (beatAvg > 100) { tone(BUZZER_PIN, 1800); // Agudo: alerta } else { tone(BUZZER_PIN, 1200); // Normal: calmo } } } Clasificar estado emocional estadoActual = (beatAvg == 0) ? DESCONECTADO : (beatAvg > 100) ? AGITADO : CALMO; } Apagar buzzer automáticamente a los 40ms if (buzzerActivo && (millis() - tiempoBuzzerEncendido > 40)) { noTone(BUZZER_PIN); buzzerActivo = false; } actualizarPantalla(); // Siempre re-dibuja }
void actualizarPantalla() { display.clearDisplay(); // BPM en tamaño grande (zona inferior) display.setTextSize(2); display.setCursor(0, 48); display.print("BPM:"); switch (estadoActual) { case CALMO: display.println("Lumina: Calmado"); // Ojos: ^ ^ alternando con o o cada 500ms if (alternarAnimacion) { display.print("^"); display.print("^"); } else { display.print("o"); display.print("o"); } break; case AGITADO: display.println("!Respira profundo!"); // Ojos bien abiertos, boca tensa display.print("O"); display.print("O"); break; case DESCONECTADO: display.println("Modo Standby"); // Ojos dormidos: u u o guiones break; } display.display(); // Flush al panel físico }
diseño PCB
La PCB fue diseñada para que todo el sistema quepa en un factor de forma de llavero. El resultado es una placa compacta y ordenada :B
Layout de la PCB, vista superior
Render 3D de la PCB
PCB lista para ensamblaje
┌─────────────────────────────────────────┐
│ ESP32-C3 SUPER MINI │
│ │
│ 3V3 ──┬── VIN[MAX30102] │
│ └── 3V3[OLED] │
│ │
│ GND ──┬── GND[MAX30102] │
│ ├── GND[OLED] │
│ └── GND[BUZZER] │
│ │
│ G21 ──┬── SCL[MAX30102] ──── I2C BUS │
│ └── SCK[OLED] │
│ │
│ G22 ──┬── SDA[MAX30102] ──── I2C BUS │
│ └── SDA[OLED] │
│ │
│ D5 ──── S[BUZZER] │
└─────────────────────────────────────────┘
D: lo que salió mal
Por mas sencillo que sea hay dificultades aveces
delay() para el buzzer bloqueaba el loop entero, haciendo que la OLED dejara de actualizarse. Reescribí el control del buzzer usando millis()
fin del documento yeyyy
De un oxímetro roto en un cajón, a un llavero con personalidad.
Lumina sabe cuándo estás bien y cuándo necesitas respirar.
— Hecho a mano, con mucho sueño y cariño.