نام این سنسور کمی فریب دهنده است و انتظار زیادی ایجاد میکند . با شنیدن نام سنسور تشخیص  ضربان قلب ، تصویر میشه که این سنسور از طریق مثلا ارتباط I2C  به صورت اعداد دیجیتالی ضربان قلب رو برای ما تعیین میکنه . اما در حقیقت اینطور نیست . 


این سنسور در واقع شدت نور مادون قرمز رو به صورت آنالوگ برای ما تعیین میکنه . با استفاده از ورودی ADC اعدادی از 0 تا 1024  رو به ما میده .

با قرار گرفتن انگشت بین LED مادون قرمز و گیرنده مادون قرمز با کم و زیاد شدن جریان خون در انگشت مقدار نور عبوری از انگشت هم تغییر میکنه . ما با اندازه گیری تعداد این تغیرات در واحد زمان ضربان قلب رو محاسبه میکنیم . :)



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


برد آردوینو  Arduino UNO

ماژول سنسور تشخیص ضربان قلب KY-039



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

اگر ما فقط مقادیر خروجی سنسور رو ترسیم کنیم ، چیزی مثل شکل زیر رو داریم :


این ها مقادیر و اعداد صحیح هستند . خیلی دقیق نیستند . اما اگر از این دسته از اعداد میانگین بگیریم چیزی شبیه شکل زیر به دست میاد :

توی این شکل میتونیم ضربان قلب رو ببینیم :) . الگوی ریز دندونه اره ای که توی شکا میبینید به خاطر منابع دیر نور مادون قرمز به مجود میاد .

اینجا میبینیم که بین مقادیر پایین و پالا تفاوت محسوسی وجود داره و با محاسبه این مقادیر در واحد زمان میتونیم ضربان قلب در دقیقه رو به دست بیاریم .


آزمایش عملی توضیحات بالا در مورد سنسور ضربان قلب KY-039 


اینجا کدهای ساده ای رو مینویسیم که هرمقداری رو که از سنسور تشخیص ضربان قلب KY-039   دریافت میکنیم به صورت خام به  ما نشون بده . مثل همون شکل اول .


// Pulse Monitor Test Script
int sensorPin = 0;
void setup() {
   Serial.begin(9600);
}
void loop ()
{
   while(1)
   {
     Serial.print(analogRead(sensorPin));
     Serial.print('\n');
   }
} 

این کد چیزی شبیه  شکل زیر رو به ما میده :

این شکل از طرق سریال مانیتور  Arduino IDE  نمایش داده میشه و از حروجی سریال برد آردوینو با بادریت 9600 دریافت میشه . برای اینکار از تابع ()Serial.print استفاده کردیم که مقادیر رو میگیره و در سریال مانیتور رسم میکنه . میبینید که مقادیر بسیار زیاد و دندانه دار است چون که مقادیر دریافتی از 360 تا 383 متفاوت است و فقط اعداد صحیح هستند .


هموارسازی و صافکردن شکل موج خروجی 

برای داشتن خروجی صاف باید از آخرین 20 مقدار خروجی سنسور تشخیص ضربان قلب KY-039 میانگین بگیریم . 

خب برای اینکار ابتدا تعیین میکنیم که از چه تعداد اعداد دریافتی میخوایم میانگین بگیریم . 

#define samp_siz 20
سپس یک آرایه میسازیم . 

int reads[samp_siz]; 

.

کدهای زیر از جدیدترین مقادیری که از سنسور دریافت میکنه میانگین میگیره، مقادیر رو در یه آرایه 20 تایی ذخیره میکنه. به این صورت که هربار با دریافت جدیدترین مقدار از سنسور اون رو جایگزین قدیمیترین مقدار آرایه میکنه.

