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.
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
- Giao tiếp cảm biến điện áp Voltage Sensor với Arduino
- Hướng dẫn sử dụng cảm biến gia tốc MPU6050 với Arduino
- Cách thức hoạt động của Rotary Encoder với Arduino
- Giao tiếp cảm biến nhiệt độ, độ ẩm, áp suất không khí BME280 với Arduino
- Hướng dẫn sử dụng cảm biến nồng độ cồn MQ3 (Alcohol Sensor) với Arduino