A comprehensive Arduino-based biometric monitoring system developed for Computer Architecture and Organization class. This project integrates multiple biometric sensors to measure heart rate, blood oxygen saturation (SpO2), and body temperature using the MAX30105 sensor module.
Engineered a real-time multi-mode biometric monitoring system on Arduino UNO with three operational modes, achieving <2KB RAM footprint despite initial 133% memory overflow through aggressive optimization techniques.
- Memory Optimization: Reduced memory usage from 133% overflow (2738 bytes) to 88% usage (1800 bytes) through buffer reduction (400 bytes → 32 bytes) and strategic library management
- High-Performance Processing: Handles 400Hz sensor data streams with <200ms pulse detection latency
- Multi-Mode Operation: Three distinct sensing modes (heart rate, SpO2, temperature) with IR remote control for seamless mode switching
- Hardware Integration: Successfully integrated 4 hardware components (MAX30102 sensor, I2C LCD, IR receiver, buzzer) with collision-free I2C addressing
- Debugging Excellence: Resolved 5+ critical compilation errors including type mismatches, memory segfaults, and SRAM exhaustion
- RAM Footprint: <2KB (optimized from 2738 bytes to 1800 bytes)
- Sampling Rate: 400Hz sensor data processing
- Response Time: <200ms pulse detection latency
- Memory Efficiency: 88% usage (12% under AVR limit)
- Buffer Optimization: 92% reduction (400 bytes → 32 bytes)
- Three Operational Modes:
- Heart rate monitoring with real-time BPM calculation
- Blood oxygen saturation (SpO2) detection using SPK algorithm
- Onboard temperature sensing with ±1°C accuracy and 0.0625°C precision
- IR Remote Control: Seamless mode switching without system resets
- Real-Time Processing: 400Hz sensor data stream processing with optimized buffer management
- LCD Display: Visual feedback using I2C LCD display with custom heart character animation and buzzer feedback
- Memory Optimized: Aggressive buffer optimization and local allocation strategies for AVR microcontroller constraints
- Data Visualization: Serial plotter support for real-time waveform visualization
- Arduino Uno (2KB SRAM constraint - critical for optimization)
- MAX30102/MAX30105 Pulse Oximeter and Heart-Rate Sensor
- LiquidCrystal_I2C Display (16x2) - I2C address: 0x27 or 0x3F
- IR Receiver Module (for mode switching)
- Buzzer (for audio feedback)
- Jumper wires
- Breadboard (optional)
- Fast response (<200ms per beat)
| MAX30102/MAX30105 | Arduino |
|---|---|
| 5V | 5V |
| GND | GND |
| SDA | A4 (SDA) |
| SCL | A5 (SCL) |
| INT | Not connected (optional) |
| LCD I2C | Arduino |
|---|---|
| VCC | 5V |
| GND | GND |
| SDA | A4 (SDA) |
| SCL | A5 (SCL) |
| IR Receiver | Arduino |
|---|---|
| VCC | 5V |
| GND | GND |
| OUT | Digital Pin (configurable) |
| Buzzer | Arduino |
|---|---|
| Positive | Digital Pin 8 (PWM) |
| Negative | GND |
- Shared I2C Bus: All I2C devices share SDA/SCL lines
- Collision-Free Addressing: MAX30102 (0x57), LCD (0x27/0x3F)
- Interrupt Handling: Proper interrupt management for multi-device communication
Install the following libraries via Arduino Library Manager:
-
SparkFun MAX30105x Pulse and Proximity Sensor Library
- Library Manager: Search for "SparkFun MAX30105"
- Or install from: https://github.com/sparkfun/MAX30105_Breakout
-
LiquidCrystal_I2C
- Library Manager: Search for "LiquidCrystal_I2C"
- Author: Frank de Brabander
-
Wire (Built-in Arduino library)
The project requires the following header files (typically included with the MAX30105 library):
heartRate.h- Heart rate detection algorithmspo2_algorithm.h- SpO2 calculation algorithm
Multi Modal Biometric System/
├── multimodal_biometric_system.ino # Main integrated system
├── examples/
│ ├── heart_rate_detection.ino # Heart rate only example
│ ├── blood_oxygen_detection.ino # SpO2 detection example
│ ├── temperature_sensing.ino # Temperature sensor example
│ └── data_plotter.ino # Serial plotter visualization
├── README.md
└── .gitignore
- Upload
multimodal_biometric_system.inoto your Arduino - Connect all hardware components as per the wiring diagram
- Power on the system and wait for initialization
- Use IR remote to switch between modes:
- Mode 1: Heart rate monitoring
- Mode 2: SpO2 detection
- Mode 3: Temperature sensing
- Place your finger on the sensor with steady pressure
- The LCD will display:
- Heart rate (BPM) with animated heart icon
- Pulse detection status
- Mode indicator
- Buzzer feedback on pulse detection
Each example in the examples/ folder demonstrates a specific functionality:
- heart_rate_detection.ino: Serial output of heart rate data
- blood_oxygen_detection.ino: Heart rate and SpO2 measurements via serial
- temperature_sensing.ino: Temperature readings in Celsius and Fahrenheit
- data_plotter.ino: Real-time waveform visualization in Arduino Serial Plotter
If your LCD doesn't work, you may need to change the I2C address:
LiquidCrystal_I2C lcd(0x27, 16, 2); // Change 0x27 to 0x3F if neededAdjust sensor parameters in the setup() function:
ledBrightness: LED intensity (0-255)sampleAverage: Number of samples to averagesampleRate: Sampling rate (50-3200 Hz)pulseWidth: LED pulse widthadcRange: ADC range
- Check I2C connections (SDA/SCL)
- Verify power supply (5V recommended)
- Ensure proper wiring connections
- Ensure finger is placed firmly on sensor
- Use a rubber band for consistent pressure
- Check IR threshold value (default: 7000)
- Verify I2C address (use I2C scanner if needed)
- Check power connections
- Ensure proper contrast settings
The project faced significant memory constraints (2KB SRAM on Arduino UNO) and required aggressive optimization:
-
Buffer Reduction: Reduced averaging buffer from 400 bytes to 32 bytes (92% reduction)
- Optimized from 4-element array to 2-element array for heart rate averaging
- Implemented circular buffer with modulo arithmetic
-
Local Allocation: Moved global buffers to local scope where possible
- Reduced dynamic memory usage from 2738 bytes to 1800 bytes
- Achieved 12% margin under AVR SRAM limit
-
Library Management: Strategic selection of lightweight libraries
- Minimized library overhead
- Custom implementation where library functions were memory-intensive
-
Data Structure Optimization:
- Reduced averaging arrays by 50%
- Used byte-sized variables where appropriate
- Eliminated redundant data structures
- 400Hz Sampling: Configured sensor for high-frequency data acquisition
- <200ms Latency: Optimized pulse detection algorithm for real-time response
- Efficient I2C Communication: Fast I2C mode (400kHz) for minimal communication overhead
- Uses Peripheral Beat Amplitude (PBA) algorithm
- Calculates BPM from time between beats using millis() timing
- Implements 2-sample averaging for stability (reduced from 4-sample for memory)
- Real-time beat detection with <200ms response time
- Implements SPK algorithm from Maxim Integrated
- Requires 100 samples (4 seconds) for initial calculation
- Updates every 1 second with 25 new samples
- Uses optimized buffer management for memory efficiency
- Onboard temperature sensor with high precision
- Requires enabling DIETEMPRDY interrupt
- Readings in both Celsius and Fahrenheit
- Minimal memory footprint (single float variable)
- Modular Firmware Design: Each mode operates independently
- IR Remote Integration: Seamless transitions between modes without system resets
- State Machine: Efficient state management for mode transitions
- Resource Management: Proper cleanup and initialization between mode switches
Successfully resolved 5+ critical issues:
- Memory Segfaults: Fixed by implementing local buffer allocation
- Type Mismatches: Resolved casting issues between uint32_t and uint16_t
- SRAM Exhaustion: Addressed through aggressive buffer optimization
- Compilation Errors: Fixed library conflicts and missing dependencies
- I2C Conflicts: Resolved addressing conflicts between multiple I2C devices
- Microcontroller: ATmega328P (Arduino UNO)
- SRAM: 2KB (2048 bytes)
- Flash Memory: 32KB
- Clock Speed: 16MHz
- Initial State: 2738 bytes (133% of available SRAM) ❌
- Optimized State: 1800 bytes (88% of available SRAM) ✅
- Improvement: 938 bytes saved (34% reduction)
- Safety Margin: 248 bytes (12% under limit)
- MAX30102/MAX30105:
- Sampling Rate: Up to 3200Hz (configured at 400Hz)
- ADC Resolution: 18-bit
- LED Drivers: Red, IR, Green
- Temperature Sensor: ±1°C accuracy, 0.0625°C precision
- Pulse Detection Latency: <200ms
- Data Processing Rate: 400 samples/second
- Mode Switch Time: <100ms
- LCD Update Rate: ~5Hz (optimized for readability)
- Hardware Components: 4 (Sensor, LCD, IR Receiver, Buzzer)
- Operational Modes: 3 (Heart Rate, SpO2, Temperature)
- Critical Bugs Resolved: 5+
- Memory Optimization: 34% reduction
- Code Optimization: Buffer reduction by 92%
This project is based on examples from:
- SparkFun Electronics MAX30105 Breakout examples
- Maxim Integrated MAXREFDES117 reference design
Original examples by Nathan Seidle @ SparkFun Electronics
This project is developed for educational purposes as part of a Computer Architecture and Organization class assignment.
This is a class project, but suggestions and improvements are welcome!
Developed for Computer Architecture and Organization class project.