MAX30102: heart rate monitor and oximeter module for Arduino

MAX30102

During all this time, we have shown a large number of Electronic components compatible with boards like Arduino or compatible, as well as for many other maker or DIY jobs. Now we will introduce you to the module MAX30102, which includes a sensor to measure pulse and blood oxygen.

In this way, you can also create wearables such as self-made activity bracelets or hardware for monitor health status of a person, providing biometric data or telemetry of said person thanks to the integration of the heart rate monitor and oximeter in this device...

What is a heart rate monitor? How does it work?

Un pulse sensor or heart rate monitor It is an electronic device used to measure a person's heart rate in real time. It is mainly used in the sports field to monitor performance and effort during training or on a daily basis. Heart rate monitors are popular among athletes, but they are also a fundamental device in medical centers to know the heart rate, that is, the heart rate or beats per minute:

  • PR Bpm: shows the heart rate, that is, the beats per minute.

In all cases, the Sensors capture variation in blood volume with each heartbeat. This variation is translated into an electrical signal that is processed to obtain the heart rate. Some heart rate monitors also include amplification and noise cancellation circuits to improve the accuracy of the readings.

What is an oximeter? How does it work?

Un oximeter is a medical or sports device which is used to measure oxygen saturation in the blood. This device offers blood oxygen saturation data with values ​​from 0 to 100%. It is common for the same device to also include the heart rate option, indicating all the information for monitoring or recording.

The data that measures an oximeter is

  • %SpO2: refers to the percentage of oxygen saturation in the blood.

The oximeter is placed like a clamp in such a way that it is adapted to the morphology of our finger or it can also be placed in other places on the body, as is the case with the heart rate monitor, such as the wrist, as can be seen in many activity bracelets. ,

Regarding their operation, oximeters emit different light wavelengths that pass through the skin. What acts on this light is hemoglobin, a blood molecule responsible for transporting oxygen, absorbing different amounts of light depending on the level of oxygen it transports. The detailed process is as follows:

  1. light emission- The oximeter emits two wavelengths of light, one red and one infrared, which pass through the finger placed on the device.
  2. Light absorption: Hemoglobin, a molecule in red blood cells that carries oxygen, absorbs different amounts of these lights. Oxygen-laden hemoglobin (oxyhemoglobin) and oxygen-free hemoglobin (deoxyhemoglobin) have different light absorption properties.
  3. Light detection: A detector on the opposite side of the light emitter collects the light that has passed through the finger.
  4. Calculation of oxygen saturation- The device calculates the ratio of oxyhemoglobin to the total amount of hemoglobin present, both oxyhemoglobin and deoxyhemoglobin. This proportion is presented as the percentage of blood oxygen saturation (%SpO2). This is done through a processor capable of interpreting these electrical signals to translate them into a numerical value.

What is MAX30102 module?

The sensor MAX30102, produced by Maxim Integrated, is an integrated device that combines the functionalities of a heart rate monitor and an oximeter. This sensor can easily be used with a microcontroller such as Arduino. The MAX30102 belongs to the MAX3010x series of optical sensors from this firm.

Its operation is based on the variation of light absorption by the blood, depending on its oxygen saturation level, and pulse as I have mentioned in the two previous sections. This sensor is equipped with two LEDs, one red and one infrared. It is placed on the skin, such as on the finger or wrist, and detects reflected light to determine the degree of oxygen saturation.

Communication with the MAX30102 is carried out via I2C bus, making it easy to connect to a microcontroller such as Arduino. The MAX30102 needs a double power supply: 1.8V for the logic and 3.3V for the LEDs. Typically found on 5V modules that already include the necessary level matching.

The MAX30102 is a sensor used in home or sports projects, that is, it may not have sufficient reliability and sensitivity for professional medical use.

