It's time for some more advanced heart rate sensors. Today, we are going to take a look at the MAX3010x pulse oximeter sensor family.
The MAX3010x family is a series of pulse oximeter sensors manufactured by Maxim Integrated. Currently, the sensor family consists of the MAX30100, the MAX30101, the MAX30102 and the MAX30105. Only the MAX30101 and the MAX30102 are still actively manufactured. All sensors feature a red and an IR LED, as well as a photodiode to measure the amount of reflected light. In addition to that, the MAX30101 and the MAX30105 have a green LED. The sensors are designed for photoplethysmography (PPG) aka optical heart rate measurements, pulse oximetry, proximity sensing and particle detection in case of the MAX30105.
The fundamental working principle is the same as the one of simple heart rate modules. Only one LED is active at a time. The photodiode is then used to measure the amount of reflected light which varies due to the changing amount of blood in the tissue during heart beats. However, the MAX3010x sensors can do more than only heart rate measurements. They can be used for pulse oximetry as well.
So what is pulse oximetry and how does it work? Pulse oximetry is a method to measure the peripheral oxygen saturation (SpO2). In our body the red blood cells transport oxygen from our lungs into the whole body. They do this with the help of a protein called hemoglobin. The hemoglobin reacts with the oxygen in the lungs and becomes oxygenated hemoglobin. The stored oxygen is then released in the cells that need it and the hemoglobin becomes deoxygenated hemoglobin again.
Oxygenated and deoxygenated hemoglobin have a slightly different molecular structure which also causes them to have a different absorption spectrum. Oxygenated hemoglobin absorbs IR light stronger than red light, while deoxygenated hemoglobin absorbs red light better than IR light. In the blood we always have a mix of both. By comparing the amount of absorbed light for the red and the IR LED, it is possible to determine the concentration of each of the two and calculate the oxygen saturation.
Let's see how we can use the MAX3010x modules to acquire data, which we can later use for heart rate measurements and pulse oximetry.
As a first step, we need to connect the sensor module to the Arduino Uno. The sensor is using I2C for the data transfer. In consequence, we need only four wires: two for power, one data line (SDA
) and one clock line (SCL
). In the simplest case we can directly connect the sensor to the Arduino Uno. For this we connect VIN
to 5V
, GND
to GND
, SDA
to SDA
and SCL
to SCL
. However, there are some MAX301x modules that are not designed for 5 V, but for 3.3 V. To use these modules with the Arduino Uno, you need to connect them through a logic level converter. Both ways are shown in the images below:
For communicating with the sensor we need to import an Arduino Library. There are already some libraries for different sensors out of the MAX3010x sensor family, but none that I found has support for all of them. For this reason I decided to create one for the purpose of this tutorial.
You can install the MAX3010x Sensor Library
via the Arduino Library Manager or download it using the download link below. The ZIP archive can be imported into the Arduino IDE by clicking Sketch
> Include Library
> Add .ZIP Library ...
. If you have any issues with the library, report them on GitHub.
Once you have installed the library, it is time to make use of it. The example below shows how you can use the sensor with a default configuration to acquire data for both the red and the IR LED. Adjust the code to the sensor you are using by uncommenting the corresponding code line:
#include <MAX3010x.h>
/*
* Select your sensor by uncommenting
* the corresponding line
*/
MAX30100 sensor;
// MAX30101 sensor;
// MAX30102 sensor;
// MAX30105 sensor;
void setup() {
Serial.begin(115200);
if(sensor.begin()) {
Serial.println("IR,Red");
}
else {
Serial.println("Sensor not found");
while(1);
}
}
void loop() {
auto sample = sensor.readSample(1000);
Serial.print(sample.ir);
Serial.print(",");
Serial.println(sample.red);
}
In the default configuration the sensor performs 50 measurements per second which corresponds to one measurement every 20 ms. The sensor has an internal buffer to store these measurements. However, if they are not read back fast enough the buffer runs full and the sensor starts dropping samples. For this reason the program uses a baudrate of 115200
instead of the usual 9600
. This enables a faster data transfer from the Arduino to your computer.
The result can be viewed in the serial plotter (Tools
> Serial Plotter
). Please remember to set the baudrate to 115200
. If you hold your finger on the sensor, you should be able to recognize your heart beats in the graph:
In case that the values from the two LEDs differ a lot, the serial plotter will zoom out and you might not be able to see the small changes caused by your heart beat. In this case it can make sense to change the program, so that only the value of one of the two LEDs is transmitted at a time.
If you play around with the sensor, you will quickly notice, that it is very easy to detect if no finger is on the sensor. With the simpler heart rate modules with only one LED and a photodiode this was much harder. The reason for this is MAX3010x sensors built-in ambient light cancellation. If no finger is on the sensor the output value is close to zero, once you move your finger closer the value rises. Due to the ambient light cancellation the sensor can also be used as a proximity sensor. The MAX30105 sensor even has some special functions for that.