ساخت پالس‌اکسی‌متر خانگی با آردوینو و سنسور MAX30102

مقدمه

در دنیای امروز که تجهیزات پایش سلامتی نقش مهمی در تشخیص سریع و مراقبت دقیق دارند، ساخت یک پالس‌اکسی‌متر خانگی نه تنها یک پروژه جذاب مهندسی است، بلکه می‌تواند در شرایط اضطراری کاربرد واقعی داشته باشد. پالس‌اکسی‌متر دستگاهی است که میزان اکسیژن خون (SpO₂) و ضربان قلب را اندازه‌گیری می‌کند و معمولاً در بیمارستان‌ها، کلینیک‌ها و حتی خانه‌ها مورد استفاده قرار می‌گیرد.

در این آموزش، قدم به قدم یاد می‌گیریم چگونه با استفاده از سنسور MAX30102، یک LCD کاراکتری و یک بیزر هشداردهنده، نسخه‌ی اختصاصی خودمان را بسازیم؛ دستگاهی که هم اندازه‌گیری‌ها را دقیق و لحظه‌ای نمایش می‌دهد و هم در شرایط بحرانی مانند افت اکسیژن یا افزایش بیش از حد ضربان، به‌صورت خودکار هشدار می‌دهد و هم قادر به تشخیص قرار گیری انگشت روی سنسور است.

ویژگی‌های سنسور تشخیص ضربان قلب و اکسیژن خون MAX30102

سنسور MAX30102 یک ماژول پیشرفته است که می‌تواند ضربان قلب و سطح اکسیژن خون را با دقت بالا اندازه‌گیری کند. این سنسور از نور LED و فوتودیود برای خواندن تغییرات جریان خون استفاده می‌کند و به دلیل اندازه کوچک و مصرف پایین، برای پروژه‌های خانگی و پزشکی ایده‌آل است.

MAX30102 Heart Rate Module Datasheet

این سنسور از فناوری PPG (Photoplethysmography) استفاده می‌کند، دارای LED قرمز و IR است و می‌تواند داده‌ها را با دقت میلی‌ثانیه‌ای برای الگوریتم‌های تشخیص ضربان قلب و اکسیژن خون فراهم کند.

معرفی پایه‌ها (Pinout) سنسور MAX30102

سنسور MAX30102 دارای چند پایه اصلی است:

  • VIN: تغذیه 3.3V یا 5V
  • GND: زمین
  • SCL: خط ساعت I2C
  • SDA: خط داده I2C
  • INT: وقفه اختیاری برای برخی عملکردها

لوازمی که به آن احتیاج دارید

قطعات مورد نیاز

ال‌سی‌دی کاراکتری 16×2×1🛒
ماژول سنسور اکسیژن خون و ضربان MAX30102×1🛒
ماژول بیزر (Buzzer)×1🛒
برد آردوینو (UNO یا هر مدل سازگار)×1🛒
مبدل سریال I2C برای LCD×1🛒

نرم‌افزارهای مورد نیاز

  • Arduino IDE آخرین نسخه
  • کتابخانه‌های MAX30102 برای آردوینو
  • کتابخانه LiquidCrystal برای نمایشگر LCD

راه‌اندازی ماژول MAX30102 با آردوینو

ماژول MAX30102

ماژول I2C LCD

گام اول: سیم‌بندی

ابتدا سنسور MAX30102 را به آردوینو متصل کنید:

  • VCC به 3.3V یا 5V
  • GND به زمین
  • SCL به A5 (در Arduino UNO)
  • SDA به A4 (در Arduino UNO)
  • INT به اختیاری

و همچنین برای LCD داریم

و در انتها بازر را متصل کنید.

در تصویر به پایه ۱۲ اتصال داده شد ولی در کد بازر به پایه A0 اتصال داده شده. 

گام دوم: نصب کتابخانه

  1. ابتدا برنامه Arduino IDE خود را باز کنید.
  2. سپس روی آیکون Library Manager در نوار کناری سمت چپ کلیک کنید.
  3. در کادر جستجو، عبارت “MAX3010x” را تایپ کنید تا نتایج مربوطه نمایش داده شوند.
  4. کتابخانه SparkFun MAX3010x Pulse and Proximity Sensor Library ساخته شرکت SparkFun Electronics را پیدا و نصب کنید.
  5. سپس کتابخانه “LiquidCrystal I2C” ساخته Frank de Brabander را پیدا و نصب کنید.


MAX30102 Library Installation

نصب کتابخانه MAX30102


LiquidCrystal I2C Library Installation

نصب کتابخانه LiquidCrystal I2C

گام سوم: کد تشخیص ضربان قلب

