Hướng dẫn sử dụng cảm biến nhịp tim và Oxy trong máu MAX30102 với Arduino

Hướng dẫn sử dụng cảm biến nhịp tim và Oxy trong máu MAX30102 với Arduino

Bạn đang quan tâm đến việc sử dụng cảm biến nhịp tim và Oxy trong máu MAX30102 với Arduino? Trong bài viết này, hãy cùng mình khám phá cách sử dụng module MAX30102 để đo mức oxy (SpO2) và nhịp tim (HR) thông qua giao tiếp với Arduino.

Ngoài ra, bạn sẽ tìm hiểu về các chức năng của cảm biến, cách kết nối với Arduino và lập trình để thu thập dữ liệu SpO2 và HR. Bằng cách áp dụng các kiến thức này, bạn có thể tạo ra các ứng dụng y tế, giám sát sức khỏe hoặc các dự án sáng tạo khác liên quan đến đo nhịp tim và mức oxy trong máu.

Để tạo động lực cho Team Arduino KIT ra nhiều bài viết chất lượng hơn, các bạn có thể ủng hộ mình bằng cách Donate qua MoMo, Ngân hàng, Paypal…Nhấn vào link bên dưới nhé.

Linh kiện cần thiết cho dự án

TÊN LINH KIỆN SỐ LƯỢNG NƠI BÁN
Arduino Uno R3 1 Shopee | Cytron
Cảm biến nhịp tim MAX30102 1 Shopee | Cytron
Breadboard 1 Shopee | Cytron
Dây cắm (Đực – Đực) 10 – 20 Shopee | Cytron

Tổng quan về cảm biến nhịp tim và Oxy trong máu MAX30102

Module này tích hợp một IC cao cấp MAX30102 (phiên bản nâng cấp của MAX30100) từ Analog Devices, được sử dụng để đo mức oxy (SpO2) và nhịp tim (HR). Nó kết hợp hai đèn LED, bộ tách sóng quang, và quá trình xử lý tín hiệu Analog với độ nhiễu thấp để phát hiện các tín hiệu SpO2 và HR.

Mặt sau của module có hai đèn LED, bao gồm một đèn LED đỏ và một đèn LED hồng ngoại. Phía bên kia là bộ tách sóng quang cực kỳ nhạy. Cách hoạt động là bạn sẽ chiếu ánh sáng từ một đèn LED duy nhất vào cơ thể, sau đó ánh sáng phản xạ từ module và dựa trên thông tin thu được, bạn có thể đo mức oxy trong máu và nhịp tim.

Xem ngay: Hướng dẫn sử dụng cảm biến nhịp tim (Pulse Sensor) với Arduino

Nguồn cấp

Cảm biến đo nhịp tim MAX30102 có hai dải điện áp khác nhau: 1.8V cho IC và 3.3V cho đèn LED và IR. Vì vậy, module được tích hợp bộ điều chỉnh điện áp 3.3V và 1.8V.

Ở mặt sau của module, bạn sẽ thấy một Jumper hàn dùng để chọn giữa mức logic 3.3V và 1.8V. Theo mặc định, sẽ là mức logic 3.3V phù hợp cho Arduino. Nhưng bạn cũng có thể chọn mức logic 1.8V theo từng yêu cầu vụ thể.

Một trong những tính năng quan trọng nhất của cảm biến MAX30102 là mức tiêu thụ điện năng thấp: MAX30102 tiêu thụ khoảng 600μA trong quá trình đo. Ngoài ra, có thể đặt MAX30102 ở chế độ chờ, mức tiêu thụ chỉ 0,7μA. Mức tiêu thụ điện năng thấp cho phép triển khai trong các thiết bị chạy bằng pin như thiết bị cầm tay, thiết bị đeo tay hoặc đồng hồ thông minh.

Cảm biến nhiệt độ

MAX30102 có một cảm biến nhiệt độ được tích hợp sẵn trên module được sử dụng để bù cho những thay đổi trong môi trường và hiệu chỉnh các phép đo.

Đây là cảm biến nhiệt độ có độ chính xác hợp lý có thể đo nhiệt độ trong khoảng từ -40˚C đến +85˚C với độ chính xác ±1˚C.

Giao tiếp I2C

