Deneyap Kart

Oluşturulma Tarihi: 2022-02-09 15:29:21

KY-039 Nabız Ölçer

KY-039 Nabız Sensörü uygulamalarına ait şema ve kodlara bu dokümanda yer verilmiştir.

  • Proje Numarası :#152189
  • Deneyap Kart  Adet: 1

  • Nabız Ölçer  Adet: 1

    KY-039

  • Ekran  Adet: 1

    128x64 0.96 inch OLED Grafik LCD Ekran - SSD1306 - 4 Pin I2C

  • Breadboard  Adet: 1

  • Jumper Kablo  Adet: 7

    M-M

  • Arduino IDE  Adet: 1

Proje Akışı

Deneyap Kart kullanarak KY-039 Nabız Sensörü uygulamalarına ait şema ve kodlara bu dokümanda yer verilmiştir. Bu proje Deneyap Kart ile gerçekleştirilebilecek giriş uygulamalarından birisidir ve ekipmanlar listesinde yer alan gereksinimler karşılanmalıdır. Uygulama adımları örnek kodlar ile açıklanmıştır ve nihai kod dokümanın sonunda yer almaktadır.
 

Bu Proje Hakkında

Deneyap Kartta, 12-bit çözünürlüğe sahip analog dijital dönüştürücü (ADC – analog to digital converter) bulunmaktadır. (Deneyap Mini için 13-bit) 12-bit ADC, Deneyap Kartta 0V ile 3.3V arası gerilimleri 2^12 = 4096 birim hassasiyetle okuyabilir. Yani analog giriş pinlerinden birine vereceğimiz 0V gerilim bize 0 değerini; aynı şekilde 3.3V gerilim ise 4095 değerini verecektir. Bir potansiyometre kullanarak bu verileri elde edebilir ve seri port ekranında gösterebiliriz. Bu proje için potansiyometre gerekli değildir. Bu bilgiler nabız sensöründen verilerin işlenmesi aşamasında kullanılarak nabız ölçümü gerçekleştirilecektir.

En çok kullanılan sensörlerin bulunduğu 37 sensörlük bir sette nabız sensörü bulunmaktadır. Bu isim çok şey vaat ediyor. İnsanlar, I2C veya benzeri bir şey aracılığıyla kalp atış hızını belirten dijital bir sayı sağladığını düşünme eğilimindedir. Aslında bu sensörün sağladığı şey, ışık sensörünün ne kadar kızılötesi ışık aldığını veya aslında ışık sensörünü bir cismin ne kadar gölgelediğini söyleyen 0 ile 4095 (geliştirme kartlarının ADC çözünürlüğüne bağlı olarak değişebilir) arasında bir "analog" değerdir. Değer ne kadar yüksek olursa, kızılötesi ışık o kadar az olur.

Kısacası: parmağınızı IR LED ile sensörün ışık transistörü arasına yerleştirin. Kalp atışınız, parmağınızdaki kan damarlarını genişletecek ve bu da IR'yi filtreleyecektir. Bu, titreşimli bir sinyal oluşturur.

Bu projede, bu sinyalin nasıl 66 BPM (dakikadaki atım sayısı) gibi bir kalp atış hızına dönüştürüldüğünü anlatıyoruz.

Basit Adımlar


 

KY-039 sensöründen sadece değerleri okuyup çizerseniz, şöyle bir şey elde edersiniz:

 

NOT: Grafikteki değerler bulunduğunuz ortama göre değişebilir. Sensör çeşitli ışık kaynaklarından ve ölçüm esnasındaki hareketlerden etkilenmektedir.

 

 

Bu çizim üzerinden oluşan grafiğin çok doğru olmadığını fark edebilirsiniz. Bunun yerine bir grup verinin ortalamasını hesaplayın ve ortalamayı çizin. Sonuç bu şekilde olacaktır:

 

 

Burada kalbin nabzını zaten görebilirsiniz. Nabzın her tepe noktası arasındaki zaman farkını alın. Bundan dakikadaki kalp atış hızını hesaplayabilirsiniz.

 

Yukarıdaki resimdeki küçük zikzak deseni, 50 Hz'lik yapay ışıktan kaynaklanmaktadır, bu da uğraşılması gereken başka bir problemdir.

 

İşte KY-039 sensöründen okuduğunuz her şeyi yazdırmak için basit bir kod:

#define sensorPin  A0

void setup() {

   Serial.begin(9600);

}

void loop ()

