Arduino ile MAX30100 Kalp Nabız Sensörü Kullanımı

Arduino ile MAX30100 Kalp Nabız Sensörü Kullanımı

Arduino ile medikal sensor uygulamaları geliştirmek, akıllı giyilebilir sağlık cihazlarının çalışma dinamiklerini anlamak için mükemmel bir yöntemdir. Bu yazımızda, dijital nabız ve kandaki oksijen satürasyonu (SpO2) ölçümlerinde yaygın olarak tercih edilen MAX30100 Kalp Nabız Sensörü‘nü inceleyeceğiz. Piyasadaki MAX30100 modüllerinin (özellikle RCWL-0530) barındırdığı kritik donanım tasarım hatalarını, bu hataları fiziksel olarak nasıl düzeltebileceğinizi, kararlı I2C veri transferi sağlamayı ve Arduino ile kesintisiz çalışan uygulamaları tüm mühendislik detaylarıyla ele alıyoruz.

Alternatif biyomedikal nabız sensörü rehberlerimiz:

MAX30100 Nasıl Çalışır?

MAX30100, optik tabanlı bir Fotopletismografi (PPG) sensörüdür. Bünyesinde iki adet ışık yayan diyot (LED) ve bir adet hassas fotodedektör barındırır. LED’lerden biri Kırmızı ışık (660 nm), diğeri ise Kızılötesi ışık (880 nm) yayar.

Kalbin kasılıp gevşemesi (kardiyak siklus) sırasında parmak dokumuzdaki kılcal damarlardan geçen kan hacmi dinamik olarak dalgalanır:

  • Oksijenli Hemoglobin (O2Hb): Kızılötesi (IR) ışığı yüksek oranda absorbe eder (emer), kırmızı ışığı ise geçirir.
  • Oksijensiz Hemoglobin (HHb): Kırmızı ışığı yüksek oranda absorbe eder, kızılötesi ışığı geçirir.

Kalp her attığında parmaktaki temiz kan miktarı anlık olarak artar ve bu durum kızılötesi ışığın emilimini tepe noktasına ulaştırır. Sensör, bu emilim dalgalanmalarını okuyarak dahili ADC birimi aracılığıyla dijital verilere dönüştürür. Veriler Arduino I2C Haberleşme Protokolü veri hattı üzerinden okunmak üzere cihazın dahili 16-örneklik FIFO (First-In-First-Out) belleğinde depolanır.

MAX30100 Modül Çeşitleri ve Donanım Bağlantısı

Piyasada iki popüler MAX30100 kart tasarımı bulunur: Sorunsuz çalışan GY-MAX30100 ve hatalı tasarıma sahip yeşil renkli RCWL-0530.

GY-MAX30100 Sensör Modülü
GY-MAX30100 modülü

1. Standart GY-MAX30100 Modülü

GY-MAX30100 kartı, dahili regülatörleri ve 3.3V seviyesindeki I2C hatları ile doğrudan Arduino Uno ve Nano ile kullanıma hazırdır. Aşağıdaki standart kablo şemasını takip ederek doğrudan bağlayabilirsiniz:

GY-MAX30100 ModülüArduino Uno PinAçıklama
VIN5V veya 3.3VPozitif Güç Girişi
GNDGNDOrtak Toprak Hattı
SCLA5 / SCLI2C Saat Hattı
SDAA4 / SDAI2C Veri Hattı
INTD2Donanımsal Kesme Çıkışı

Bu bağlantının ardından xcoder123 MAX30100 Kütüphanesi GitHub Deposu yazılımını indirerek temel okuma işlemlerini gerçekleştirebilirsiniz.

2. Problemli RCWL-0530 Modülü ve Çözüm Yöntemi

Eğer elinizdeki yeşil renkli, üzerinde RCWL-0530 yazan ucuz modül bulunuyorsa, Arduino ile doğrudan bağladığınızda I2C hattının tamamen kilitlendiğini veya veri alınamadığını göreceksiniz. Bunun sebebi ciddi bir donanımsal tasarım hatasıdır.

