هدف ما از انجام این پروژه چیست؟

هدف این پروژه، راهاندازی و استفاده از ماژول بیوپتانسیل و ضربان قلب GebraBit MAX30101 با استفاده از برد Arduino UNO (یا بردهای سازگار) است. در این پروژه یاد میگیریم چگونه سنسور اپتیکال MAX30101 با تابش نور LEDهای قرمز/مادون قرمز به بافت بدن، تغییرات جریان خون را تشخیص داده و آن را به سیگنال الکتریکی قابل اندازهگیری تبدیل میکند.
با استفاده از کتابخانهی MAX30100_PulseOximeter (یا نسخهی اصلاحشده برای MAX30101) ضربان قلب (Heart Rate) و سطح اکسیژن خون (SpO2) در هر دقیقه محاسبه شده و به صورت عددی در Serial Monitor نمایش داده میشود. همچنین در طی این پروژه، مفاهیم مهمی مثل رابط I²C، نرخ نمونهبرداری، تنظیم جریان LED، تشخیص ضربان (Beat Detection) را مرور میکنیم.
در این آموزش چه چیزهایی یاد میگیریم؟
در این پروژه با مفاهیم و مهارتهای زیر آشنا میشویم:
- آشنایی با نحوه کار سنسور اپتیکال MAX30101 و اصول اندازهگیری ضربان قلب و SpO2 با استفاده از نور بازتابی از پوست.
- نحوهی اتصال ماژول GebraBit MAX30101 به Arduino از طریق رابط I²C (پینهای SDA و SCL).
- استفاده از کتابخانهی MAX30100.h و کلاس PulseOximeter برای راهاندازی سریع سنسور و محاسبهی خودکار HR و SpO2.
- تنظیم جریان LED مادون قرمز (IR LED Current) از طریق تابع setIRLedCurrent() برای رسیدن به سیگنال مناسب متناسب با نوع بافت و فاصلهی سنسور تا پوست.
- استفاده از یک کالبک (Callback) برای تشخیص هر ضربان قلب و چاپ پیام “♥ Beat!” در لحظهی تشخیص.
- خواندن و نمایش ضربان قلب (bpm) و درصد اکسیژن خون (%SpO2) در یک بازهی زمانی مشخص (هر ۱ ثانیه) با استفاده از تابع millis().
- آشنایی با مفاهیم پردازش سیگنال در سطح کتابخانه مثل:
- حذف مولفهی DC سیگنال با DCRemover
- فیلتر پایینگذر با FilterBuLp1
- تشخیص ضربان با MAX30100_BeatDetector
- تخمین SpO2 با MAX30100_SpO2Calculator
برای شروع این پروژه به چه چیزهایی نیاز داریم؟
برای اجرای این پروژه به سختافزار و نرمافزار نیاز داریم. عناوین این سختافزارها و نرمافزارها در جدول زیر به شما ارائه شده است و میتوانید با کلیک بر روی هر یک، آن را تهیه/دانلود کرده و برای شروع آماده شوید.
| سختافزارهای مورد نیاز | نرمافزارهای مورد نیاز |
| برد Arduino UNO (یا Nano / Mega سازگار) | Arduino IDE |
| ماژول بیوپتانسیل و ضربان قلب GebraBit MAX30101 | درایور USB برد آردوینو (CH340 یا مشابه) |
| کابل USB Type-A به Type-B یا Micro/Type-C | کتابخانه MAX30100 / PulseOximeter برای Arduino |
| سیم جامپر (M–F) یا بردبورد برای اتصال I²C |
ابتدا مانند تصویر زیر ماژول ضربان قلب GebraBit MAX30101 را به صورت زیر به آردوینو متصل می کنیم:

