🩺Oximeter Using Arduino – a DIY Health Monitoring Project
by rutujavaidya72 in Circuits > Arduino
44 Views, 1 Favorites, 0 Comments
🩺Oximeter Using Arduino – a DIY Health Monitoring Project

This is my first Instructable project . I Build a compact and educational pulse oximeter that displays heart rate (BPM) and blood oxygen level (SpO₂). The project uses the popular MAX30100 sensor with an Arduino Uno—ideal for makers, students, and health-tech enthusiasts.
why bpm is important ?
Health Monitoring
- Helps detect abnormal heart rhythms (arrhythmias).
- Identifies stress, fatigue, or illness early.
- Monitors heart conditions like bradycardia (slow) or tachycardia (fast).
Oxygen is essential for all body functions.
Low SpOâ‚‚ levels mean your organs and tissues aren't getting enough oxygen, which can be dangerous for heart when sufficient oxygen cant reach to heart its veins and arteries may get block and it leads to heart attack , heart failure too.
Supplies
.jpeg)
️ Supplies for Pulse Oximeter Project
I used this Components
- Arduino Uno
- The main microcontroller board to control everything
- A microcontroller (a small computer that runs your code)
- Input/output pins (to connect sensors, LEDs, motors, etc.)
- A USB port (to upload code from your computer)
- Power supply pins (for external components)
- MAX30100 or MAX30102 Pulse Oximeter & Heart Rate Sensor Module
- Measures your blood oxygen saturation (SpO2) and heart rate.
- LEDs (Red & IR) – Light passes through the skin.
- Photodetector – Detects light absorption changes, which vary with blood flow.
- 16x2 I2C LCD Display Module
- To display the readings easily with just 4 wires (SDA, SCL, VCC, GND).
- Jumper wires (male to male)
- For connecting sensor, LCD, and Arduino.
- Breadboard (optional)
- For easy prototyping without soldering.
- Power supply (USB cable or 9V battery + adapter)
- To power the Arduino.
🔌 Circuit Connections

1. MAX30100 Pulse Oximeter Sensor to Arduino Uno
- VCC: Connect to 3.3V on the Arduino. Note: The MAX30100 operates at 3.3V, not 5V.
- GND: Connect to GND on the Arduino.
- SDA: Connect to A4 on the Arduino.
- SCL: Connect to A5 on the Arduino.
- INT: This is an interrupt pin; it's optional for basic readings. If used, connect to D2 on the Arduino.
16x2 I2C LCD Display to Arduino Uno
- VCC: Connect to 5V on the Arduino.
- GND: Connect to GND on the Arduino.
- SDA: Connect to A4 on the Arduino.
- SCL: Connect to A5 on the Arduino.
- ARDUINO CODE
// Scientist BENIELS LAB
/* CREATED BY: HOW TO ELECTRONICS | MODIFIED BY: SCIENTIST BENIELS LAB */
#include <LiquidCrystal_I2C.h>
#include <Wire.h>
#include "MAX30100_PulseOximeter.h"
#define REPORTING_PERIOD_MS 1000
LiquidCrystal_I2C lcd(0x27, 16, 2);
// Custom characters for smile, mod, sad
byte smile[] = {
B00000,
B00000,
B01010,
B00000,
B10001,
B01110,
B00000,
B00000
};
byte mod[] = {
B00000,
B00000,
B01010,
B00000,
B11111,
B00000,
B00000,
B00000
};
byte sad[] = {
B00000,
B00000,
B01010,
B00000,
B01110,
B10001,
B00000,
B00000
};
PulseOximeter pox;
uint32_t tsLastReport = 0;
void onBeatDetected() {
Serial.println("Beat detected!");
}
void setup() {
Serial.begin(115200);
lcd.init(); // LCD initialization
lcd.backlight(); // Backlight on
lcd.createChar(1, smile);
lcd.createChar(2, mod);
lcd.createChar(3, sad);
// Display initial welcome text
lcd.setCursor(0, 0);
lcd.print("Welcome to");
lcd.setCursor(0, 1);
lcd.print("Pulse Oximeter");
delay(2000); // Display for 2 seconds
// Show instructions or information about the system
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Please wait...");
lcd.setCursor(0, 1);
lcd.print("Initializing...");
delay(2000); // Display for 2 seconds
if (!pox.begin()) {
Serial.println("FAILED to initialize!");
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Initialization");
lcd.setCursor(0, 1);
lcd.print("FAILED!");
for (;;); // Stop if sensor fails to initialize
} else {
Serial.println("Pulse Oximeter Initialized!");
}
pox.setIRLedCurrent(MAX30100_LED_CURR_7_6MA); // Set the LED current
pox.setOnBeatDetectedCallback(onBeatDetected); // Detect pulse beats
}
void loop() {
pox.update(); // Update pulse oximeter sensor
if (millis() - tsLastReport > REPORTING_PERIOD_MS) {
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("BPM: ");
lcd.print(pox.getHeartRate()); // Display BPM
lcd.setCursor(0, 1);
lcd.print("SpO2: ");
lcd.print(pox.getSpO2()); // Display SpO2
lcd.print("%");
tsLastReport = millis(); // Update the last report time
// Display custom characters based on SpO2 levels
if (pox.getSpO2() >= 96) {
lcd.setCursor(15, 1);
lcd.write(1); // Display smiley face
}
else if (pox.getSpO2() <= 95 && pox.getSpO2() >= 91) {
lcd.setCursor(15, 1);
lcd.write(2); // Display modified face
}
else if (pox.getSpO2() <= 90) {
lcd.setCursor(15, 1);
lcd.write(3); // Display sad face
}
}
}
đź§Ş Testing and Calibration