Module sử dụng giao tiếp I2C, thông qua hai dây truyền dữ liệu SDA và SCL để giao tiếp với Arduino. Địa chỉ I2C mặc định là: 0xAE HEX (cho thao tác ghi) và 0xAF HEX (cho thao tác đọc).

Bộ đệm FIFO

Bộ đệm FIFO trong cảm biến nhịp tim và oxy trong máu MAX30102 được sử dụng để lưu trữ các mẫu dữ liệu nhịp tim và mức độ oxy huyết trong máu mà cảm biến đo được.

Bộ đệm FIFO trong cảm biến MAX30102 có thể được cấu hình để lưu trữ từ 32 đến 256 mẫu dữ liệu, tùy thuộc vào cài đặt của bạn. Khi bộ đệm đạt đến giới hạn lưu trữ, các mẫu dữ liệu mới sẽ ghi đè lên các mẫu cũ, theo nguyên tắc First-In-First-Out.

Ngắt (Interrupts)

MAX30102 có thể sử dụng ngắt để lập trình. Có thể kích hoạt ngắt trong 5 trường hợp sau:

  • Power Ready: Kích hoạt khi bật nguồn hoặc sau khi mất điện. Ngắt này thông báo cho vi điều khiển rằng MAX30102 đã hoàn tất quá trình khởi động và sẵn sàng hoạt động.
  • New Data Ready: Kích hoạt sau mỗi lần thu thập mẫu dữ liệu SpO2 và nhịp tim (HR). Ngắt này cho biết rằng dữ liệu mới đã sẵn sàng để đọc từ bộ nhớ FIFO của cảm biến MAX30102.
  • Ambient Light Cancellation: Kích hoạt khi chức năng loại bỏ ánh sáng xung quanh của diode quang SpO2/HR đạt đến giới hạn tối đa và ảnh hưởng đến đầu ra của ADC. Ngắt này thông báo về việc điều chỉnh ánh sáng xung quanh để đảm bảo chất lượng đo lường.
  • Temperature Ready: Kích hoạt khi quá trình chuyển đổi nhiệt độ bên trong MAX30102 kết thúc. Ngắt này thông báo rằng dữ liệu nhiệt độ mới nhất đã sẵn sàng để đọc.
  • FIFO Almost Full: Ngắt này cảnh báo cho vi điều khiển rằng FIFO sắp đầy và cần được đọc và xử lý để tránh mất dữ liệu.

Thông số kỹ thuật

Power supply 3.3V to 5.5V
Current draw ~600μA (during measurements)
~0.7μA (during standby mode)
Red LED Wavelength 660nm
IR LED Wavelength 880nm
Temperature Range -40˚C to +85˚C
Temperature Accuracy ±1˚C

Cảm biến nhịp tim và Oxy trong máu MAX30102 hoạt động như thế nào

Cảm biến nhịp tim và oxy trong máu MAX30102 hoạt động dựa trên nguyên lý phát hiện ánh sáng hấp thụ bởi máu trong các mô và mạch máu. MAX30102 sử dụng công nghệ phản xạ ánh sáng hồng ngoại (IR) và ánh sáng đỏ để đo lường nồng độ oxy (SpO2) và nhịp tim (HR) của người dùng.

Cảm biến được tích hợp các đèn LED hồng ngoại và đèn LED đỏ, cùng với một bộ lọc quang để tạo ra ánh sáng phù hợp để xuyên qua da và mô màu đỏ. Đèn LED hồng ngoại thẩm thấu sâu vào da, trong khi đèn LED đỏ thẩm thấu xa hơn. Khi ánh sáng được chiếu qua da, nó sẽ gặp phản xạ từ máu chảy trong các mạch máu dưới da.

Cảm biến sử dụng photodiodes để đo lượng ánh sáng phản xạ từ máu. Các photodiodes nhận tín hiệu ánh sáng và chuyển đổi chúng thành dữ liệu Analog. Sau đó, dữ liệu này được khuếch đại và chuyển đổi thành dữ liệu kỹ thuật số bằng một bộ chuyển đổi analog-số (ADC).

