Documentation

MAX30102 Pre-Soldered Heart Rate & Pulse Oximeter Sensor Module | ShillehTek Product Manual
Documentation / MAX30102 Pre-Soldered Heart Rate & Pulse Oximeter Sensor Module | ShillehTek Product Manual

MAX30102 Pre-Soldered Heart Rate & Pulse Oximeter Sensor Module | ShillehTek Product Manual

Raspberry Pi

Overview

The MAX30102 is an integrated pulse oximetry and heart rate sensor module that communicates over I2C. It contains red and infrared LEDs along with a photodetector to measure blood oxygen saturation (SpO2) and heart rate through your fingertip. The module runs on 1.8V-5V and works with Arduino, Raspberry Pi, ESP32, and Pico — making it a go-to choice for wearable health monitors, fitness trackers, and biomedical prototyping projects.

This pre-soldered breakout board includes onboard voltage regulators and pull-up resistors, so you can connect it directly to your microcontroller’s I2C bus with just four wires. The MAX30102 uses an 18-bit ADC for high-resolution readings and draws under 600 uA during active measurement, dropping to just 0.7 uA in standby mode.

At a Glance

Operating Voltage
1.8V - 5V
Interface
I2C
I2C Address
0x57
ADC Resolution
18-bit
Active Current
< 600 uA
Pins
VIN, GND, SCL, SDA, INT, IRD, RD

Specifications

Parameter Value
Operating Voltage (Module) 1.8V - 5V (onboard regulators)
IC Supply Voltage 1.8V
LED Supply Voltage 3.3V
Active Current < 600 uA
Standby Current 0.7 uA
Red LED Wavelength 660 nm
IR LED Wavelength 880 nm
ADC Resolution 18-bit
Sample Rate 50 - 3200 samples/sec
Communication I2C (address 0x57)
I2C Speed Up to 400 kHz
Operating Temperature -40 to +85 C
Dimensions (Module) 18 x 13 mm

Pinout Diagram

MAX30102 pulse oximeter module pinout diagram showing GND, SCL, SDA, VIN pins on bottom row and INT, IRD, RD, GND pins on top row

The MAX30102 module has 8 pins across two rows. Bottom row (pins 1-4): GND, SCL, SDA, VIN — these are the four pins you connect to your microcontroller. Top row (pins 5-8): INT (interrupt output, active-low, optional), IRD (IR LED cathode driver), RD (Red LED cathode driver), GND. The IRD and RD pins are used internally by the module’s LED drivers — you do not need to connect them for normal operation.

Wiring Guide

Arduino Wiring

The MAX30102 module has onboard voltage regulators, so it can be powered from the Arduino 5V or 3.3V pin. Connect it to the Arduino’s hardware I2C pins (A4/A5 on the Uno). The INT pin is optional but useful for interrupt-driven reading.

MAX30102 Pin Arduino Pin
VIN 3.3V or 5V
GND GND
SCL A5 (SCL)
SDA A4 (SDA)
INT Digital Pin 2 (optional)
Tip: The MAX30102 module includes onboard 4.7k pull-up resistors on the I2C lines. If you have other I2C devices on the same bus that also have pull-ups, the combined resistance may be too low. In that case, remove the extra pull-ups from one of the devices.

ESP32 Wiring

The ESP32 uses 3.3V I2C logic, which is compatible with the MAX30102 module. The default I2C pins on the ESP32 are GPIO 21 (SDA) and GPIO 22 (SCL). Power the module from the ESP32’s 3.3V pin.

MAX30102 Pin ESP32 Pin
VIN 3.3V
GND GND
SCL GPIO 22
SDA GPIO 21
INT GPIO 19 (optional)
Tip: The ESP32 operates at 3.3V I2C levels, which matches the MAX30102 perfectly. No level shifting or voltage dividers are needed — just connect directly.

Raspberry Pi Wiring

The Raspberry Pi has dedicated I2C pins on GPIO 2 (SDA) and GPIO 3 (SCL). The MAX30102 module can be powered from the Pi’s 3.3V pin. Make sure I2C is enabled in raspi-config before using the sensor.

MAX30102 Pin Raspberry Pi Pin
VIN Pin 1 (3.3V)
GND Pin 6 (GND)
SCL Pin 5 (GPIO 3 / SCL)
SDA Pin 3 (GPIO 2 / SDA)
INT Pin 7 (GPIO 4) (optional)
Note: You must enable I2C on your Raspberry Pi before the sensor will work. Run sudo raspi-config, go to Interface Options, and enable I2C. Then reboot. You can verify the sensor is detected by running sudo i2cdetect -y 1 — you should see address 0x57.