- Upload the Code: Connect your Arduino Uno to your computer and upload the provided code using the Arduino IDE.
- Connect the Circuit: Use jumper wires to connect the components as per the circuit diagram.
- Power On: Power the Arduino using the USB cable or a 9V battery with clip.
- Observe the LCD: Place your finger on the MAX30100 sensor. The LCD should display your heart rate (BPM) and SpOâ‚‚ levels.
đź§ Working Principle
As you seen above the sensor , here is the working of it . The MAX30100 sensor utilizes two LEDs—red (660 nm) and infrared (940 nm)—to emit light through a fingertip. Oxygenated and deoxygenated hemoglobin absorb these wavelengths differently:
- Oxygenated hemoglobin absorbs more infrared light and less red light.
- Deoxygenated hemoglobin absorbs more red light and less infrared light.
By measuring the variations in light absorption during each heartbeat, the sensor calculates:
- Heart Rate (BPM): Determined by the pulsatile changes in blood volume.
- SpOâ‚‚: Calculated using the ratio of red to infrared light absorption.
The sensor processes this data and communicates it to the Arduino via the I2C protocol, which then displays the readings on the LCD.
Difficulties :
I had difficulties in running the code because I did not download the libraries example liquidcrystal , MAX30100_pulseoximeter .
I also faced difficulties in code when I add buzzer in circuit . Decided that when spO2 is above 95 buzzer will on and after 3 sec it will be off , But this is optional .
so I added this code ,
#include <Wire.h>
#include "MAX30100_PulseOximeter.h"
#define BUZZER_PIN 8 // Buzzer connected to pin 8
#define REPORTING_PERIOD_MS 1000
PulseOximeter pox;
uint32_t tsLastReport = 0;
void setup() {
Serial.begin(9600);
pinMode(BUZZER_PIN, OUTPUT);
digitalWrite(BUZZER_PIN, LOW); // Make sure buzzer is off initially
Serial.print("Initializing pulse oximeter... ");
if (!pox.begin()) {
Serial.println("FAILED");
while (1);
} else {
Serial.println("SUCCESS");
}
âś… Conclusion
This project demonstrates how to interface the MAX30100 sensor with the Arduino Uno and a 16x2 I2C LCD to create a functional pulse oximeter. It's an excellent introduction to sensor integration, data processing, and display interfacing.
Key Takeaways:
- Sensor Integration: Learned how to connect and interface the MAX30100 sensor with the Arduino.
- Data Processing: Understood how the sensor calculates heart rate and SpOâ‚‚ levels.
- Display Interfacing: Implemented the use of an I2C LCD to display real-time data.
Further Exploration:
- Wireless Monitoring: Integrate a Bluetooth module to transmit data to a smartphone.
- Data Logging: Use an SD card module to record readings for later analysis.
- Power Optimization: Implement sleep modes to reduce power consumption for wearable applications.