Sơ đồ chân module MAX30102

  • VIN: Chân dương (3.3V hoặc 5V)
  • SCL: Chân xung clock
  • SDA: Chân dữ liệu
  • INT: Chân ngắt (interrupt), được sử dụng để kích hoạt ngắt trong các sự kiện
  • IRD: Chân dữ liệu hồng ngoại, đây là chân dữ liệu đầu ra hồng ngoại từ cảm biến
  • RD: Chân dữ liệu LED đỏ, dùng để đo nồng độ oxy (SpO2) và nhịp tim (HR)
  • GND: Chân nối đất

Sơ đồ đấu nối cảm biến nhịp tim và Oxy trong máu MAX30102 với Arduino

Arduino Uno R3 Module MAX30102
5V VIN
GND GND
A4 SDA
A5 SCL

Cài đặt thư viện

Để giao tiếp với bất kỳ cảm biến nào với Arduino IDE, bước đầu tiên các bạn cần phải cài đặt thư viện tương ứng. Có rất nhiều thư viện dành cho cảm biến nhịp tim và Oxy trong máu MAX30102, nhưng thư viện mình thấy đơn giản và hiểu nhất là của SparkFun, để cài đặt các bạn truy cập theo đường dẫn: Sketch > Include Library > Manage Libraries…

Tìm kiếm thư viện, bằng cách nhập từ khóa ‘max3010x’, chọn đến thư viện SparkFun MAX3010x Pulse and Proximity Sensor và tiến hành cài đặt.

Code đo nhịp tim (BPM)

#include <Wire.h>
#include "MAX30105.h"
#include "heartRate.h"

MAX30105 particleSensor;

const byte RATE_SIZE = 4; //Increase this for more averaging. 4 is good.
byte rates[RATE_SIZE]; //Array of heart rates
byte rateSpot = 0;
long lastBeat = 0; //Time at which the last beat occurred

float beatsPerMinute;
int beatAvg;

void setup() {
  Serial.begin(115200);
  Serial.println("Initializing...");

  // Initialize sensor
  if (!particleSensor.begin(Wire, I2C_SPEED_FAST)) {
    Serial.println("MAX30102 was not found. Please check wiring/power. ");
    while (1);
  }
  Serial.println("Place your index finger on the sensor with steady pressure.");

  particleSensor.setup(); //Configure sensor with default settings
  particleSensor.setPulseAmplitudeRed(0x0A); //Turn Red LED to low to indicate sensor is running
  particleSensor.setPulseAmplitudeGreen(0); //Turn off Green LED
}

void loop() {
  long irValue = particleSensor.getIR();

  if (checkForBeat(irValue) == true) {
    //We sensed a beat!
    long delta = millis() - lastBeat;
    lastBeat = millis();

    beatsPerMinute = 60 / (delta / 1000.0);

    if (beatsPerMinute < 255 && beatsPerMinute > 20) {
      rates[rateSpot++] = (byte)beatsPerMinute; //Store this reading in the array
      rateSpot %= RATE_SIZE; //Wrap variable

      //Take average of readings
      beatAvg = 0;
      for (byte x = 0 ; x < RATE_SIZE ; x++)
        beatAvg += rates[x];
      beatAvg /= RATE_SIZE;
    }
  }

  Serial.print("IR=");
  Serial.print(irValue);
  Serial.print(", BPM=");
  Serial.print(beatsPerMinute);
  Serial.print(", Avg BPM=");
  Serial.print(beatAvg);

  if (irValue < 50000)
    Serial.print(" No finger?");

  Serial.println();
}

Sau khi nạp code xong, các bạn đưa ngón tay lại gần cảm biến nhịp tim MAX30102, và xem kết quả. Dưới đây là kết quả đo nhịp tim (BMP).

Code đo nồng độ Oxy trong máu (SpO2)

#include <Wire.h>
#include "MAX30105.h"
#include "spo2_algorithm.h"

MAX30105 particleSensor;

#define MAX_BRIGHTNESS 255

#if defined(__AVR_ATmega328P__) || defined(__AVR_ATmega168__)
//Arduino Uno doesn't have enough SRAM to store 100 samples of IR led data and red led data in 32-bit format
//To solve this problem, 16-bit MSB of the sampled data will be truncated. Samples become 16-bit data.
uint16_t irBuffer[100]; //infrared LED sensor data
uint16_t redBuffer[100];  //red LED sensor data
#else
uint32_t irBuffer[100]; //infrared LED sensor data
uint32_t redBuffer[100];  //red LED sensor data
#endif

