Back to Sensors & Actuators Series

Biomedical Sensor: MAX30102

July 21, 2025 Wasil Zafar 9 min read

MAX30102 deep dive — PPG sensing principle, I2C interfacing, heart rate and SpO2 algorithm, complete code, and real-world wearable health applications.

Contents

  1. Working Principle
  2. Electrical Characteristics
  3. Interfacing with MCU
  4. Calibration
  5. Code Example
  6. Real-World Applications
  7. Limitations

Working Principle

The MAX30102 is an integrated pulse oximetry and heart rate sensor that uses photoplethysmography (PPG). It shines red (660 nm) and infrared (880 nm) LEDs into the finger or wrist. Oxygenated haemoglobin absorbs more IR light, deoxygenated haemoglobin absorbs more red light. The ratio of absorption at both wavelengths yields SpO2 (blood oxygen saturation), while the pulsatile component reveals heart rate.

Analogy: Imagine shining a torch through your finger — you can see the red glow because blood absorbs some wavelengths more than others. The MAX30102 does this precisely with two specific colours to measure oxygen levels.

Electrical Characteristics

ParameterValue
Supply Voltage1.8 V (core), 3.3 V (LED)
LED Wavelengths660 nm (red), 880 nm (IR)
ADC Resolution18-bit
Sample Rate50 – 3200 Hz
InterfaceI2C at 0x57
LED Current (max)50 mA per LED

Code Example

/*
 * MAX30102 Heart Rate Reader — Arduino
 * Requires: SparkFun MAX3010x library
 * Wiring: I2C — SCL→A5, SDA→A4, VCC→3.3V, INT→Pin 2
 */
#include <Wire.h>
#include "MAX30105.h"
#include "heartRate.h"

MAX30105 sensor;
const byte RATE_SIZE = 4;
byte rates[RATE_SIZE];
byte rateSpot = 0;
long lastBeat = 0;
float beatsPerMinute;
int beatAvg;

void setup() {
    Serial.begin(115200);
    if (!sensor.begin(Wire, I2C_SPEED_FAST)) {
        Serial.println("MAX30102 not found!");
        while (1);
    }
    sensor.setup();
    sensor.setPulseAmplitudeRed(0x0A);  /* Low for proximity detect */
    sensor.setPulseAmplitudeIR(0x1F);   /* Higher for SpO2 */
    Serial.println("Place finger on sensor...");
}

void loop() {
    long irValue = sensor.getIR();

    if (irValue < 50000) {
        Serial.println("No finger detected");
        delay(100);
        return;
    }

    if (checkForBeat(irValue)) {
        long delta = millis() - lastBeat;
        lastBeat = millis();
        beatsPerMinute = 60.0 / (delta / 1000.0);

        if (beatsPerMinute > 40 && beatsPerMinute < 200) {
            rates[rateSpot++ % RATE_SIZE] = (byte)beatsPerMinute;
            beatAvg = 0;
            for (byte i = 0; i < RATE_SIZE; i++) beatAvg += rates[i];
            beatAvg /= RATE_SIZE;
        }
    }

    Serial.print("IR: "); Serial.print(irValue);
    Serial.print(" | BPM: "); Serial.print(beatsPerMinute, 0);
    Serial.print(" | Avg BPM: "); Serial.println(beatAvg);
}
Medical Disclaimer: The MAX30102 with hobbyist code is not a medical device. Do not use it for clinical diagnosis. Medical-grade pulse oximeters require FDA/CE certification, validated algorithms, and controlled LED drive currents.

Real-World Applications

Healthcare

Fitness Wearables

Smartwatches like the Apple Watch and Fitbit use PPG sensors similar to the MAX30102 to continuously monitor heart rate, detect irregular rhythms (AFib screening), and estimate SpO2 during sleep — driving the $70B wearable health market.

WearablesPPGHealth Monitoring

Limitations

  • Motion artefacts: Wrist movement corrupts PPG signal; advanced filtering (adaptive thresholds) is essential.
  • Skin tone variation: Darker skin absorbs more light, requiring higher LED current and careful calibration.
  • Ambient light: Direct sunlight can saturate the photodetector; use optical shielding.
  • Contact pressure: Too tight reduces blood flow; too loose lets ambient light in.