Raspberry Pi Pico Wiring

The Pico has two I2C buses. We’ll use I2C bus 0 on GP0 (SDA) and GP1 (SCL). The MAX30102 module can be powered from the Pico’s 3V3 pin.

MAX30102 Pin Pico Pin
VIN 3V3 (Pin 36)
GND GND
SCL GP1 (Pin 2)
SDA GP0 (Pin 1)
INT GP2 (Pin 4) (optional)
Tip: The Pico runs at 3.3V I2C, which is fully compatible with the MAX30102. No voltage dividers or level shifters needed. You can verify the sensor is connected by running an I2C scan in MicroPython.

Code Examples

Arduino

max30102_arduino.ino
// MAX30102 Heart Rate Sensor - Arduino Example
// Uses the SparkFun MAX3010x library
// Install: Arduino Library Manager -> search "SparkFun MAX3010x"
// I2C Pins: A4 (SDA), A5 (SCL)

#include <Wire.h>
#include "MAX30105.h"
#include "heartRate.h"

MAX30105 particleSensor;

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

void setup() {
  Serial.begin(9600);
  Serial.println("MAX30102 Heart Rate Sensor");

  // Initialize sensor
  if (!particleSensor.begin(Wire, I2C_SPEED_FAST)) {
    Serial.println("MAX30102 not found. Check wiring.");
    while (1);
  }

  Serial.println("Place your finger on the sensor.");
  particleSensor.setup();
  particleSensor.setPulseAmplitudeRed(0x0A);
  particleSensor.setPulseAmplitudeGreen(0);
}

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

  if (checkForBeat(irValue) == true) {
    long delta = millis() - lastBeat;
    lastBeat = millis();

    beatsPerMinute = 60 / (delta / 1000.0);

    if (beatsPerMinute < 255 && beatsPerMinute > 20) {
      rates[rateSpot++] = (byte)beatsPerMinute;
      rateSpot %= RATE_SIZE;

      // Calculate average BPM
      beatAvg = 0;
      for (byte x = 0; x < RATE_SIZE; x++)
        beatAvg += rates[x];
      beatAvg /= RATE_SIZE;
    }
  }

  Serial.print("IR=");
  Serial.print(irValue);
  Serial.print(", BPM=");
  Serial.print(beatsPerMinute);
  Serial.print(", Avg BPM=");
  Serial.println(beatAvg);

  if (irValue < 50000)
    Serial.println("No finger detected");
}

Raspberry Pi (Python)

max30102_rpi.py
#!/usr/bin/env python3
# MAX30102 Heart Rate Sensor - Raspberry Pi Example
# Install: pip3 install max30102 smbus2
# I2C Pins: GPIO 2 (SDA), GPIO 3 (SCL)
# Enable I2C first: sudo raspi-config -> Interface Options -> I2C

from max30102 import MAX30102
import time

# Initialize the sensor on I2C bus 1
sensor = MAX30102(bus=1)

# Check if sensor is connected
if not sensor.check():
    print("MAX30102 not found. Check wiring.")
    exit(1)

print("MAX30102 Heart Rate Sensor")
print("Place your finger on the sensor...")
print("Press Ctrl+C to stop")

try:
    while True:
        # Read a batch of samples from the sensor
        red, ir = sensor.read_sequential()

        if len(ir) > 0:
            # Calculate average IR value (used for finger detection)
            avg_ir = sum(ir) / len(ir)

            if avg_ir < 50000:
                print("No finger detected")
            else:
                print("IR: {:.0f}, Red: {:.0f}".format(
                    sum(ir) / len(ir),
                    sum(red) / len(red)
                ))

        time.sleep(0.1)

except KeyboardInterrupt:
    print("\nMeasurement stopped by user")
finally:
    sensor.shutdown()

Raspberry Pi Pico (MicroPython)

max30102_pico.py
# MAX30102 Heart Rate Sensor - Pico MicroPython Example
# Install library: import mip; mip.install("github:n-undertaker/micropython-max30102")
# I2C Pins: GP0 (SDA), GP1 (SCL)

from machine import Pin, I2C, SoftI2C
from max30102 import MAX30102
import time

# Initialize I2C bus
i2c = SoftI2C(sda=Pin(0), scl=Pin(1), freq=400000)

# Scan for devices to verify connection
devices = i2c.scan()
print("I2C devices found:", [hex(d) for d in devices])

