MAX30102 pulse oximeter

Maxim's MAX30102 heart-rate and blood-oxygen sensor on its breakout board.

A red and an infrared LED shine into a fingertip, and a photodiode measures how much light comes back. Aliases: pulse oximeter, heart rate sensor, SpO2 sensor, MAX30100 (its predecessor), MAX30105 (its sibling with a green LED).

Pins

Pin What it does
VIN Supply, 1.8 to 5.5 V; the board's regulators make the chip's 1.8 V and the LEDs' 3.3 V.
SCL, SDA The I2C bus, address 0x57. The board has the pull-ups.
INT Interrupt output, open drain: low while an enabled interrupt is set.
IRD, RD The IR and red LED drivers, brought out on the board. Leave them open.
GND Ground.

While it runs

The two sliders are the person: the heart rate, 30 to 220 beats a minute, and the blood oxygen, 70 to 100%. The F button puts a finger on the window or takes it off.

Reading it on an Arduino

With the SparkFun MAX3010x library, which Mokxi ships as MAX30105.h with its heartRate.h and spo2_algorithm.h:

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

void setup() {
  Serial.begin(9600);
  sensor.begin(Wire, I2C_SPEED_FAST);
  sensor.setup();                 // 6.4 mA, red, IR and the (missing) green slot
}

void loop() {
  long ir = sensor.getIR();       // about 100000 with a finger on it
  if (checkForBeat(ir)) Serial.println("beat");
}

What the model gets right

From the MAX30102 datasheet:

The registers: the part ID 0x15, the mode (heart rate, SpO2, or the multi-LED slots), the ADC range, sample rate and pulse width, the LED currents at 0.2 mA a step, and a reset that puts them all back.

The FIFO: 32 samples of three bytes a channel, with its read and write pointers, the overflow counter, averaging from 1 to 32 samples, and rollover on or off. The pulse width sets the resolution, 15 to 18 bits, left justified.

The interrupts: new sample and almost full, the die temperature, and power ready, on the open-drain INT pin.

The light: a fingertip sends back a fixed share of each LED's light, so the reading scales with the LED current and the ADC range the way it does on the chip, and the libraries' "finger present" level, about 100 000 counts of IR at their defaults, is where it should be. With no finger a few hundred counts come back.

What it does not model

The pulse is drawn, not recorded: a dip once a beat of 2% of the IR level (the perfusion index), with a quick fall and a slower recovery. The red dips by R times as much, from SpO2 = 110 - 25 R, the linear calibration most oximeter notes give; real oximeters are calibrated per design against blood samples. There is no noise, no motion, and no ambient light, the MAX30102's third slot reads 0 because it has no green LED, and any sample rate and pulse width combination runs, including the ones the datasheet rules out.

Common mistakes

Storing 18-bit samples in 16-bit variables: the Uno's examples do, to fit a hundred of each in its RAM, so turn the LED current down until the readings stay under 65536.

Reading too few samples for the SpO2 algorithm: it needs a few beats, four seconds at 25 samples a second.

See it in action

Pulse oximeter prints the heart rate and SpO2. Open it at /templates.