Arduino ve pulse sensör nabız okuma sorunu ?

Başlatan eml581, 16 Nisan 2016, 00:14:07

eml581

arkadslar pulse sensör ile nabız okumaya caluşıyorum ama sabit bi değere ulaşamıyoum sürekli salınım halinde gercege yakın bir deger göremedim daha kullananan varı hiç bu sensörden ?

int pulsePin = 0; //0. pin pulsepin e atandı
int blinkPin = 13; // 13. pin atama işlemi
/*
 * kodlarda volatile tanımlayıcısının kullanılmasının sebebi yapılan okuma yazma işlemlerinde optimize edilmesini sağlamaktır.
 * Interrupt işleminde değiştirilen bir alan kesme dışındaki kodda okunuyorsa (ya da tam tersi) söz konusu 
 * alanın değeri programın çalışması süresince her an değişebilir. Derleyici bundan haberdar olmadığı için bir kere değeri 
 * okuyup/yazdıktan sonra tekrar aynı işlemi yapmayabilir. Bu gibi durumlarda bu yüzden volatilenin kullanılması gerekir. 
 */

volatile int BPM;   // nabız değişkeni tanımlandı
volatile int Signal; // ham değeri alan değişken tanımlandı
volatile int IBI = 600; // atım arasındaki aralık
volatile boolean Pulse = false; //pulse sensörü high olduğunda bu değer true olur
volatile boolean QS = false; // arduino nabzı bulduğunda true olur

void setup(){
  Serial.begin(9600); // serial haberleşme başlatıldı.
interruptSetup(); // her 2 milisaniyede nabız değeri okuyan interrupt
}

void loop(){
  if (QS == true) { // nabız bulunduğunda
       Serial.println(BPM); // nabzı serial monitöre yazdır 
    QS = false;  // bir sonraki nabza kadar hiçbir veri göndermemesi için false yapılır.                     
   }
}


ınterupt
volatile int rate[10];                    // 10 IBI değerini tutması için tanımlandı 
volatile unsigned long sampleCounter = 0;          // nabız süresinin hesaplanması için 
volatile unsigned long lastBeatTime = 0;           // IBI değerinin bulunması için 
volatile int P =512;                      //nabız dalgasının tepe değerinin bulunmasında kullanılır. 
volatile int T = 512;                     // nabız dalgasının çukur değerinin bulunmasında kullanılır. 
volatile int thresh = 512;                // kal atışı anını bulmada
volatile int amp = 100;                   // nabzın dalga genliğini bulmada
volatile boolean firstBeat = true;        // 
volatile boolean secondBeat = false;      // 