کد نمونه را بارگذاری کنید و با گذاشتن انگشت روی سنسور، ضربان قلب روی LCD نمایش داده می‌شود. توجه داشته باشید که انگشت باید ثابت باشد تا خوانش دقیق باشد.

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

MAX30105 particleSensor;
LiquidCrystal_I2C lcd(0x27, 16, 2);

#define IR_THRESHOLD 50000
#define TIMEOUT 1000  // میلی‌ثانیه

#if defined(__AVR_ATmega328P__) || defined(__AVR_ATmega168__)
uint16_t irBuffer[100];
uint16_t redBuffer[100];
#else
uint32_t irBuffer[100];
uint32_t redBuffer[100];
#endif

int32_t bufferLength = 100;
int32_t spo2, heartRate;
int8_t validSPO2, validHeartRate;

byte readLED = 13;

// فیلتر EMA برای smooth کردن داده‌ها
float emaHR = 0, emaSpO2 = 0;
float alpha = 0.3; // ضریب فیلتر نمایی

#define MAX_HR 150
#define MIN_HR 40
#define MAX_SPO2 99
#define MIN_SPO2 70

// --- تنظیمات آلارم ---
#define ALARM_PIN A0

#define HR_THRESHOLD 150           // اگر ضربان قلب بالاتر از این شد
#define HR_ALARM_DURATION 500     // میلی‌ثانیه (5 ثانیه)

#define SPO2_THRESHOLD 93          // اگر SpO2 کمتر از این شد
#define SPO2_ALARM_DURATION 500   // میلی‌ثانیه (4 ثانیه)

unsigned long hrAlarmStart = 0;
unsigned long spo2AlarmStart = 0;
bool hrAlarmActive = false;
bool spo2AlarmActive = false;

void setup() {
  Serial.begin(9600);
  pinMode(readLED, OUTPUT);
  pinMode(ALARM_PIN, OUTPUT);

  if (!particleSensor.begin(Wire, I2C_SPEED_FAST)) {
    Serial.println(F("MAX30105 not found."));
    while (1);
  }

  particleSensor.setup(60, 4, 2, 100, 411, 4096);

  lcd.init();
  lcd.backlight();
  lcd.clear();
  lcd.setCursor(0,0);
  lcd.print("Place finger");
}

void readInitialBuffer() {
  for (byte i = 0; i < bufferLength; i++) { unsigned long start = millis(); while (!particleSensor.available()) { particleSensor.check(); if (millis() - start > TIMEOUT) break;
    }

    redBuffer[i] = particleSensor.getRed();
    irBuffer[i] = particleSensor.getIR();
    particleSensor.nextSample();
  }
}

void loop() {
  if (particleSensor.check() && particleSensor.getIR() > IR_THRESHOLD) {
    lcd.clear();
    lcd.setCursor(0,0);
    lcd.print("Reading...");
    readInitialBuffer();

    maxim_heart_rate_and_oxygen_saturation(irBuffer, bufferLength, redBuffer, &spo2, &validSPO2, &heartRate, &validHeartRate);

    emaHR = validHeartRate ? heartRate : 0;
    emaSpO2 = validSPO2 ? spo2 : 0;

    while (particleSensor.getIR() > IR_THRESHOLD) {
      // شیفت داده‌ها برای buffer
      for (byte i = 25; i < 100; i++) {
        redBuffer[i - 25] = redBuffer[i];
        irBuffer[i - 25] = irBuffer[i];
      }

      for (byte i = 75; i < 100; i++) { unsigned long start = millis(); while (!particleSensor.available()) { particleSensor.check(); if (millis() - start > TIMEOUT) break;
        }

        digitalWrite(readLED, !digitalRead(readLED));

        redBuffer[i] = particleSensor.getRed();
        irBuffer[i] = particleSensor.getIR();
        particleSensor.nextSample();

        maxim_heart_rate_and_oxygen_saturation(irBuffer, bufferLength, redBuffer, &spo2, &validSPO2, &heartRate, &validHeartRate);

        // محدود کردن منطقی
        if(validHeartRate){
          if(heartRate > MAX_HR) heartRate = MAX_HR;
          if(heartRate < MIN_HR) heartRate = MIN_HR; } if(validSPO2){ if(spo2 > MAX_SPO2) spo2 = MAX_SPO2;
          if(spo2 < MIN_SPO2) spo2 = MIN_SPO2; } // فیلتر نمایی EMA if(validHeartRate) emaHR = alpha * heartRate + (1 - alpha) * emaHR; if(validSPO2) emaSpO2 = alpha * spo2 + (1 - alpha) * emaSpO2; // نمایش روی LCD lcd.setCursor(0,0); lcd.print("HR:"); if(emaHR > 0){
              if(emaHR < 100) lcd.print(" "); // اضافه کردن فضای خالی برای دو رقمی lcd.print((int)emaHR); } else lcd.print("--"); lcd.print(" SpO2:"); if(emaSpO2 > 0){
              if(emaSpO2 < 100) lcd.print(" "); // فضای خالی برای تک رقمی یا دو رقمی lcd.print((int)emaSpO2); } else lcd.print("--"); // --- بررسی آلارم‌ها --- unsigned long currentMillis = millis(); // ضربان قلب if(emaHR > HR_THRESHOLD){
          if(!hrAlarmActive){
            hrAlarmActive = true;
            hrAlarmStart = currentMillis;
            digitalWrite(ALARM_PIN, HIGH);
          }
        }

        if(hrAlarmActive && (currentMillis - hrAlarmStart >= HR_ALARM_DURATION)){
          hrAlarmActive = false;
          digitalWrite(ALARM_PIN, LOW);
        }

        // SpO2
        if(emaSpO2 < SPO2_THRESHOLD){ if(!spo2AlarmActive){ spo2AlarmActive = true; spo2AlarmStart = currentMillis; digitalWrite(ALARM_PIN, HIGH); } } if(spo2AlarmActive && (currentMillis - spo2AlarmStart >= SPO2_ALARM_DURATION)){
          spo2AlarmActive = false;
          digitalWrite(ALARM_PIN, LOW);
        }

        delay(300); // به‌روزرسانی آرام برای LCD
      }
    }

    lcd.clear();
    lcd.setCursor(0,0);
    lcd.print("Place finger");
  }
}