همانطور که میدونیم میانگین چند عدد از جمع اعداد تقسیم بر تعداد آنها بدست میآید float(sum) / samp_size
قدیمیترین مقدار رو از مجموع مقادیر کم میکنه و بجاش جدیدترین مقدار خونده شده از سنسور رو با مجموع مقادیر جمع میکنه
همچنین مقدار جدید رو در آرایه جایگزین مقدار قدیمی میکنه ، بعدش میانگین رو بدست میاره . هربار یکی به مقدار ptr اضافه میشه که تعیین کننده عنصر آرایه هست .

مثلا مقدار ptr از صفر شروع شده. عضو صفرم آرایه که قدیمیترین هست از مجموع کم میشه بجاش جدیدترین مقدار با مجموع مقادیر جمع میشه و همچنین جایگزین عضو صفرم میشه، بعد از محاسبه میانگین یکی به ptr اضافه میشه و دوباره ...

Ptr %= samp_size
باقیمانده تقسیم ptr با samp_size رو حساب میکنه و میریزه داخل ptr ، به عبارتی کارش اینه که وقتی مقدار ptr به samp_size یعنی در اینجا به 20 رسید صفر میشه و این روند دوباره تکرار میشه..

     reader = analogRead (sensorPin); // read the sensor
     sum -= reads[ptr];               // subtract the oldest reading from sum
     sum += reader;                   // add the newest reading to the sum
     reads[ptr] = reader;             // save the newest reading in the array
     last = float(sum) / samp_siz;    // calculate the average now
     ptr++;                           // update the index for the array, have
     ptr %= samp_siz;                 // it restart at 0 when needed

.

با یه آرایه 20 تایی و  9600  baud rate سریال مانیتورشبیه شکل زیر رو خواهیم داشت .

در اینجا در ضربان واقعی قلب رو میبینید به صورت یه منحنی که با شیب تندی بالا میره و با شیب کم پایین میاد . همونطور که گفتم این پارازیت های ریزی که در منحنی میبینید مزبوط به نور ها و امواج مادون قرمز موجود در محیط هست . همانطور که میدونیم نویز برق شهر 50هرتز هست که در واقع دوره تناوبش میشه 20میلی ثانیه

هدف اینه که نویز حاصل از برق شهر رو حذف کنیم. فرض کن یه سیگنال خالص برق شهر داریم اگه ازش در 20میلی ثانیه میانگین بگیریم جواب میشه صفر.
خوب حالا ما اینجا توی خروجیمون یه سیگنالی داریم که شامل نویز برق شهر+سیگنال اصلیه، که اگه ازش در 20میلی ثانیه میاگین بگیریم نویز برق شهره ازش حذف میشه و سیگنال اصلی باقی میمونه.

توی این کد تابع millis میاد زمان فعلی رو بر حسب میلی ثاینه بر میگردونه که در متغیر start نگهش میداریم.
داخل یه حلقه مرتب مقادیر سنسور رو میگیریم و با هم جمع میکنیم تا زمانی که 20میلی ثانیه بگذره یعنیstart+20.
داخل حلقه n++ هم تعداد دفعات خواندن مقدار از سنسور رو بهمون میده که برای بدست آوردن میانگین reader /=n بهش احتیاج داریم.

 n = 0;
     start = millis();
     reader = 0.;
     do
     {
       reader += analogRead (sensorPin); // read and add values...
       n++;
       now = millis();
     }
     while (now < start + 20);           // ...until 20 ms have elapsed
     reader /= n;                        // and take an average of the values

خب با این تغییر الان شکل زیر رو داریم 

 

آخرین کاری که باید انجام بدیم اینه که تعداد تکرار منحنی ها رودر واحد زمان  بدست بیاریم . همانطور که میبینید مقادیر در محور Y بسیار متفاوت است . پس من باید فقط تعداد شیب های  بالا و پایین  رو در نظر بگیرم . برای کافیه که فقط تعداد بالا رفتن منحنی رو تشخیص بدیم . 

ادامه مطلب 


منبع  :  ElectroPi.ir