پس از اتصال آردوینو به ماژول ، کتابخانه MAX30101 دانلود و به نرم افزار آردوینو اضافه و برنامه پیوست را اجرا کنید.
سورس کد
توضیح فایل MAX30100_PulseOximeter.h
ثابتهای تنظیمات
#define SAMPLING_FREQUENCY 100
#define CURRENT_ADJUSTMENT_PERIOD_MS 500
#define DEFAULT_IR_LED_CURRENT MAX30100_LED_CURR_50MA
#define RED_LED_CURRENT_START MAX30100_LED_CURR_27_1MA
#define DC_REMOVER_ALPHA 0.95
SAMPLING_FREQUENCY: فرکانس نمونهبرداری داخلی سنسور (به Hz).
CURRENT_ADJUSTMENT_PERIOD_MS: هر چند میلیثانیه یکبار جریان LED برای رسیدن به سیگنال مناسب تنظیم شود.
DEFAULT_IR_LED_CURRENT: جریان پیشفرض LED مادون قرمز.
RED_LED_CURRENT_START: جریان شروع برای LED قرمز.
DC_REMOVER_ALPHA: ضریب فیلتر برای حذف مولفهی DC سیگنال (نزدیک ۱ یعنی فیلتر نرم و کند).
کتابخانههای وابسته
#include "MAX30100.h"
#include "MAX30100_BeatDetector.h"
#include "MAX30100_Filters.h"
#include "MAX30100_SpO2Calculator.h"
این فایلها کلاسهای زیر را فراهم میکنند:
- MAX30100: برای ارتباط مستقیم با رجیسترهای سختافزار سنسور.
- MAX30100_BeatDetector: برای تشخیص قلهها و فواصل زمانی بین ضربانها.
- MAX30100_Filters: برای اعمال فیلترهای سیگنال روی دادهی خام نوری.
- MAX30100_SpO2Calculator: برای محاسبهی SpO2 بر اساس نسبت سیگنالهای قرمز و IR.
حالتهای کاری و دیباگ
typedef enum PulseOximeterState {
PULSEOXIMETER_STATE_INIT,
PULSEOXIMETER_STATE_IDLE,
PULSEOXIMETER_STATE_DETECTING
} PulseOximeterState;
- INIT: سنسور در حال مقداردهی اولیه است.
- IDLE: سنسور آماده است ولی هنوز ضربان معناداری تشخیص نداده.
- DETECTING: در حال تشخیص و پیگیری ضربانهای متوالی.
typedef enum PulseOximeterDebuggingMode {
PULSEOXIMETER_DEBUGGINGMODE_NONE,
PULSEOXIMETER_DEBUGGINGMODE_RAW_VALUES,
PULSEOXIMETER_DEBUGGINGMODE_AC_VALUES,
PULSEOXIMETER_DEBUGGINGMODE_PULSEDETECT
} PulseOximeterDebuggingMode;
امکان انتخاب مدهای دیباگ برای چاپ دادهی خام، دادهی AC، یا اطلاعات تشخیص ضربان.
رابط عمومی کلاس PulseOximeter
class PulseOximeter {
public:
PulseOximeter();
bool begin(PulseOximeterDebuggingMode debuggingMode_=PULSEOXIMETER_DEBUGGINGMODE_NONE);
void update();
float getHeartRate();
uint8_t getSpO2();
uint8_t getRedLedCurrentBias();
void setOnBeatDetectedCallback(void (*cb)());
void setIRLedCurrent(LEDCurrent irLedCurrent);
void shutdown();
void resume();
- begin(): راهاندازی سنسور، چک کردن ID و تنظیم رجیسترها.
- update(): خواندن نمونهی جدید، اعمال فیلتر و بهروزرسانی HR/SpO2، تشخیص ضربان.
- getHeartRate(): دریافت مقدار HR.
- getSpO2(): دریافت مقدار SpO2.
- getRedLedCurrentBias(): مقدار بایاس جریان LED قرمز را برمیگرداند.
- setOnBeatDetectedCallback(): ثبت تابع کالبک برای تشخیص ضربان.
- setIRLedCurrent(): تنظیم جریان LED IR (همان تابعی که در setup() استفاده کردیم).
- shutdown() / resume(): خاموش و روشن کردن سنسور برای کاهش مصرف توان.
بخش private شامل متغیرهایی است که برای نگهداری وضعیت، زمانبندی ضربانها، فیلترهای DC و پایینگذر و شیء MAX30100 hrm; استفاده میشود و معمولاً نیازی به تغییر توسط کاربر ندارند.
فایل برنامهی اصلی آردوینو (Sketch)
تعریف کتابخانهها و ثابتها
#include <Wire.h>
#include "MAX30100_PulseOximeter.h"
#define REPORTING_PERIOD_MS 1000
Wire.h: کتابخانهی استاندارد آردوینو برای برقراری ارتباط I²C است که برای صحبتکردن با MAX30101 استفاده میشود.
“MAX30100_PulseOximeter.h”: هدر کتابخانهی پالساکسیمتر که کلاس PulseOximeter را در اختیار ما قرار میدهد.
REPORTING_PERIOD_MS: بازهی زمانی گزارشگیری از مقادیر ضربان قلب و SpO2 است. مقدار 1000 یعنی هر ۱ ثانیه یک بار مقادیر جدید چاپ شوند.
ایجاد شیء PulseOximeter و متغیرهای زمانی
PulseOximeter pox;
uint32_t tsLastReport = 0;
PulseOximeter pox;: یک شیء از کلاس PulseOximeter میسازیم که تمام کارهای راهاندازی، خواندن سنسور، فیلتر، تشخیص ضربان و محاسبه HR/SpO2 را انجام میدهد.
tsLastReport: زمان آخرین باری که مقادیر چاپ شدهاند، برای مقایسه با millis() استفاده میشود تا هر ثانیه یک بار خروجی بدهیم.
تابع کالبک تشخیص ضربان
# void onBeatDetected() {
Serial.println("♥ Beat!");
}
این تابع هر بار که کتابخانه تشخیص دهد یک ضربان قلب کامل اتفاق افتاده، توسط سنسور فراخوانی میشود.
تنها کاری که انجام میدهد چاپ رشتهی “♥ Beat!” روی Serial Monitor است تا کاربر در همان لحظهی ضربان، آن را ببیند.
این تابع بهعنوان callback بعداً به سنسور معرفی میشود:
pox.setOnBeatDetectedCallback(onBeatDetected);
تابع setup() – راهاندازی اولیه
void setup() {
Serial.begin(9600);
Serial.print("Initializing pulse oximeter.."); #define BH1790_PRM_CTRL2_CUR (4U)
Serial.begin(9600);: راهاندازی ارتباط سریال با سرعت 9600 بیت بر ثانیه برای نمایش متن و دادهها.
چاپ پیام اولیه برای اطلاع کاربر از شروع پروسهی راهاندازی.
if (!pox.begin()) {
Serial.println("FAILED");
for(;;);
} else {
Serial.println("SUCCESS");
}
pox.begin(): تلاش برای راهاندازی سنسور از طریق I²C، چک کردن اینکه سنسور در باس I²C وجود دارد و تنظیم رجیسترهای اولیه.
اگر begin() مقدار false برگرداند، یعنی سنسور پیدا نشده یا خطای راهاندازی وجود دارد؛ در این صورت “FAILED” چاپ میشود و برنامه در یک حلقهی بینهایت (for(;;);) متوقف میشود تا کاربر مشکل سختافزاری را برطرف کند.
در صورت موفقیت “SUCCESS” چاپ میشود.
// Configure sensor to use 7.6mA for LED drive
pox.setIRLedCurrent(MAX30100_LED_CURR_7_6MA);
با setIRLedCurrent() جریان LED مادون قرمز تنظیم میشود؛ مقدار MAX30100_LED_CURR_7_6MA یعنی حدود ۷٫۶ میلیآمپر.
این پارامتر روی شدت سیگنال اپتیکال و در نتیجه کیفیت سیگنال ضربان تأثیر مستقیم دارد (بسته به ضخامت پوست، فاصله سنسور و مصرف توان ممکن است این مقدار نیاز به تنظیم داشته باشد).
// Register a callback routine
pox.setOnBeatDetectedCallback(onBeatDetected);
}
این خط تابع onBeatDetected را بهعنوان کالبک تشخیص ضربان ثبت میکند.
از این لحظه به بعد، هر زمان کتابخانه ضربان را تشخیص دهد، بهطور خودکار onBeatDetected() را صدا میزند.
تابع loop() – خواندن مداوم از سنسور
void loop() {
// Read from the sensor
pox.update();
در هر بار اجرای loop() باید تابع pox.update() فراخوانی شود تا کتابخانه:
- دادههای جدید را از MAX30101 بخواند،
- فیلترها را اعمال کند،
- ضربانها را تشخیص دهد،
- HR و SpO2 را بهروز کند.
// Grab the updated heart rate and SpO2 levels
if (millis() - tsLastReport > REPORTING_PERIOD_MS) {
Serial.print("Heart rate:");
Serial.print(pox.getHeartRate());
Serial.print("bpm / SpO2:");
Serial.print(pox.getSpO2());
Serial.println("%");
tsLastReport = millis();
}
}
جمعبندی کاربردی
- با استفاده از millis() چک میشود اگر بیش از REPORTING_PERIOD_MS (یعنی 1000ms = 1s) از آخرین گزارش گذشته باشد، زمان چاپ مقادیر جدید رسیده است.
- pox.getHeartRate(): مقدار ضربان قلب را برحسب ضربه در دقیقه (bpm) برمیگرداند.
- pox.getSpO2(): مقدار سطح اکسیژن خون را بر حسب درصد (%) محاسبه و برمیگرداند.
- در پایان، tsLastReport به زمان فعلی millis() بهروزرسانی میشود تا یک ثانیهی جدید شمرده شود.
اجرای کد
آردوینو خود را به کامپیوتر متصل کنید و مدل و پورت آردوینو خود را انتخاب کنید. سپس نمونه کد را ابتدا Verify و سپس Upload کنید . بعد از Upload کردن کد Serial Monitor را باز کرده و می توانید خروجی های سنسور را مشاهده کنید .