La optical pulse oximetry It is a non-invasive method to determine the percentage of oxygen saturation in the blood. As I mentioned before, it is based on the difference in the light absorption coefficients of hemoglobin (Hb) and oxyhemoglobin (HbO2) for different wavelengths. Blood rich in oxygen absorbs more infrared light, while blood low in oxygen absorbs more red light. In areas of the body where the skin is thin enough and there are blood vessels underneath, this difference can be used to determine the degree of oxygen saturation.

Features of the MAX30102 module with pulse and blood oxygen sensor

The MAX30102 includes:

  • 2x LEDs, one red (660nm) and one infrared (880nm)
  • 2x photodiodes to measure reflected light
  • 18-bit ADC converter with a sampling rate of 50 to 3200 samples per second.
  • In addition, it has the necessary electronics for signal amplification and filtering, cancellation of ambient light, rejection of frequencies of 50-60Hz (artificial light) and temperature compensation.

Module consumption can reach up to 50mA during measurement, although the intensity can be adjusted programmatically, with a low power mode of 0.7µA during measurements.

Price and where to buy

The MAX30102 sensors to measure pulse and blood oxygen they are quite cheap. These modules can be yours for just a few euros on sites like eBay, Aliexpress or Amazon. You will see that there are several types, and we recommend the following:

Connections and example with Arduino

Arduino IDE, data types, programming

To test the MAX30102 with Arduino, the first thing is to connect this module to the Arduino board. This connection is very simple, you just have to connect the following:

  1. Vcc of the module must be connected to the 5V output of the Arduino board.
  2. GND of the module must be connected to the GND socket of the Arduino board.
  3. SCL of the module has to be connected to one of the analog inputs of the Arduino board, such as A5.
  4. SDA of the module has to be connected to another of the analog inputs of the Arduino board, such as A4.

Once the appropriate connections have been established between the MAX30102 board and the Arduino board, the next thing will be to write a source code or sketch to make it work and begin receiving biometric data from the person in question. This is as easy as writing the following code in Arduino IDE and program the board:

You also need to install a library in the Arduino IDE to use it. The library has been developed by SparkFun, and is available at https://github.com/sparkfun/SparkFun_MAX3010x_Sensor_Library.
#include <Wire.h>
#include "MAX30105.h"
#include "spo2_algorithm.h"

MAX30102 pulsioximetro;


#define MAX_BRIGHTNESS 255


#if defined(__AVR_ATmega328P__) || defined(__AVR_ATmega168__)
//Arduino Uno no tiene suficiente SRAM para almacenar 100 muestreos, por lo que hay que truncar las muestras en 16-bit MSB.
uint16_t pulsoBuffer[100]; //infrared LED sensor data
uint16_t oxiBuffer[100];  //red LED sensor data

#else
uint32_t pulsoBuffer[100]; //Sensores
uint32_t oxiBuffer[100];  

#endif

int32_t BufferLongitud; //Longitud de datos
int32_t spo2; //Valor de SPO2
int8_t SPO2valido; //Indicador de validez del valor SPO2
int32_t rangopulsacion; //PR BPM o pulsaciones
int8_t validrangopulsacion; //Indicador de validez del valor PR BPM

byte pulsoLED = 11; //Pin PWM
byte lecturaLED = 13; //Titila con cada lectura

void setup()
{
  Serial.begin(115200); // Inicia la comunicación con el microcontrolador a 115200 bits/segundo

  pinMode(pulsoLED, OUTPUT);
  pinMode(lecturaLED, OUTPUT);

  // Inicializar sensores
  if (!pulsioximetro.begin(Wire, I2C_SPEED_FAST)) //Usar el bus I2C a 400kHz 
  {
    Serial.println(F("MAX30102 no encontrado. Por favor, comprueba la conexión y alimentación del módulo."));
    while (1);
  }

  Serial.println(F("Pon el sensor en contacto con tu dedo y presiona cualquier tecla para iniciar la conversión."));
  while (Serial.available() == 0) ; //Esperar hasta que se pulsa una tecla
  Serial.read();

  byte brilloLED = 60; //Opciones: 0=Apagado hasta 255=50mA
  byte mediaMuestreo = 4; //Opciones: 1, 2, 4, 8, 16, 32
  byte ModoLED = 2; //Opciones: 1 = Rojo solo, 2 = Rojo + IR, 3 = Rojo + IR + Verde
  byte rangoMuestreo = 100; //Opciones: 50, 100, 200, 400, 800, 1000, 1600, 3200
  int anchoPulso = 411; //Opciones: 69, 118, 215, 411
  int rangoADC = 4096; //Opciones: 2048, 4096, 8192, 16384

  pulsioximetro.setup(brilloLED, mediaMuestreo, ModoLED, rangoMuestreo, anchoPulso, rangoADC); //Configuración del módulo
}