{

     Serial.println(analogRead(sensorPin));

 

Bu kod ile bu şekilde bir grafik elde edebilirsiniz:

 

 

Bu, Deneyap Kart’tan 9600 baud'da seri çıktıyı okuyan seri monitör penceresi olduğundan, tüm süreç, değerleri okumak ve yazdırmak için bir hız ayarlayacak olan Serial.println() işlevi tarafından zamanlanır. Grafikte görüldüğü üzere eğri çok pürüzlü, çünkü 360 ile 383 arasında değişiyor ve sadece tam sayı değerlerine sahip.

 

Yumuşatma

 

Daha düzgün bir çıktı elde etmek için sensörden ortalama son 20 veriyi alın. Kaç tane veriyi tutmak istediğimi söyleyen bir sabit tanımlarım:

#define samp_siz 20

Sonra bu sayıda okunan verileri tutan bir dizi:

int reads[samp_siz]; 

 

Her yeni veri için bir toplamdan en eski veriyi çıkarır ve en yeni okunan veriyi toplama eklerim. Dizide en eski veriyi en yeni veri ile değiştiririm.

 

reader = analogRead (sensorPin); // sensorden oku

sum -= reads[ptr];               // en eski veri toplamdan cikartilir

sum += reader;                   // yeni veri toplama eklenir

reads[ptr] = reader;             // yeni veri en eski verinin yerine diziye kaydedilir

last = float(sum) / samp_siz;    // degerlerin ortalamasi hesaplanir

ptr++;                           // en eski verinin indeksi guncellenir

ptr %= samp_siz;                 // sona ulasinca bastan baslar

 

Seri monitörde dizi boyutu 20 ve baud hızı 9600 ile şöyle bir çizim elde edebilirim:

 

 

Burada gerçek kalp atışlarını dik bir yükselen eğri olarak görüyorsunuz. Ama aynı zamanda küçük bir zikzak deseni de görüyorsunuz. Küçük zikzak mutfak ışığımdan geliyor, odayı üç LED ampul aydınlatıyor. Evimdeki elektrik şebekesi 230 V, 50 Hz AC'dir. (Türkiye) Yani saniyede 50 kez, görünüşe göre IR bandında da ışık yoğunluğunda bir artış var. Bu 50 Hz gürültüyü yumuşatmak istiyorum. 20 ms'lik bir süre boyunca sensörden değerleri okuyup tüm değerlerin ortalamasını alırsam çalışması gerekir. Görelim…

 

n = 0;

start = millis();

reader = 0.;

do

{

reader += analogRead(sensorPin);

n++;

now = millis();

}

while (now < start + 20);           

reader /= n;                        


 

Bu kod parçası ile sensör okumalarını 20 ms'lik parçalar halinde alıyorum, bu da yapay ışığın neden olduğu 50 Hz'lik titremeyi bile ortadan kaldıracak. 60 Hz'lik bir ülkede yaşıyorsanız, bunun yerine 16,67 ms'lik parçalar kullanın. Veya 16667µs.

 

Eğriyi 20 ms'lik bölümlerde zaten yumuşattığım için, aslında daha önce kullandığım diziye ihtiyacım yok, ancak orada olduğu ve kolayca yeniden boyutlandırılabilir olduğu için onu orada bırakıyorum. Ve 5 dizi boyutu (20 yerine) kullanmak, son sinir bozucu gürültüyü bile ortadan kaldırıyor gibi görünüyor. Şimdi sahip olduğumuz şey bu:

 

 

Yapmamız gereken son şey, yinelenen modeldeki herhangi bir parçayı tanımak. Yükselen eğim daha düzenli olduğu için tercih ediyoruz. Tüm grafiklerde y ekseni değerlerinin nasıl çok farklı olduğuna dikkat edin. Gerçekten sadece mutlak değerlere güvenemeyiz. Sadece eğrinin yükselişine ve düşüşüne güvenebiliriz. Türev hakkında konuşulabilirdi fakat n'nin kullanışlı bir ayarlanabilir değer olabileceği ardışık n artan değer bulursak bu bizi tatmin edecektir. 5 ile başlıyoruz. Bunun için kodda tanımlanmış olan rise_threshold sabitine sahibiz. Ardışık 5 yükselen değer bulduğumuzda, yukarı doğru giden eğrinin en altında olduğumuzu biliyoruz. Zamanı alırız ve düşen bir eğri bekliyoruz, ardından sonraki 5 yükselen değeri bekliyoruz ve zamanı kaydediyoruz. Sonra ilgili BPM değerini yazdırırız.

 

Bir test yaptık ve eğride art arda kaç tane yükselen değer olduğunu saydık ve 10 ile 15 arasında olduğunu öğrendik. Yani 5'e kadar sayarsak, kalp atışının başlangıcını bulduğumuzdan emin olacağız.

 

Sadece her kalp atışından sonra yazdırdığım için grafikte çok fazla veri olmayacak. Sensörü okumak için daha fazla zamanımız olacak. Nasıl çalıştığını görelim.


 


 

Görseldeki grafik karanlık bir ortamda nabız ölçümü esnasında elde edilmiştir. Düz çizginin bulunduğu kısım sensörde nabız ölçümü esnasında kaydedilmiştir. Grafiğin başındaki ve sonundaki uzun dalgalı verilerde sensörde ölçüm yapılmamaktadır.

Tamamlanmış Kod [OLED EKRANA YAZDIRMAZ, OLED Ekrana Yazdırma Kodu İçin Bölüm Sonunu İnceleyin]

 

#define samp_siz 5  // ortalamasi alinacak ornek sayisi

#define rise_threshold 4 // yukselmeleri tespit icin ardisik n artan deger

#define sensorPin A0 // sensorun bagli oldugu analog pin

 

void setup() {

    Serial.begin(9600); // seri haberlesme

}

 

void loop ()

{

    float reads[samp_siz], sum; // degisken tanimlari

    long int now, ptr;

    float last, reader, start;

    float first, second, third, before, print_value;

    bool rising;

    int rise_count;

    int n;

    long int last_beat;

    // daha kolay hesaplama icin diziye degerler atanir

    for (int i = 0; i < samp_siz; i++)

      reads[i] = 0;

    sum = 0;

    ptr = 0;

 

    while(1)

    {

      // 20 mslik bir süre boyunca sensorun ortalamasini hesaplayin (15 denenebilir)

      // (bu, yapay isigin neden olduğu 50 Hz gurultuyu ortadan kaldiracaktir)

      n = 0;

      start = millis();

      reader = 0.;

      do

      {

        reader += analogRead(sensorPin);

        n++;

        now = millis();

      }

      while (now < start + 15);  

      reader /= n;  // ortalama

      

      // En yeni veriyi toplama ekleyin, en eskisini cikartin

      // En eski verinin yerine yeni veriyi diziye kaydedin

      sum -= reads[ptr];

      sum += reader;

      reads[ptr] = reader;

      last = sum / samp_siz;  // olusan son dizinin ortalamasi

 

      // yukselen bir egri olup olmadigini kontrol (= kalp atisi)

      if (last > before)

      {

        rise_count++;

        if (!rising && rise_count > rise_threshold)

        {

          // Kalp atisi anlamina gelen yukselen bir egri tespit ettik.

          // Son atistan bu yana gecen sureyi kaydedin, agirlikli bir

          // ortalama elde etmek icin onceki iki zamani (first, sec, third) kaydedin.

          // rising degiskeni ayni atisi birden fazla algilamamizi engeller.

          rising = true;

          first = millis() - last_beat;

          last_beat = millis();

 

          print_value = 60000. / (0.4 * first + 0.3 * second + 0.3 * third); // Kalp atis hizinin agirlikli ortalamasini son uc atisa gore hesapla

          

          Serial.print(print_value);

          Serial.print('\n');

          

          third = second;

          second = first;

          

        }

      }

      else

      {

        // egri dusuyor

        rising = false;

        rise_count = 0;

      }

      before = last;

      

      ptr++;

      ptr %= samp_siz;

 

    }

}

 

 

Basitçe, bir kalp atışı olduğunda, hız hesaplanır ve seri ekrana yazdırılır. Parmak biraz hareket ettiğinde hatalı okumalar olacaktır.

 

Daha Fazla Geliştirme

 

Şu anda yazdırılan hız, son üç atışa göre hesaplanır. Ama 15 s periyoda göre hesaplamak daha uygun olabilir. 15 ardışık hız değeri kaydedebilir, ortalamayı hesaplayabilir, ardından ortalamadan en uzak olan beş değeri dışarıda bırakıp yeni bir ortalama hesaplayabiliriz. Bu, kalp atış hızının hemen hemen güvenilir ve sabit bir ölçümünü verir.

 

Sensörü sadece kendi üzerimde test ettim. Önceki okumalara dayanarak yaptığım sinyali güçlendirmedeki her adım. Başka birinin, farklı bir eğriye neden olan başka bir kalp atışı türü olabilir, bu da ritmi bulmak için başka bir yaklaşıma ihtiyaç duyar. Belki de tanınması daha kolay olan düşen eğri veya en tepedir. Nabız 180 - 200 BPM ise ne olur? Yükselen eğriyi bulmak daha zor olabilir.

Şema

Proje Ortakları

Location for : Listing Title