RCWL-0530 MAX30100 Hatalı Kart Tasarımı
Tasarım hatası barındıran RCWL-0530 modülü

Modül şemasını incelediğimizde, I2C veri (SDA), saat (SCL) ve kesme (INT) sinyal hatlarındaki 4.7kΩ pull-up (çekme) dirençlerinin, entegrenin dahili 1.8V voltaj regülatör çıkışına bağlı olduğunu görüyoruz:

RCWL-0530 Şematik Hata Detayı
1.8V regülatörüne bağlanan I2C pull-up hatları

Mühendislik Analizi: 5V ile çalışan Arduino Uno (ATmega328P), giriş pinlerinde 3.0V ($0.6 \times V_{CC}$) altındaki voltajları “Lojik HIGH” olarak tanıyamaz. Hatlar 1.8V’a çekildiğinde Arduino hattı sürekli lojik sıfır algılar ve haberleşme anında kesilir.

Fiziksel Çözüm: Kartın arka kısmında bulunan üç adet 4.7kΩ pull-up direncini (aşağıdaki resimde işaretli olan 3’lü direnç bloğu) havya yardımıyla yerinden sökün:

Kart Üzerinde Sökülmesi Gereken Direnç Bloğu
Sökülmesi gereken 3’lü direnç paketi

Dirençleri söktükten sonra modülün lojik hatları tamamen boşa çıkacaktır:

Dirençleri Sökülmüş RCWL-0530 Modülü
Modifikasyon sonrası temizlenmiş kart yüzeyi

Şimdi harici olarak üç adet 4.7kΩ direnci, I2C hatlarından (SDA, SCL) ve harici kesme hattından (INT) Arduino’nun 3.3V pinine bağlayarak hattı güvenli seviyeye çekin. Aşağıdaki modifiyeli bağlantı şemasını uygulayın:

Modifiye Edilmiş MAX30100 Donanım Bağlantısı
3.3V hattına harici dirençlerle çekilmiş I2C bağlantısı

Arduino Kodlama Uygulamaları

MAX30100 sensörüyle kararlı ölçümler yapabilmek için oxullo tarafından geliştirilen popüler ve güçlü oxullo Arduino-MAX30100 Kütüphanesi Resmi Deposu kütüphanesini kullanacağız. Kitaplığı Arduino Kütüphane Yöneticisi üzerinden MAX30100 yazarak kurabilirsiniz.

Uygulama 1: Seri Port Üzerinden Nabız ve Oksijen Seviyesi İzleme

// MAX30100 Temel Seri Okuma Kodu
#include <Wire.h>
#include "MAX30100_PulseOximeter.h"

#define REPORTING_PERIOD_MS 1000

PulseOximeter pox;
uint32_t tsLastReport = 0;

// Kalp atışı algılandığında tetiklenecek geri çağrım (callback) fonksiyonu
void onBeatDetected() {
    Serial.println("♥ Kalp Atışı Algılandı!");
}

void setup() {
    Serial.begin(115200);
    Serial.print("MAX30100 Baslatiliyor...");

    if (!pox.begin()) {
        Serial.println("FAILED");
        while(1);
    } else {
        Serial.println("SUCCESS");
    }

    // Kızılötesi LED akımını güç kaynaklarını yormayacak kararlı bir değere (7.6mA) ayarlıyoruz
    pox.setIRLedCurrent(MAX30100_LED_CURR_7_6MA);

    // Kalp atış geri bildirimi için callback ataması
    pox.setOnBeatDetectedCallback(onBeatDetected);
}

void loop() {
    // FIFO tamponunu doldurmak ve sinyal filtrelerini çalıştırmak için 
    // pox.update() fonksiyonu döngüde kesintisiz ve olabildiğince hızlı çağrılmalıdır.
    pox.update();

    // delay() kullanmadan zaman kontrolü yapıyoruz (Non-blocking)
    if (millis() - tsLastReport > REPORTING_PERIOD_MS) {
        Serial.print("Nabiz: ");
        Serial.print(pox.getHeartRate());
        Serial.print(" BPM | SpO2: ");
        Serial.print(pox.getSpO2());
        Serial.println(" %");

        tsLastReport = millis();
    }
}