void loop()
{
  BufferLongitud = 100; //10 almacenamientos en el buffer con 4 segundos corriendo a 25sps

  //Leer las primeras 100 muestras
  for (byte i = 0 ; i < BufferLongitud ; i++)
  {
    while (pulsioximetro.available() == false) //Comprobar nuevos datos
      pulsioximetro.check(); 
    oxiBuffer[i] = pulsioximetro.getRed();
    pulsoBuffer[i] = pulsioximetro.getIR();
    pulsioximetro.siguienteMuestreo(); //Muestreo terminado, ir al siguiente muestreo

    Serial.print(F("red="));
    Serial.print(oxiBuffer[i], DEC);
    Serial.print(F(", ir="));
    Serial.println(pulsoBuffer[i], DEC);
  }

  //Calcular el valor del pulso PM y SpO2 tras los primeros 100 samples
  maxim_heart_rate_and_oxygen_saturation(pulsoBuffer, BufferLongitud, oxiBuffer, &spo2, &SPO2valido, &rangopulsacion, &validrangopulsacion);

  //Calcular muestreos continuos
  while (1)
  {
    //Volcar los 25 primeros valores en memoria y desplazar los últimos 75 arriba
    for (byte i = 25; i < 100; i++)
    {
      oxiBuffer[i - 25] = oxiBuffer[i];
      pulsoBuffer[i - 25] = pulsoBuffer[i];
    }

    for (byte i = 75; i < 100; i++)
    {
      while (pulsioximetro.available() == false) //Comprobar si existen nuevos datos
        pulsioximetro.check(); 

      digitalWrite(lecturaLED, !digitalRead(lecturaLED)); //Parpadea el LED on-board con cada dato

      oxiBuffer[i] = pulsioximetro.getRed();
      pulsoBuffer[i] = pulsioximetro.getIR();
      pulsioximetro.siguienteMuestreo(); //Al finalizar, moverse al siguiente muestreo

      Serial.print(F("Oxígeno="));
      Serial.print(oxiBuffer[i], DEC);
      Serial.print(F(", Pulso="));
      Serial.print(pulsoBuffer[i], DEC);

      Serial.print(F(", HR="));
      Serial.print(rangopulsacion, DEC);

      Serial.print(F(", HRvalid="));
      Serial.print(validrangopulsacion, DEC);

      Serial.print(F(", SPO2="));
      Serial.print(spo2, DEC);

      Serial.print(F(", SPO2 válido="));
      Serial.println(SPO2valido, DEC);
    }

    //Recalcular tras los primeros muestreos
    maxim_heart_rate_and_oxygen_saturation(pulsoBuffer, BufferLongitud, oxiBuffer, &spo2, &SPO2valido, &rangopulsacion, &validrangopulsacion);
  }
}

Of course, you can modify the code according to your needs, this is just an example...


Be the first to comment

Leave a Comment

Your email address will not be published. Required fields are marked with *

*

*

  1. Responsible for the data: Miguel Ángel Gatón
  2. Purpose of the data: Control SPAM, comment management.
  3. Legitimation: Your consent
  4. Communication of the data: The data will not be communicated to third parties except by legal obligation.
  5. Data storage: Database hosted by Occentus Networks (EU)
  6. Rights: At any time you can limit, recover and delete your information.