int32_t bufferLength; //data length
int32_t spo2; //SPO2 value
int8_t validSPO2; //indicator to show if the SPO2 calculation is valid
int32_t heartRate; //heart rate value
int8_t validHeartRate; //indicator to show if the heart rate calculation is valid

byte pulseLED = 11; //Must be on PWM pin
byte readLED = 13; //Blinks with each data read

void setup()
{
  Serial.begin(115200); // initialize serial communication at 115200 bits per second:

  pinMode(pulseLED, OUTPUT);
  pinMode(readLED, OUTPUT);

  // Initialize sensor
  if (!particleSensor.begin(Wire, I2C_SPEED_FAST)) //Use default I2C port, 400kHz speed
  {
    Serial.println(F("MAX30105 was not found. Please check wiring/power."));
    while (1);
  }

  Serial.println(F("Attach sensor to finger with rubber band. Press any key to start conversion"));
  while (Serial.available() == 0) ; //wait until user presses a key
  Serial.read();

  byte ledBrightness = 60; //Options: 0=Off to 255=50mA
  byte sampleAverage = 4; //Options: 1, 2, 4, 8, 16, 32
  byte ledMode = 2; //Options: 1 = Red only, 2 = Red + IR, 3 = Red + IR + Green
  byte sampleRate = 100; //Options: 50, 100, 200, 400, 800, 1000, 1600, 3200
  int pulseWidth = 411; //Options: 69, 118, 215, 411
  int adcRange = 4096; //Options: 2048, 4096, 8192, 16384

  particleSensor.setup(ledBrightness, sampleAverage, ledMode, sampleRate, pulseWidth, adcRange); //Configure sensor with these settings
}

void loop()
{
  bufferLength = 100; //buffer length of 100 stores 4 seconds of samples running at 25sps

  //read the first 100 samples, and determine the signal range
  for (byte i = 0 ; i < bufferLength ; i++)
  {
    while (particleSensor.available() == false) //do we have new data?
      particleSensor.check(); //Check the sensor for new data

    redBuffer[i] = particleSensor.getRed();
    irBuffer[i] = particleSensor.getIR();
    particleSensor.nextSample(); //We're finished with this sample so move to next sample

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

  //calculate heart rate and SpO2 after first 100 samples (first 4 seconds of samples)
  maxim_heart_rate_and_oxygen_saturation(irBuffer, bufferLength, redBuffer, &spo2, &validSPO2, &heartRate, &validHeartRate);

  //Continuously taking samples from MAX30102.  Heart rate and SpO2 are calculated every 1 second
  while (1)
  {
    //dumping the first 25 sets of samples in the memory and shift the last 75 sets of samples to the top
    for (byte i = 25; i < 100; i++)
    {
      redBuffer[i - 25] = redBuffer[i];
      irBuffer[i - 25] = irBuffer[i];
    }

    //take 25 sets of samples before calculating the heart rate.
    for (byte i = 75; i < 100; i++)
    {
      while (particleSensor.available() == false) //do we have new data?
        particleSensor.check(); //Check the sensor for new data

      digitalWrite(readLED, !digitalRead(readLED)); //Blink onboard LED with every data read

      redBuffer[i] = particleSensor.getRed();
      irBuffer[i] = particleSensor.getIR();
      particleSensor.nextSample(); //We're finished with this sample so move to next sample

      //send samples and calculation result to terminal program through UART
      Serial.print(F("red="));
      Serial.print(redBuffer[i], DEC);
      Serial.print(F(", ir="));
      Serial.print(irBuffer[i], DEC);

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

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

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

      Serial.print(F(", SPO2Valid="));
      Serial.println(validSPO2, DEC);
    }

    //After gathering 25 new samples recalculate HR and SP02
    maxim_heart_rate_and_oxygen_saturation(irBuffer, bufferLength, redBuffer, &spo2, &validSPO2, &heartRate, &validHeartRate);
  }
}

Giống như việc đo nhịp tim, để đo được nồng độ oxy trong máy, các bạn cũng để ngón tay lại gần cảm biến. Thông tin sẽ được hiển thị trên Serial Monitor.

Bài viết liên quan

Subscribe
Notify of
guest

0 Comments
Inline Feedbacks
View all comments