El sensor de pulso y SpO₂ más usado, explicado en serio
Si alguna vez abriste un smartwatch o un anillo Oura, encontraste un primo cercano del MAX30102: un sensor óptico que ilumina la piel con LEDs rojo e infrarrojo y mide cuánto se refleja para calcular frecuencia cardíaca y saturación de oxígeno. Es el chip dominante en proyectos DIY de salud porque cuesta poco, habla I²C, y la librería de SparkFun lo abstrae casi por completo.
Este tutorial está inspirado en la guía de Components101 y reorganiza la información en tres bloques útiles: qué está pasando físicamente dentro del chip, cómo lo conectas con Arduino o ESP32, y cómo resolver el bug clásico del módulo barato que no aparece en el escaneo I²C. Si alguna vez compraste un MAX30102 y no respondía, ese último bloque te explica el por qué y la solución.

Qué hace el MAX30102 internamente
Dentro del chip de 14 pines (encapsulado OESIP) hay tres bloques:
- Dos LEDs: uno rojo a 660 nm y uno infrarrojo a 880 hasta 940 nm. La corriente de cada LED es programable (0 a 50 mA), lo que define la intensidad luminosa.
- Un fotodetector: una fotodiode de alta sensibilidad que mide la luz reflejada por la sangre debajo de la piel.
- Un ADC de 18 bits más FIFO de 32 muestras: digitaliza la luz reflejada y la guarda en buffer interno para que el microcontrolador no tenga que estar leyendo cada microsegundo.
Cómo se calcula la SpO₂. La hemoglobina oxigenada absorbe más infrarrojo que rojo; la desoxigenada al revés. El ratio (rojo absorbido sobre IR absorbido) está casi linealmente correlacionado con el porcentaje de saturación de oxígeno. El sensor mide ambos en paralelo y la librería corre el algoritmo de Maxim para devolverte el valor en porcentaje.
Cómo se calcula el BPM. El pulso cardíaco genera oscilaciones periódicas en el flujo sanguíneo (sístole vs diástole). El sensor detecta esos picos en la señal IR y mide el tiempo entre picos para calcular pulsaciones por minuto.
Especificaciones clave
| Parámetro | Valor |
|---|---|
| Comunicación | I²C, dirección 0x57 (fija) |
| Voltaje LEDs | 3.3 V (regulado en el módulo) |
| Voltaje núcleo | 1.8 V (regulado interno) |
| Voltaje módulo (Vin) | 3.3 V a 5 V |
| Corriente activa | ~600 µA |
| Corriente standby | 0.7 µA |
| Resolución ADC | 18 bits |
| Sample rate | 50 a 3200 muestras por segundo (configurable) |
| Sensor temperatura interno | ±1 °C, rango de menos 40 a más 85 °C |
El módulo breakout es diminuto, 1.67 cm de ancho por 1.24 cm de alto, así que entra en cualquier carcasa wearable que diseñes.

Pinout del módulo breakout
| Pin | Función |
|---|---|
| VIN | 3.3 a 5 V |
| SCL | Reloj I²C |
| SDA | Datos I²C |
| INT | Interrupción (opcional) |
| IRD | Control LED infrarrojo |
| RD | Control LED rojo |
| GND | Tierra |
Para uso básico solo necesitas VIN, GND, SDA y SCL.
Conexión con Arduino Uno
| MAX30102 | Arduino Uno |
|---|---|
| VIN | 5V (el módulo regula a 3.3V internamente) |
| GND | GND |
| SCL | A5 (Mega: pin 21) |
| SDA | A4 (Mega: pin 20) |
| INT | opcional, cualquier digital con attachInterrupt |
Con ESP32: SDA al GPIO 21, SCL al GPIO 22 (defaults).

⚠️ El bug del pull up de 1.8 V (debugging crítico)
Síntoma: subes el código, abres el monitor serial, y dice "MAX30102 not found. Check wiring!", pero el cableado está perfecto y el LED rojo del módulo a veces se enciende un instante al energizar.
Causa: algunos módulos breakout (especialmente clones baratos) tienen los resistores pull up de 4.7 kΩ de SDA y SCL conectados al carril interno de 1.8 V del MAX30102, no a los 3.3 V que usa el bus I²C del microcontrolador. Con SDA y SCL apenas en 1.8 V, ningún ESP32 ni Arduino los reconoce como nivel lógico alto, y el escaneo I²C falla.
En el esquemático del módulo se ve claro: el regulador U1 entrega 3.3 V y el regulador U2 entrega 1.8 V, y los tres resistores de 4.7K que actúan como pull up tienen que colgar del riel de 3.3 V, no del de 1.8 V.