Uygulama 2: Gecikmesiz Tasarımla I2C LCD Ekran Entegrasyonu

Önemli Mühendislik Hatası: Geliştiriciler LCD ekrana veri yazdırırken sık sık delay(500) veya delay(1000) gibi bloklayıcı komutlar kullanır. Ancak MAX30100 kütüphanesinin dahili DC filtreleri ve FIR filtre katsayıları, pox.update() fonksiyonunun en fazla 10 ms aralıklarla çalışmasını şart koşar. Eğer döngü bloklanırsa, FIFO taşar ve nabız tespiti tamamen başarısız olur.

Bu sebeple, 16×2 I2C LCD ekran entegrasyonunda millis() tabanlı durum makineleri kullanarak sistemin kesintisiz akmasını sağlıyoruz:

MAX30100 ve 16x2 I2C LCD Ekran Bağlantısı
I2C veri yolu üzerinden LCD ve MAX30100 eş zamanlı çalışması
// Gecikmesiz MAX30100 ve I2C LCD Ekran Kodu
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include "MAX30100_PulseOximeter.h"

PulseOximeter pox;
LiquidCrystal_I2C lcd(0x27, 16, 2); // LCD I2C adresi ve boyutları

uint32_t tsLastReport = 0;
const uint32_t REPORTING_PERIOD_MS = 1000;

void onBeatDetected() {
    // Kalp sembolü yakma veya anlık tetikleme işlemleri buraya yazılabilir
}

void setup() {
    lcd.init();
    lcd.backlight();
    lcd.setCursor(0, 0);
    lcd.print("MAX30100 Init...");

    if (!pox.begin()) {
        lcd.setCursor(0, 1);
        lcd.print("FAILED!          ");
        while(1);
    } else {
        lcd.setCursor(0, 1);
        lcd.print("SUCCESS          ");
        delay(1000);
    }

    pox.setIRLedCurrent(MAX30100_LED_CURR_7_6MA);
    pox.setOnBeatDetectedCallback(onBeatDetected);
    
    lcd.clear();
}

void loop() {
    // Sensörü en yüksek hızda pollemeye (sorgulamaya) devam ediyoruz
    pox.update();

    // LCD ekran güncellemesini her 1 saniyede bir bloklama yapmadan yürütüyoruz
    if (millis() - tsLastReport > REPORTING_PERIOD_MS) {
        float bpm = pox.getHeartRate();
        uint8_t spo2 = pox.getSpO2();

        lcd.setCursor(0, 0);
        lcd.print("Nabiz: ");
        if (bpm > 0) {
            lcd.print((int)bpm);
            lcd.print(" BPM   ");
        } else {
            lcd.print("Okunuyor...");
        }

        lcd.setCursor(0, 1);
        lcd.print("SpO2 : ");
        if (spo2 > 0) {
            lcd.print(spo2);
            lcd.print(" %     ");
        } else {
            lcd.print("Bekleniyor..");
        }

        tsLastReport = millis();
    }
}

Bu kod mimarisinde, LCD ekrana veri gönderme yükü sadece saniyede bir kez mikrosaniyeler mertebesinde gerçekleşir, böylece pox.update() fonksiyonunun çalışma frekansı neredeyse hiç etkilenmez.

MAX30100 entegresinin sinyal entegrasyonu, modifikasyon teknikleri veya yazılımsal optimizasyon adımları hakkında sorularınızı alt kısımdaki yorum alanından bizimle paylaşabilirsiniz.

Yorum yapma özelliği, forum tarafından gelen istek sebebiyle kapatılmıştır. Lütfen tartışmalar ve sorularınız için topluluk forumumuza katılın.