گام چهارم: کد تشخیص اکسیژن خون

برای تشخیص SpO₂، از همان کتابخانه‌ها استفاده می‌کنیم و مقادیر اکسیژن خون روی LCD نمایش داده می‌شوند. اگر سطح اکسیژن کمتر از حد استاندارد باشد، بازر هشدار فعال می‌شود.

برای تغییر مقادیر هشدار بازر و همچینین میزان طول زمانی این هشدا میتوانید در کد این موارد را تغییر دهید.

#define HR_THRESHOLD 150                         // اگر ضربان قلب بالاتر از این شد
#define HR_ALARM_DURATION 500               // میلی‌ثانیه (500 میلی ثانیه)

#define SPO2_THRESHOLD 93                      // اگر SpO2 کمتر از این شد
#define SPO2_ALARM_DURATION 700          // میلی‌ثانیه (700 میلی ثانیه)

برای مثال در این کد اگر ضربان قلب بالاتر از 150 باشد بازر ۵۰۰ میلی ثانیه بوق میزند. همچنین اگر میزان اکسیژن خون کمتر از 93 باشد نیز بازر ۷۰۰ میلی ثانیه بوق خواهد زد.

جمع‌بندی

در این مقاله، شما یاد گرفتید چگونه یک پالس‌اکسی‌متر خانگی با آردوینو و سنسور MAX30102 بسازید، قطعات لازم را بشناسید، سیم‌بندی کنید، کتابخانه‌ها را نصب کنید و کدهای ضربان قلب و اکسیژن خون را اجرا کنید. این پروژه ترکیبی از الکترونیک، برنامه‌نویسی و طراحی سیستم است و می‌تواند یک تجربه کاربردی و جذاب برای علاقه‌مندان به پزشکی‌الکترونیک باشد.

6 thoughts on “ساخت پالس‌اکسی‌متر خانگی با آردوینو و سنسور MAX30102

  1. کیمیا گفت:

    ممنون از اطلاعات مفیدتون. من ساختم یک نمونه با ESP32 خیلیم دقت خوبی داشت.

    1. admin گفت:

      سلام
      روزتون بخیر، ممنون از باز خورد مثبتتون.

  2. سینا گفت:

    ممنون از اموزش خوبتون

    1. admin گفت:

      سلام
      روزتون بخیر، خوشحالم که مفید بوده براتون.

  3. سمانه گفت:

    چیکار میتونم کنم که دقت اندازه گیریش بالاتر بره

    1. admin گفت:

      سلام وقت‌تون بخیر 🌸 اگر بتونین داخل یک محفظه با پوشش مشکی قرار بدین و طوری باشه که لرزش دست هم کمتر بشه دقتش خیلی بالاتر میره. برای دقت های خیلی بالاتر هم میتونید به لحاظ نرم افزاری با یک دستگاه دقیق کالیبره هم بکنید.

دیدگاهتان را بنویسید

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *