Blog

MAX30102 Pulse Oximeter & Heart Rate Sensor – Complete Guide

Heart Rate & SpO2 Sensor

MAX30102 Pulse Oximeter & Heart Rate Sensor

Photoplethysmography (PPG) Sensor with I2C Interface

The MAX30102 measures your pulse using photoplethysmography (PPG): a red LED and an infrared LED shine into the skin, and a photodiode on the same side measures how much of that light is absorbed and reflected back. Because blood volume in the capillaries just under the skin pulses very slightly with every heartbeat, the amount of light reaching the photodiode fluctuates in time with your pulse - that fluctuating signal, once filtered, is your heart rate waveform. The two-wavelength design (red + infrared) is what enables the second measurement, SpO2 (blood oxygen saturation): oxygenated and deoxygenated hemoglobin absorb red and infrared light in different ratios, so comparing the two channels' absorption lets onboard-assisted algorithms estimate how oxygen-saturated your blood is. What makes the MAX30102 practical rather than merely a lab curiosity is that it integrates the LEDs, the photodetector, an 18-bit ADC, and ambient-light-rejection circuitry into a single chip talking over I2C - the noisy, low-level analog front-end problems that would otherwise require careful board design are handled entirely in silicon.

Heart Rate + SpO2
Measures
I2C
Interface
18-bit
ADC Resolution

Key features

Integrated Red + IR LEDs

Both wavelengths needed for SpO2 estimation are built into the same package.

Ambient Light Rejection

Onboard circuitry cancels out interference from room lighting automatically.

Ultra-Low Power Shutdown

Software-controlled power-save mode makes it practical for battery-powered wearables.

High Sample Rate

Samples up to 3200 times per second for a clean, detailed waveform capture.

I2C Digital Interface

A simple 2-wire connection - no analog frontend design required on your board.

On-Chip Temperature Sensor

Built-in temperature reading helps compensate readings for thermal drift.

Technical specifications

Supply Voltage 1.8V (logic) / 3.3V (LED supply)
Interface I2C (up to 400 kHz)
LED Wavelengths Red (660nm) + Infrared (880nm)
ADC Resolution 18-bit
Sample Rate Up to 3200 samples/sec
Default I2C Address 0x57
Measures Heart rate (BPM) + SpO2 (%)
Operating Current ~600µA typical (LED-dependent)
Package Breakout module with onboard 3.3V regulator

Pinout

PinFunction
VIN Power supply (module regulator accepts 3.3V–5V)
GND Ground
SCL I2C clock line
SDA I2C data line
INT Interrupt output - signals new data ready

Applications

Fitness trackers and wearable prototypes DIY pulse oximeter projects Patient-monitoring proof-of-concepts Sleep tracking projects Heart rate variability (HRV) research Sports training heart-rate belts

What's in the box

1x MAX30102 breakout module

Downloads

