| Crates.io | max30102 |
| lib.rs | max30102 |
| version | 0.1.0 |
| created_at | 2026-01-10 11:14:09.989968+00 |
| updated_at | 2026-01-10 11:14:09.989968+00 |
| description | Blocking and async driver for the MAX30102 pulse oximeter and heart rate sensor |
| homepage | |
| repository | https://github.com/leftger/max30102 |
| max_upload_size | |
| id | 2034059 |
| size | 81,842 |
A no_std Rust driver for the MAX30102 pulse oximeter and heart rate sensor with support for both blocking and async I2C operations.
embedded-hal and embedded-hal-asyncdevice-driver for type-safe register accessThe MAX30102 is an integrated pulse oximetry and heart rate monitor sensor solution. It combines:
Add this to your Cargo.toml:
[dependencies]
max30102 = "0.1.0"
For async support:
[dependencies]
max30102 = { version = "0.1.0", features = ["async"] }
For Embassy framework support:
[dependencies]
max30102 = { version = "0.1.0", features = ["embassy"] }
use max30102::{Max30102, SampleRate, PulseWidth, AdcRange};
use embedded_hal::i2c::I2c;
fn main() -> Result<(), Error> {
// Initialize your I2C peripheral
let i2c = /* your I2C instance */;
// Create the driver
let mut sensor = Max30102::new(i2c);
// Verify the device
sensor.verify_part_id()?;
// Reset and configure
sensor.reset()?;
sensor.set_sample_rate(SampleRate::Rate100)?;
sensor.set_pulse_width(PulseWidth::Pw411)?;
sensor.set_adc_range(AdcRange::Range4096)?;
sensor.set_led_pulse_amplitude(0x1F, 0x1F)?;
sensor.set_fifo_rollover(true)?;
sensor.clear_fifo()?;
// Start SpO2 mode (Red + IR LEDs)
sensor.start_spo2_mode()?;
// Read samples
loop {
if sensor.get_fifo_samples_available()? > 0 {
let (red, ir) = sensor.read_fifo_sample()?;
// Process red and ir values...
}
}
}
// Start temperature conversion
sensor.start_temperature_conversion()?;
// Wait for conversion to complete
while !sensor.is_temperature_ready()? {
// Wait or do other work
}
// Read temperature in Celsius
let temp = sensor.read_temperature()?;
// Configure FIFO almost full interrupt (4 samples remaining)
sensor.set_fifo_almost_full(4)?;
sensor.enable_fifo_almost_full_interrupt()?;
// In your interrupt handler:
let status = sensor.read_interrupt_status_1()?;
if (status & 0x80) != 0 {
// FIFO almost full
let mut buffer = [0u8; 24]; // 4 samples * 6 bytes
sensor.read_fifo(&mut buffer)?;
}
use max30102::Max30102;
use embassy_time::Timer;
#[embassy_executor::task]
async fn sensor_task(i2c: I2cDevice) {
let mut sensor = Max30102::new(i2c);
sensor.verify_part_id_async().await.unwrap();
sensor.reset_async().await.unwrap();
sensor.start_spo2_mode().unwrap();
loop {
if sensor.get_fifo_samples_available().unwrap() > 0 {
let mut buffer = [0u8; 6];
sensor.read_fifo_async(&mut buffer).await.unwrap();
// Process samples...
}
Timer::after_millis(10).await;
}
}
Uses only the red LED to detect heart rate.
sensor.start_heart_rate_mode()?;
Uses both red and IR LEDs for SpO2 and heart rate measurement (most common mode).
sensor.start_spo2_mode()?;
Advanced mode allowing custom LED time-slotting patterns.
sensor.start_multi_led_mode()?;
Available rates: 50, 100, 200, 400, 800, 1000, 1600, 3200 samples per second
sensor.set_sample_rate(SampleRate::Rate100)?;
Pw69: 69 μs (15-bit ADC resolution)Pw118: 118 μs (16-bit ADC resolution)Pw215: 215 μs (17-bit ADC resolution)Pw411: 411 μs (18-bit ADC resolution)sensor.set_pulse_width(PulseWidth::Pw411)?;
Range2048: 2048 nA full scaleRange4096: 4096 nA full scale (typical)Range8192: 8192 nA full scaleRange16384: 16384 nA full scalesensor.set_adc_range(AdcRange::Range4096)?;
Values from 0x00 to 0xFF control LED brightness (0x1F is typical).
sensor.set_led_pulse_amplitude(0x1F, 0x1F)?; // Red, IR
Average multiple samples to reduce noise: 1, 2, 4, 8, 16, or 32 samples.
sensor.set_sample_averaging(SampleAveraging::Avg4)?;
The MAX30102 has a 32-sample FIFO buffer that can be configured to:
// Enable rollover mode
sensor.set_fifo_rollover(true)?;
// Clear FIFO
sensor.clear_fifo()?;
// Check available samples
let count = sensor.get_fifo_samples_available()?;
// Read samples
let (red, ir) = sensor.read_fifo_sample()?;
// Enter low-power shutdown mode
sensor.shutdown()?;
// Wake up from shutdown
sensor.wakeup()?;
// Software reset
sensor.reset()?;
async: Enable async I2C support via embedded-hal-asyncdefmt-03: Enable defmt logging supportembassy: Enable both async and defmt support for Embassy frameworkThe MAX30102 uses I2C communication:
| MAX30102 Pin | Function | MCU Connection |
|---|---|---|
| VCC | Power Supply | 1.8V or 3.3V |
| GND | Ground | GND |
| SDA | I2C Data | I2C SDA |
| SCL | I2C Clock | I2C SCL |
| INT | Interrupt (optional) | GPIO with interrupt |
Default I2C address: 0x57
Licensed under either of:
at your option.
Contributions are welcome! Please feel free to submit a Pull Request.