# Initialize the MAX30102 sensor
sensor = MAX30102(i2c=i2c)

# Check sensor is responding
if sensor.i2c_address not in devices:
    print("MAX30102 not found. Check wiring.")
    raise SystemExit

# Configure the sensor
sensor.setup_sensor()

print("MAX30102 Heart Rate Sensor")
print("Place your finger on the sensor...")

while True:
    # Check if new data is available
    sensor.check()

    if sensor.available():
        # Read red and IR values
        red = sensor.pop_red_from_storage()
        ir = sensor.pop_ir_from_storage()

        if ir < 50000:
            print("No finger detected")
        else:
            print("IR: {}, Red: {}".format(ir, red))

    time.sleep_ms(10)

ESP32 (MicroPython)

max30102_esp32.py
# MAX30102 Heart Rate Sensor - ESP32 MicroPython Example
# Install library: import mip; mip.install("github:n-undertaker/micropython-max30102")
# I2C Pins: GPIO 21 (SDA), GPIO 22 (SCL)

from machine import Pin, SoftI2C
from max30102 import MAX30102
import time

# Initialize I2C bus (ESP32 default I2C pins)
i2c = SoftI2C(sda=Pin(21), scl=Pin(22), freq=400000)

# Scan for devices
devices = i2c.scan()
print("I2C devices found:", [hex(d) for d in devices])

# Initialize the MAX30102 sensor
sensor = MAX30102(i2c=i2c)

if sensor.i2c_address not in devices:
    print("MAX30102 not found. Check wiring.")
    raise SystemExit

# Configure the sensor
sensor.setup_sensor()

print("MAX30102 Heart Rate Sensor")
print("Place your finger on the sensor...")

while True:
    sensor.check()

    if sensor.available():
        red = sensor.pop_red_from_storage()
        ir = sensor.pop_ir_from_storage()

        if ir < 50000:
            print("No finger detected")
        else:
            print("IR: {}, Red: {}".format(ir, red))

    time.sleep_ms(10)

Frequently Asked Questions

How do I wire the MAX30102 to my Arduino?
Connect VIN to 3.3V or 5V, GND to GND, SCL to A5, and SDA to A4 on the Arduino Uno. The module has onboard voltage regulators, so it works at either voltage. The INT pin is optional — connect it to digital pin 2 if you want interrupt-driven readings.
How accurate is the MAX30102 for measuring heart rate and SpO2?
The MAX30102 provides reasonable heart rate and SpO2 readings for hobby and prototyping purposes. However, it is NOT a medical device and should not be used for clinical diagnosis. Accuracy depends on finger placement, ambient light, skin tone, and how still you hold your finger on the sensor. For best results, press gently and stay still during measurement.
The sensor doesn’t show up on I2C scan — what’s wrong?
First check your wiring — make sure SDA goes to SDA and SCL goes to SCL (don’t cross them). Verify you’re powering the module with 3.3V or 5V. On Raspberry Pi, make sure I2C is enabled in raspi-config. Some breakout boards have a hardware issue where the onboard I2C pull-up resistors are connected to the 1.8V rail instead of 3.3V — if this is the case, you may need to add external 4.7k pull-up resistors from SDA and SCL to 3.3V.
Do I need a voltage divider for the MAX30102?
No. Unlike sensors that output 5V signals, the MAX30102 module uses I2C communication at logic levels set by the pull-up resistors. The module’s onboard regulators handle voltage conversion internally. It works safely with 3.3V platforms (ESP32, Raspberry Pi, Pico) and 5V platforms (Arduino) without any level shifting.
What library should I use to read the MAX30102?
Arduino: Install the "SparkFun MAX3010x Pulse and Proximity Sensor Library" from the Library Manager — it includes heart rate detection and example sketches. Python (Raspberry Pi): Install the max30102 package with pip. MicroPython (Pico/ESP32): Use the micropython-max30102 library, installable via mip.
Can I use the MAX30102 as a proximity sensor?
Yes. The IR LED and photodetector can detect nearby objects based on reflected infrared light. The SparkFun Arduino library includes a proximity sensing example. This makes the MAX30102 useful for gesture detection and presence sensing in addition to heart rate monitoring.
Why does the sensor read zero or very low values when I put my finger on it?
The most common cause is pressing too hard. Heavy pressure restricts blood flow and reduces the signal. Place your finger gently on the sensor with light, steady pressure. Also make sure you’re using the flat pad of your fingertip (not the side or tip) and keep your hand still during measurement. Ambient light can also interfere — try shielding the sensor from direct light.

Related Tutorials