Solución: abre el módulo bajo lupa, ubica los dos resistores SMD pegados al chip, que son los pull up. Corta con cutter las pistas que van desde esos resistores al riel de 1.8 V interno, y suelda un puente fino que los lleve al pin VCC del módulo (que tiene 3.3 V). Después del reruteo, el escaneo I²C detecta el 0x57 y todo arranca.
Si quieres evitar la cirugía: comprar un módulo "Adafruit MAX30102" o un "SparkFun MAX30101", que vienen cableados correctamente desde fábrica.
Librería más código mínimo
La librería de referencia es SparkFun MAX3010x Pulse and Proximity Sensor Library. Instálala desde el Library Manager (Sketch → Include Library → Manage Libraries → buscar MAX30105). Funciona con MAX30102, MAX30105 y MAX30101.
#include <Wire.h>
#include "MAX30105.h"
#include "spo2_algorithm.h"
MAX30105 particleSensor;
#define BUFFER_SIZE 50
uint16_t irBuffer[BUFFER_SIZE];
uint16_t redBuffer[BUFFER_SIZE];
int32_t spo2;
int8_t spo2Valid;
int32_t heartRate;
int8_t hrValid;
void setup() {
Serial.begin(115200);
Wire.begin();
if (!particleSensor.begin(Wire, I2C_SPEED_FAST)) {
Serial.println("MAX30102 no encontrado. Revisa el cableado!");
while (1);
}
Serial.println("Pon el dedo suavemente sobre el sensor...");
particleSensor.setup();
particleSensor.setPulseAmplitudeRed(0x1F);
particleSensor.setPulseAmplitudeIR(0x1F);
}
void loop() {
for (int i = 0; i < BUFFER_SIZE; i++) {
while (!particleSensor.available())
particleSensor.check();
redBuffer[i] = particleSensor.getRed();
irBuffer[i] = particleSensor.getIR();
particleSensor.nextSample();
}
maxim_heart_rate_and_oxygen_saturation(
irBuffer, BUFFER_SIZE, redBuffer,
&spo2, &spo2Valid, &heartRate, &hrValid);
Serial.print("SpO2: ");
Serial.print(spo2Valid ? String(spo2) : "Invalid");
Serial.print(" BPM: ");
Serial.println(hrValid ? String(heartRate) : "Invalid");
delay(1000);
}
Tip de calibración: si los valores son inestables, ajusta setPulseAmplitudeRed o IR. Valores típicos para un adulto con piel media son 0x1F (~6 mA). Pieles más oscuras pueden requerir 0x3F (~12 mA) para que el IR penetre suficiente.
MAX30102 vs MAX30100 vs MAX30101 vs MAX30105
| Spec | MAX30102 | MAX30100 | MAX30101 | MAX30105 |
|---|---|---|---|---|
| LEDs | Rojo más IR | Rojo más IR | Rojo más IR | Rojo, IR y Verde |
| ADC | 18 bits | 16 bits | 18 bits | 18 bits |
| FIFO | 32 | 16 | 32 | 32 |
| Sample max | 3200 sps | 1000 sps | 3200 sps | 3200 sps |
| Power activo | 600 µA | 1000 µA | 600 µA | 600 µA |
| Mejor para | Wearables de bajo consumo | Proyectos económicos | Performance alta | Detección de partículas, multi LED |
Veredicto pragmático: el MAX30102 es el mejor balance precio sobre rendimiento. Sólo necesitas el 30105 si vas a hacer detección de partículas (humo) o un detector de humo multibanda. El 30100 está descontinuado en muchos lugares, así que evítalo.
Variantes y mejoras
- Filtro pasabanda en el firmware. El BPM real está entre 40 y 200 lpm (0.66 a 3.3 Hz). Filtra la señal IR con un IIR de 2do orden centrado ahí y vas a tener detección de picos muchísimo más estable, especialmente con dedos fríos o movimiento.
- HRV (Heart Rate Variability). En vez de promediar BPM, guarda los intervalos R a R y calcula rMSSD, un indicador de estrés y recuperación muy citado en literatura wearable.
- Display OLED en el sitio. Reemplaza los
Serial.printpor una pantalla SSD1306 con BPM grande y un sparkline del pulso. Proyecto portátil sin laptop. - Subida a InfluxDB más Grafana. Manda BPM y SpO₂ cada segundo a una base de series temporales. Después puedes ver tu tendencia de descanso semanal en un dashboard local.
Personalización para Chile (MechatronicStore)
- Arduino Uno R3: base ideal para empezar; la librería SparkFun fue desarrollada y testeada principalmente sobre Uno.
- Placa ESP32 (USB tipo C): alternativa con WiFi si quieres publicar a un dashboard. Usa GPIO 21 y 22 para SDA y SCL.
- Pantalla OLED SSD1306 0.91": para mostrar BPM y SpO₂ en tiempo real sin laptop.
- Resistencia 4.7 kΩ: el valor exacto de pull up I²C, por si necesitas reponer los del módulo durante la reparación.
- Cables macho a hembra 10 cm: conexión sin soldar.
- Protoboard 830 puntos: prototipado.
Recursos
- Tutorial original: MAX30102 Sensor: Pinout, Arduino Code & Datasheet Guide
- Librería SparkFun MAX3010x: https://github.com/sparkfun/SparkFun_MAX3010x_Sensor_Library
- Datasheet MAX30102 (Analog Devices): https://www.analog.com/media/en/technical-documentation/data-sheets/MAX30102.pdf
- Algoritmo de SpO₂ (Maxim app note): AN6409
Versión chilena con componentes en stock local en MechatronicStore.