void interruptSetup(){     
  // timer 2 nin her 2 milisaniyede çalışmasını sağlar 
  TCCR2A = 0x02;     // 
  TCCR2B = 0x06;     // 
  OCR2A = 0X7C;      // 
  TIMSK2 = 0x02;     // 
  sei();             // interrup ı başlatır     
} 


 
//2 her iki milisaniyede çalışır
ISR(TIMER2_COMPA_vect){                         // triggered when Timer2 counts to 124
  cli();                                      // interrupt kapatılır
  Signal = analogRead(pulsePin);              // pulse sensör okunur
  sampleCounter += 3;                         // zaman takibi için
  int N = sampleCounter - lastBeatTime;       // ekran zamanı, gürültüleri önlemek için

    // nabız dalgasının tepe ve çukur değeri bulunur
  if(Signal < thresh && N > (IBI/5)*3){       // gürültüyü önlemek için IBI nin  3/5 i kadar bekler 
    if (Signal < T){                        // signal çukur değerinden küçükse
      T = Signal;                         // nabız dalgasının çukur değeri atanır 
    }
  }

  if(Signal > thresh && Signal > P){          // gürültüyü önlemede yardımcı
    P = Signal;                             // tepe değeri atanır
  }                                        // 

  //  kalp atışı hesapları
  // signal değerinde darbe olduğu zaman
  if (N > 250){                                   // gürültüyü önlemede yardımcı
    if ( (Signal > thresh) && (Pulse == false) && (N > (IBI/5)*3) ){        
      Pulse = true;                               // nabız değerinin olduğu varsayıldı
      digitalWrite(blinkPin,HIGH);                // 13. pini high yap
      IBI = sampleCounter - lastBeatTime;         // kalp atışları arasındaki zamanı milisaniye cinsinden ölçer
      lastBeatTime = sampleCounter;               // bir sonraki nabızlar arasındaki zamanı ölçebilmek için 

      if(secondBeat){                        // ikinci atış if koşulu ile başlatılır 
        secondBeat = false;                  // 
        for(int i=0; i<=9; i++){             // IBI değerleri toplanır gerçekçi BPM değeri için 
          rate[i] = IBI;                      
        }
      }

      if(firstBeat){                         // ilk atış if koşulu ile başlatılır 
        firstBeat = false;                   // 
        secondBeat = true;                   // 
        sei();                               //  interrupt aktif edilir 
        return;                              // IBI değeri güvenilmez, bu yüzden atılır 
      }   


      // son 10 IBI değeri runningTotal değerine atılır 
      word runningTotal = 0;                  // clear the runningTotal variable    

      for(int i=0; i<=8; i++){                // 
        rate[i] = rate[i+1];                  // eski IBI değeri bırakıldı
        runningTotal += rate[i];              // 9 değer atandı 
      }

      rate[9] = IBI;                          // son IBI değeri 9. indise atandı 
      runningTotal += rate[9];                // runningTotal değeri sürekli güncellenmiş olur, son değer atandı 
      runningTotal /= 10;                     // son 10 IBI değerinin ortalaması alındı
      BPM = 60000/runningTotal;               // dakikadaki atış sayısı hesabı. 60 saniye bir atış için geçen süreye bölünerek dakikadaki atış sayısı bulunur. 
      QS = true;                              // nabız değeri bulundu 
      // 
    }                       
  }

  if (Signal < thresh && Pulse == true){   // signal aşağıya düşmeye başladığı zaman atış biter 
    digitalWrite(blinkPin,LOW);            // 13. pin low yapılır
    Pulse = false;                         // 
    amp = P - T;                           //  nabzın genliği hesaplanır 
    thresh = amp/2 + T;                    // tresh değerine genliğin yarısı eklenir
    P = thresh;                            // gelecek işlemler için tepe ve çukur değerleri sıfırlanır 
    T = thresh;
  }

  if (N > 2500){                           // eğer 2.5 saniye atış olmaz ise 
    thresh = 512;                          //  thresh default olur 
    P = 512;                               //  P default olur
    T = 512;                               //  T default olur
    lastBeatTime = sampleCounter;          //  the lastBeatTime güncellenir    
    firstBeat = true;                      // gürültüyü önlemek için 
    secondBeat = false;                    // 
  }

  sei();                                   // işlemler bittiğinde interrupt ı aktif et
}// end isr

cnk


usahin

Merhaba,

Kodlarınızı incelemedim ancak aynı problemi sensörü parmağıma takabileceğim bir fixtür yaparak çözdüm. MAXREFDES117# yani MAX30102 kullanıyorum. Parmağım ile sensöre sabit basınç uygulayamadığım için PPG sinyali üstünde düşük frekanslı bi AC gürültü oluşuyordu. Bu da hesap kitap işlerini karıştırıyordu.  Sensöre fazla basınç uygulamanız da kan akışını yavaşlatacağı/durduracağı için ölçümü yanıltır. Umarım yardımcı olmuşumdur. İyi çalışmalar.

OptimusPrime

Isaretin tepesi cukuru ortalaması 5 e bol 3le carp bunlara gerek yok. Bu isaretin icinde dusuk frekanslı ac bir bilesen vardır. Dijital bir filtre ile suzerseniz ip gibi sonuc cikar. He yetmezse buda ortanca veya ortalama eklenebilir. Aksi durumda uğraşıp durursunuz
https://donanimveyazilim.wordpress.com || Cihân-ârâ cihân içredir ârâyı bilmezler, O mâhîler ki deryâ içredir deryâyı bilmezler ||

cnk

Alıntı yapılan: OptimusPrime - 28 Şubat 2018, 10:06:19
Isaretin tepesi cukuru ortalaması 5 e bol 3le carp bunlara gerek yok. Bu isaretin icinde dusuk frekanslı ac bir bilesen vardır. Dijital bir filtre ile suzerseniz ip gibi sonuc cikar. He yetmezse buda ortanca veya ortalama eklenebilir. Aksi durumda uğraşıp durursunuz

Ancak direkt olarak verdiği değerleri kullanamıyoruz.Verdiği analog değerleri grafiğe dökünce bir dalga oluşuyor.O yüzden tepe çukur sayılarak nabız hesaplanmaya çalışılıyor.Siz bu gelen analog verilerin tam olarak nasıl kullanılacağını düşünüyorsunuz?