Arduino Pulse Oximeter (With Code)

Arduino Pulse Oximeter Project

Arduino Pulse Oximeter

If you are looking for something easy, simple and at the same time you want to impress everyone with your Arduino then pulse oximeter project is probably the best choice especially when you are a beginner in the world of Arduino.

In this project we are going to learn how to make a pulse oximeter with the ability to measure heart rate and blood oxygen. This post will cover the items required, step by step procedure and final code that needs to be uploaded on the Ardunio to make it all work.

So let’s start!

Items required

Arduino Uno
Arduino board r3
OLED 128x32 Display
Arduino OLED
Jumper Wires
connecting wires
breadboard for connection

How does the Pulse Oximeter works?

In this project we are going to measure the BPM or "Beats per minute" and SpO2 which is the Oxygen saturation level of an individual using the MAX 30102 sensor. For a normal person it is around 65-75 while in a state of rest whereas oxygen saturation level is more than 95%.

Now lets learn how to put everything together.

Steps to follow

1. First let’s make the circuit, make sure to follow the exact circuit diagram since the program is designed accordingly.

Pulse Oximeter arduino

2. Upload the Arduino code which is made for this project. You can find the code at the bottom of the post.

3. Bingo! you are all set to test your Pulse Oximeter with Arduino !


Here is a short video which can help you to get it right:

Arduino Code

/* This code works with MAX30102 + 128x32 OLED i2c + Buzzer and Arduino UNO

 * It's displays the Average BPM on the screen, with an animation and a buzzer sound

 * everytime a heart pulse is detected

 * It's a modified version of the HeartRate library example

 * Refer to for more details or SurtrTech YouTube channel


#include <Adafruit_GFX.h>        //OLED libraries

#include <Adafruit_SSD1306.h>

#include <Wire.h>

#include "MAX30105.h"           //MAX3010x library

#include "heartRate.h"          //Heart rate calculating algorithm

MAX30105 particleSensor;

const byte RATE_SIZE = 4; //Increase this for more averaging. 4 is good.

byte rates[RATE_SIZE]; //Array of heart rates

byte rateSpot = 0;

long lastBeat = 0; //Time at which the last beat occurred

float beatsPerMinute;

int beatAvg;

#define SCREEN_WIDTH 128 // OLED display width, in pixels

#define SCREEN_HEIGHT 32 // OLED display height, in pixels

#define OLED_RESET    -1 // Reset pin # (or -1 if sharing Arduino reset pin)

Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET); //Declaring the display name (display)

static const unsigned char PROGMEM logo2_bmp[] =

{ 0x03, 0xC0, 0xF0, 0x06, 0x71, 0x8C, 0x0C, 0x1B, 0x06, 0x18, 0x0E, 0x02, 0x10, 0x0C, 0x03, 0x10,              //Logo2 and Logo3 are two bmp pictures that display on the OLED if called

0x04, 0x01, 0x10, 0x04, 0x01, 0x10, 0x40, 0x01, 0x10, 0x40, 0x01, 0x10, 0xC0, 0x03, 0x08, 0x88,

0x02, 0x08, 0xB8, 0x04, 0xFF, 0x37, 0x08, 0x01, 0x30, 0x18, 0x01, 0x90, 0x30, 0x00, 0xC0, 0x60,

0x00, 0x60, 0xC0, 0x00, 0x31, 0x80, 0x00, 0x1B, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x04, 0x00,  };

static const unsigned char PROGMEM logo3_bmp[] =

{ 0x01, 0xF0, 0x0F, 0x80, 0x06, 0x1C, 0x38, 0x60, 0x18, 0x06, 0x60, 0x18, 0x10, 0x01, 0x80, 0x08,

0x20, 0x01, 0x80, 0x04, 0x40, 0x00, 0x00, 0x02, 0x40, 0x00, 0x00, 0x02, 0xC0, 0x00, 0x08, 0x03,

0x80, 0x00, 0x08, 0x01, 0x80, 0x00, 0x18, 0x01, 0x80, 0x00, 0x1C, 0x01, 0x80, 0x00, 0x14, 0x00,

0x80, 0x00, 0x14, 0x00, 0x80, 0x00, 0x14, 0x00, 0x40, 0x10, 0x12, 0x00, 0x40, 0x10, 0x12, 0x00,

0x7E, 0x1F, 0x23, 0xFE, 0x03, 0x31, 0xA0, 0x04, 0x01, 0xA0, 0xA0, 0x0C, 0x00, 0xA0, 0xA0, 0x08,

0x00, 0x60, 0xE0, 0x10, 0x00, 0x20, 0x60, 0x20, 0x06, 0x00, 0x40, 0x60, 0x03, 0x00, 0x40, 0xC0,

0x01, 0x80, 0x01, 0x80, 0x00, 0xC0, 0x03, 0x00, 0x00, 0x60, 0x06, 0x00, 0x00, 0x30, 0x0C, 0x00,

0x00, 0x08, 0x10, 0x00, 0x00, 0x06, 0x60, 0x00, 0x00, 0x03, 0xC0, 0x00, 0x00, 0x01, 0x80, 0x00  };

void setup() { 

  display.begin(SSD1306_SWITCHCAPVCC, 0x3C); //Start the OLED display



  // Initialize sensor

  particleSensor.begin(Wire, I2C_SPEED_FAST); //Use default I2C port, 400kHz speed

  particleSensor.setup(); //Configure sensor with default settings

  particleSensor.setPulseAmplitudeRed(0x0A); //Turn Red LED to low to indicate sensor is running


void loop() {

 long irValue = particleSensor.getIR();    //Reading the IR value it will permit us to know if there's a finger on the sensor or not

                                           //Also detecting a heartbeat

if(irValue > 7000){                                           //If a finger is detected

    display.clearDisplay();                                   //Clear the display

    display.drawBitmap(5, 5, logo2_bmp, 24, 21, WHITE);       //Draw the first bmp picture (little heart)

    display.setTextSize(2);                                   //Near it display the average BPM you can display the BPM if you want








  if (checkForBeat(irValue) == true)                        //If a heart beat is detected


    display.clearDisplay();                                //Clear the display

    display.drawBitmap(0, 0, logo3_bmp, 32, 32, WHITE);    //Draw the second picture (bigger heart)

    display.setTextSize(2);                                //And still displays the average BPM







    tone(3,1000);                                        //And tone the buzzer for a 100ms you can reduce it it will be better


    noTone(3);                                          //Deactivate the buzzer to have the effect of a "bip"

    //We sensed a beat!

    long delta = millis() - lastBeat;                   //Measure duration between two beats

    lastBeat = millis();

    beatsPerMinute = 60 / (delta / 1000.0);           //Calculating the BPM

    if (beatsPerMinute < 255 && beatsPerMinute > 20)               //To calculate the average we strore some values (4) then do some math to calculate the average


      rates[rateSpot++] = (byte)beatsPerMinute; //Store this reading in the array

      rateSpot %= RATE_SIZE; //Wrap variable

      //Take average of readings

      beatAvg = 0;

      for (byte x = 0 ; x < RATE_SIZE ; x++)

        beatAvg += rates[x];

      beatAvg /= RATE_SIZE;




  if (irValue < 7000){       //If no finger is detected it inform the user and put the average BPM to 0 or it will be stored for the next measure






     display.println("Please Place ");


     display.println("your finger "); 





Read Our Other Interesting Electronic Engineering Articles Here