Datasheet (PDF) Arduino MAX30105 Library (SparkFun, MAX30102-compatible)
🔌
Pin Connections
1 Table
Pin Connections Table 1
BoardSensor PinConnection
MAX30102VCC/GND/SDA/SCL3.3V / GND / board SDA / board SCL
📟
MAX30102 Pulse Oximeter Heart Rate Sensor Module
7 Examples • C/C++ | Boards: Arduino Uno, Arduino Nano, Arduino Mega, ESP32, ESP8266, STM32, Raspberry Pi Pico
MAX30102 Pulse Oximeter Heart Rate Sensor Module - Arduino Uno
MAX30102 Pulse Oximeter Heart Rate Sensor Module - Arduino Nano
MAX30102 Pulse Oximeter Heart Rate Sensor Module - Arduino Mega
MAX30102 Pulse Oximeter Heart Rate Sensor Module - ESP32
MAX30102 Pulse Oximeter Heart Rate Sensor Module - ESP8266
MAX30102 Pulse Oximeter Heart Rate Sensor Module - STM32
MAX30102 Pulse Oximeter Heart Rate Sensor Module - Raspberry Pi Pico
📄 File: max30102_pulse_oximeter_heart_rate_sensor_module_-_arduino_uno.inoArduino Uno
915 characters
1//ekostra.com
2//electronics store in egypt
3//+201008896258
4
5// I2C wiring for Arduino Uno: A4=SDA, A5=SCL
6#include <Wire.h>
7#include "MAX30105.h" // SparkFun library - also covers MAX30100/30102 register-compatible reads
8
9MAX30105 particleSensor;
10
11void setup() {
12 Serial.begin(115200);
13 Wire.begin();
14 if (!particleSensor.begin(Wire, I2C_SPEED_STANDARD)) {
15 Serial.println("MAX3010x not found - check wiring!");
16 while (1) delay(10);
17 }
18 particleSensor.setup(); // default sensor settings (LED brightness, sample rate...)
19}
20
21void loop() {
22 long irValue = particleSensor.getIR();
23
24 if (irValue < 50000) {
25 Serial.println("No finger detected");
26 } else {
27 Serial.print("IR: "); Serial.print(irValue);
28 Serial.print(" Red: "); Serial.println(particleSensor.getRed());
29 // Real BPM/SpO2 needs the library's beat-detection / SpO2 algorithm on top of these raw readings.
30 }
31
32 delay(20);
33}
📄 File: max30102_pulse_oximeter_heart_rate_sensor_module_-_arduino_nano.inoArduino Nano
916 characters
1//ekostra.com
2//electronics store in egypt
3//+201008896258
4
5// I2C wiring for Arduino Nano: A4=SDA, A5=SCL
6#include <Wire.h>
7#include "MAX30105.h" // SparkFun library - also covers MAX30100/30102 register-compatible reads
8
9MAX30105 particleSensor;
10
11void setup() {
12 Serial.begin(115200);
13 Wire.begin();
14 if (!particleSensor.begin(Wire, I2C_SPEED_STANDARD)) {
15 Serial.println("MAX3010x not found - check wiring!");
16 while (1) delay(10);
17 }
18 particleSensor.setup(); // default sensor settings (LED brightness, sample rate...)
19}
20
21void loop() {
22 long irValue = particleSensor.getIR();
23
24 if (irValue < 50000) {
25 Serial.println("No finger detected");
26 } else {
27 Serial.print("IR: "); Serial.print(irValue);
28 Serial.print(" Red: "); Serial.println(particleSensor.getRed());
29 // Real BPM/SpO2 needs the library's beat-detection / SpO2 algorithm on top of these raw readings.
30 }
31
32 delay(20);
33}
📄 File: max30102_pulse_oximeter_heart_rate_sensor_module_-_arduino_mega.inoArduino Mega
918 characters
1//ekostra.com
2//electronics store in egypt
3//+201008896258
4
5// I2C wiring for Arduino Mega: D20=SDA, D21=SCL
6#include <Wire.h>
7#include "MAX30105.h" // SparkFun library - also covers MAX30100/30102 register-compatible reads
8
9MAX30105 particleSensor;
10
11void setup() {
12 Serial.begin(115200);
13 Wire.begin();
14 if (!particleSensor.begin(Wire, I2C_SPEED_STANDARD)) {
15 Serial.println("MAX3010x not found - check wiring!");
16 while (1) delay(10);
17 }
18 particleSensor.setup(); // default sensor settings (LED brightness, sample rate...)
19}
20
21void loop() {
22 long irValue = particleSensor.getIR();
23
24 if (irValue < 50000) {
25 Serial.println("No finger detected");
26 } else {
27 Serial.print("IR: "); Serial.print(irValue);
28 Serial.print(" Red: "); Serial.println(particleSensor.getRed());
29 // Real BPM/SpO2 needs the library's beat-detection / SpO2 algorithm on top of these raw readings.
30 }
31
32 delay(20);
33}
📄 File: max30102_pulse_oximeter_heart_rate_sensor_module_-_esp32.inoESP32
917 characters
1//ekostra.com
2//electronics store in egypt
3//+201008896258
4
5// I2C wiring for ESP32: GPIO21=SDA, GPIO22=SCL
6#include <Wire.h>
7#include "MAX30105.h" // SparkFun library - also covers MAX30100/30102 register-compatible reads
8
9MAX30105 particleSensor;
10
11void setup() {
12 Serial.begin(115200);
13 Wire.begin();
14 if (!particleSensor.begin(Wire, I2C_SPEED_STANDARD)) {
15 Serial.println("MAX3010x not found - check wiring!");
16 while (1) delay(10);
17 }
18 particleSensor.setup(); // default sensor settings (LED brightness, sample rate...)
19}
20
21void loop() {
22 long irValue = particleSensor.getIR();
23
24 if (irValue < 50000) {
25 Serial.println("No finger detected");
26 } else {
27 Serial.print("IR: "); Serial.print(irValue);
28 Serial.print(" Red: "); Serial.println(particleSensor.getRed());
29 // Real BPM/SpO2 needs the library's beat-detection / SpO2 algorithm on top of these raw readings.
30 }
31
32 delay(20);
33}
📄 File: max30102_pulse_oximeter_heart_rate_sensor_module_-_esp8266.inoESP8266
911 characters
1//ekostra.com
2//electronics store in egypt
3//+201008896258
4
5// I2C wiring for ESP8266: D2=SDA, D1=SCL
6#include <Wire.h>
7#include "MAX30105.h" // SparkFun library - also covers MAX30100/30102 register-compatible reads
8
9MAX30105 particleSensor;
10
11void setup() {
12 Serial.begin(115200);
13 Wire.begin();
14 if (!particleSensor.begin(Wire, I2C_SPEED_STANDARD)) {
15 Serial.println("MAX3010x not found - check wiring!");
16 while (1) delay(10);
17 }
18 particleSensor.setup(); // default sensor settings (LED brightness, sample rate...)
19}
20
21void loop() {
22 long irValue = particleSensor.getIR();
23
24 if (irValue < 50000) {
25 Serial.println("No finger detected");
26 } else {
27 Serial.print("IR: "); Serial.print(irValue);
28 Serial.print(" Red: "); Serial.println(particleSensor.getRed());
29 // Real BPM/SpO2 needs the library's beat-detection / SpO2 algorithm on top of these raw readings.
30 }
31
32 delay(20);
33}
📄 File: max30102_pulse_oximeter_heart_rate_sensor_module_-_stm32.inoSTM32
911 characters
1//ekostra.com
2//electronics store in egypt
3//+201008896258
4
5// I2C wiring for STM32: PB7=SDA, PB6=SCL
6#include <Wire.h>
7#include "MAX30105.h" // SparkFun library - also covers MAX30100/30102 register-compatible reads
8
9MAX30105 particleSensor;
10
11void setup() {
12 Serial.begin(115200);
13 Wire.begin();
14 if (!particleSensor.begin(Wire, I2C_SPEED_STANDARD)) {
15 Serial.println("MAX3010x not found - check wiring!");
16 while (1) delay(10);
17 }
18 particleSensor.setup(); // default sensor settings (LED brightness, sample rate...)
19}
20
21void loop() {
22 long irValue = particleSensor.getIR();
23
24 if (irValue < 50000) {
25 Serial.println("No finger detected");
26 } else {
27 Serial.print("IR: "); Serial.print(irValue);
28 Serial.print(" Red: "); Serial.println(particleSensor.getRed());
29 // Real BPM/SpO2 needs the library's beat-detection / SpO2 algorithm on top of these raw readings.
30 }
31
32 delay(20);
33}
📄 File: max30102_pulse_oximeter_heart_rate_sensor_module_-_raspberry_pi_pico.inoRaspberry Pi Pico
927 characters
1//ekostra.com
2//electronics store in egypt
3//+201008896258
4
5// I2C wiring for Raspberry Pi Pico: GPIO4=SDA, GPIO5=SCL
6#include <Wire.h>
7#include "MAX30105.h" // SparkFun library - also covers MAX30100/30102 register-compatible reads
8
9MAX30105 particleSensor;
10
11void setup() {
12 Serial.begin(115200);
13 Wire.begin();
14 if (!particleSensor.begin(Wire, I2C_SPEED_STANDARD)) {
15 Serial.println("MAX3010x not found - check wiring!");
16 while (1) delay(10);
17 }
18 particleSensor.setup(); // default sensor settings (LED brightness, sample rate...)
19}
20
21void loop() {
22 long irValue = particleSensor.getIR();
23
24 if (irValue < 50000) {
25 Serial.println("No finger detected");
26 } else {
27 Serial.print("IR: "); Serial.print(irValue);
28 Serial.print(" Red: "); Serial.println(particleSensor.getRed());
29 // Real BPM/SpO2 needs the library's beat-detection / SpO2 algorithm on top of these raw readings.
30 }
31
32 delay(20);
33}
I2C optical heart-rate/SpO2 sensor.
PPG readings are very sensitive to motion - the biggest source of noisy or unstable readings is not the sensor itself but the finger moving, pressing too hard, or making poor consistent contact, so keep the finger still with light, even contact rather than pressing down. Readings also take a few seconds to settle after placement as the algorithm's internal averaging window fills up, so ignore the first several samples rather than trusting an instant reading. Important: this is a hobbyist/educational sensor, not a calibrated medical device - treat its heart-rate and SpO2 output as approximate and never as a substitute for certified medical equipment.