Introduction: Finger Pulse Oximeter Using MAX30100

A pulse oximeter is a device used to monitor both your heart rate and blood oxygen concentration. This device is especially important for people who need to monitor these parameters due to certain health conditions, such as asthma or congestive heart failure.

In this implementation of a pulse oximeter, we will be using the MAX30100 chip within a breakout board, integrated with Arduino Uno and an LCD keypad shield. The chip acts as an integrated pulse oximetry and heart-rate monitor sensor solution. It should be noted that the MAX30100 is not an FDA-approved medical device and we are doing this for a small-scale project for our Bioinstrumentation class.

Our overall goal is to make a finger cuff pulse oximeter that:

- modulates light from an IR LED and a red light LED

- uses MAX30100 and Arduino

- displays heart rate or oxygen saturation levels on an LCD screen

- allows the user to select which output to display by pressing buttons on the LCD

Step 1: Materials & Components

Things needed:

1) Arduino Uno x1

2) MAX30100 Breakout Board x1

3) A suitable length of Velcro

4) A laptop downloaded with Arduino

5) Jumper wires

6) Soldering Wires

7) Soldering tools

We were given a MAX30100 breakout board from ProtoCentral, which came ready with slots to insert the Velcro so that the device can be wrapped around the finger. We also had to solder the jumper wires to the pins of the breakout board in order to connect it to the Arduino.

Step 2: Requirements and Specifications

- Build a finger cuff that can modulate light from two different LED and pick up the transmitted light on a photodiode

- Use a MAX30100 chip integrated with the Arduino and a display.

- Provide a user interface that enables the selection between displaying heart rate and oxygen saturation.

Step 3: Summary of Operation

Pulse oximetry operates on the red and IR light absorption characteristics of oxygenated and deoxygenated hemoglobin. Blood oxygen concentration can be calculated from the ratio between the absorption red light and IR light by the hemoglobin. Heart rate is detected by the change of blood volume throughout the finger, that is then quantified by the amount of light that passes through the finger.

The MAX30100 chip integrates two LEDs: red and infrared (IR), a photodetector and low-noise signal processing to detect pulse oximetry and heart rate signals. The absorption data for both IR and red light is stored in a FIFO buffer up to 64 bytes. It provides two operating modes; the heart rate mode, and the heart rate and oxygen saturation mode. In the heart rate mode, only the IR LED is switched on, while in the dual mode both IR and red LEDs are switched on. It also has an integrated 60 Hz low-pass filter. While it can filter out power line noise, it still does not account for environmental noise and fluctuations.

From the LEDs, red and IR light is transmitted through the finger and the photodetector integrated within the chip senses the the light absorption of the two separate wavelengths. In this project, we used both the oximetry and heart rate detection operations with the MAX30100, so we can detect both heart rate and oxygen saturation at the same time.

Step 4: Block Diagram

Step 5: Integrating the MAX30100 to the Arduino

The MAX30100 is an I2C device, therefore through code it requires the Wire library to interface with the Arduino. Physically, the MAX30100 (in this case, the breakout board) is connected to the Arduino through special pins that are able to read data from the SCL and SDA lines, which are A4 and A5. The SCL and SDL lines provide the data signal and the clock signal. The ground and Vin lines are connected to the GND and 5V lines respectively.

The LCD Keypad Shield is connected to the Arduino by pins 4-8 so that we can provide a user-friendly display. We have also utilized two buttons on the LCD Keypad Shield, which are used to select between two modes: the heart rate monitor and the oxygen concentration monitor.

Step 6: Source Code

#include <Arduino.h>
#include <math.h>
#include <Wire.h>
#include "MAX30100.h"

LiquidCrystal lcd(8,9,4,5,6,7)

int mode = 0;

void setup() {
	lcd.print("Up for SaO2")
	lcd.println("Pulse oxymeter test!")

	pinMode(2, OUTPUT);

void loop() {
	pulseoxymeter_t result = pulseOxymeter->update();

	if ((analogRead(0)>130) && (analogRead(0)<160)) {
		lcd.print( "SaO2: " );
		mode = 1;

	}	else if ((analogRead(0)>130) && (analogRead(0)<160)) {
		lcd.print( "BPM: " );
		mode = 2;

	if (result.pulseDetected == true)
		if (mode == 1) {
			lcd.print( "SaO2: ");
			lcd.print( result.SaO2 );
			lcd.print( "%" );

		} else if (mode == 2) {
			lcd.print( "BPM: ");



	digitalWrite( 2, !digitalRead(2) );


Step 7: More on Code Implementation

The code that we have provided in this project is based on an open-source library by Raivinis Strogonovs, who had implemented his own version of the pulse oximeter with the MAX30100.

Here is the link to his library:

Step 8: Challenges

With our implementation of the MAX30100, we noticed that position and movement of the finger dramatically affect the registered readings. This may be caused by how the measurement of heart rate is greatly dependent on the volume of blood flowing through the finger, and the thickness of skin also comes into play here. If the fingers are moving around, this may cause nonuniform light levels while acquiring a reading.

People testing out our project should not move their fingers/hands around in order to acquire a stable reading. This project can be improved by placing the sensor within an actual finger cuff that can further reduce the effects of ambient light and also keep the finger in place, instead of just using a simple Velcro strip.