مشروع حساس نبضات القلب بأستخدام الاردوينو 


مرحبا اصدقائي ! ها قد عدت اليكم بتجربه جديده وشيقه حيث سنقوم في هذه التجربه بأستخدام حساس النبض وربطه بالاردوينو من ثم قراءة نبضات القلب على شاشة السيريال (Serial Monitor) حيث يعد تصنيف هذا المشروع من مشاريع الاردوينو الطبيه , لن اقوم بالتحدث اكثر من ذلك يبدو عليك الحماسه هيا لنبدأ .

القطع المطلوبه :


قبل البدء بصنع مشروعنا يجب علينا معرفة القطع المطلوب منا توفيرها للعمل على مشروعنا وها هو جدول بالقطع المطلوبه لمشروع قراءة نبضات القلب بأستخدام الاردوينو .

اسم القطعه بالعربيه
اسم القطعه بالانجليزيه
المصدر
اردوينو اونو
Arduino Uno
https://www.sparkfun.com/products/11224
لوح تجارب
Bread Board
https://www.sparkfun.com/products/112
طنان
Buzzer/piezo Speaker
https://www.sparkfun.com/products/7950
ضوء LED
LED Light
https://www.sparkfun.com/products/12062
حساس نبضات القلب
Pulse Sensor
https://www.sparkfun.com/products/11574
اسلاك توصيل
Connecting Wires
https://www.sparkfun.com/products/12794

توصيل حساس النبض مع الاردوينو:


حساس النبض هو موديول يسمح لمستخدمه بقراءة النبض بشكل مباشر من ثم استخدام القرائات في مشروع معين مثل مراقبة نبض شخص مريض على مدار الساعه او غيره من المشاريع الرائعه!

توصيل حساس النبض بالاردوينو سهل للغايه بناء الجدول التالي قم بوصل الحساس بالاردوينو.

اسم مدخل/مخرج الاردوينو
اسم مدخل/مخرج الحساس
5V
VCC
GND
GND
A0
OUT

توصيل الطنان (البيزو):


كما نعلم ان البيزو يأتي بقطبين فقط هما ( الانود , الكاثود ) ويتم توصيل البيزو للأردوينو بهذه الطريقه :
  • السلك الاحمر (الانود) يتم توصيله الى مخرج ديجيتال رقم 13 في الاردوينو
  • السلك الاسود (الكاثود) يتم توصيله مع GND في الاردوينو
وهكذا نكون مستعدون للبدء بتوصيل اخر قطعه في مشروعنا وهي ضوء الليد "LED"  


توصيل ضوء الليد مع الاردوينو: 

كما هو الحال في توصيل البيزو فالامر متشابه هنا , حيث لو قمت بالنظر لضوء الليد سترى احدى القطبين اطول من الاخر 
حيث يكون الطرف الاطول (الانود) هو الطرف الموجب بينما يكون الطرف الاقصر (الكاثود) هو الطرف السالب .


  • يتم وصل الطرف الاطول (الانود) مع مخرج ديجيتال رقم 10 في الاردوينو
  • يتم وصل الطرف الاقصر (الكاثود) مع GND في الاردوينو
الكود البرمجي :


   int pulsePin = 0;

int blinkPin = 13;

int fadePin = 8;

int fadeRate = 0;

int BPM;

int Signal;

int IBI = 600;

boolean Pulse = false;

boolean QS = false;

boolean serialVisual = true;

volatile int rate[10];

long sampleCounter = 0;

long lastBeatTime = 0;

int P = 512;

int T = 512;

int thresh = 525;

int amp = 100;

boolean firstBeat = true;

boolean secondBeat = false;

void setup() {

pinMode(blinkPin,OUTPUT); // pin that will blink to your heartbeat!

pinMode(fadePin,OUTPUT); // pin that will fade to your heartbeat!

Serial.begin(115200); // we agree to talk fast!

interruptSetup(); // sets up to read Pulse Sensor signal every 2mS // IF YOU ARE POWERING The Pulse Sensor AT VOLTAGE LESS THAN THE BOARD VOLTAGE, // UN-COMMENT THE NEXT LINE AND APPLY THAT VOLTAGE TO THE A-REF PIN //

analogReference(EXTERNAL); }

// Where the Magic Happens

void loop() {

serialOutput();

if (QS == true) // A Heartbeat Was Found {

// BPM and IBI have been Determined // Quantified Self "QS" true when arduino finds a heartbeat

fadeRate = 255; // Makes the LED Fade Effect Happen, Set 'fadeRate' Variable to 255 to fade LED with pulse serialOutputWhenBeatHappens(); // A Beat Happened, Output that to serial.

QS = false; // reset the Quantified Self flag for next time }

ledFadeToBeat(); // Makes the LED Fade Effect Happen

delay(20); // take a break }

void ledFadeToBeat() {

fadeRate -= 15; // set LED fade value

fadeRate = constrain(fadeRate,0,255); // keep LED fade value from going into negative numbers! analogWrite(fadePin,fadeRate); //

fade LED }

void interruptSetup() { // Initializes Timer2 to throw an interrupt every 2mS.

TCCR2A = 0x02; // DISABLE PWM ON DIGITAL PINS 3 AND 11, AND GO INTO CTC MODE

TCCR2B = 0x06; // DON'T FORCE COMPARE, 256 PRESCALER

OCR2A = 0X7C; // SET THE TOP OF THE COUNT TO 124 FOR 500Hz SAMPLE RATE

TIMSK2 = 0x02; // ENABLE INTERRUPT ON MATCH BETWEEN TIMER2 AND OCR2A

sei(); // MAKE SURE GLOBAL INTERRUPTS ARE ENABLED }

void serialOutput() { // Decide How To Output Serial.

if (serialVisual == true) {

arduinoSerialMonitorVisual('-', Signal); // goes to function that makes Serial Monitor Visualizer } else { sendDataToSerial('S', Signal); // goes to sendDataToSerial function } }

void serialOutputWhenBeatHappens()

{

if (serialVisual == true) // Code to Make the Serial Monitor Visualizer Work

{ Serial.print("*** Heart-Beat Happened *** "); //ASCII Art Madness

Serial.print("BPM: ");

Serial.println(BPM); }

else {

sendDataToSerial('B',BPM); // send heart rate with a 'B' prefix sendDataToSerial('Q',IBI); // send time between beats with a 'Q' prefix }

}

void arduinoSerialMonitorVisual(char symbol, int data ) {

const int sensorMin = 0; // sensor minimum, discovered through experiment

const int sensorMax = 1024; // sensor maximum, discovered through experiment

int sensorReading = data; // map the sensor range to a range of 12 options:

int range = map(sensorReading, sensorMin, sensorMax, 0, 11); // do something different depending on the // range value: switch (range) { case 0: Serial.println(""); /////ASCII Art Madness break; case 1: Serial.println("---"); break; case 2: Serial.println("------"); break; case 3: Serial.println("---------"); break; case 4: Serial.println("------------"); break; case 5: Serial.println("--------------|-"); break; case 6: Serial.println("--------------|---"); break; case 7: Serial.println("--------------|-------"); break; case 8: Serial.println("--------------|----------"); break; case 9: Serial.println("--------------|----------------"); break; case 10: Serial.println("--------------|-------------------"); break; case 11: Serial.println("--------------|-----------------------"); break; } }

void sendDataToSerial(char symbol, int data ) {

Serial.print(symbol); Serial.println(data); }

ISR(TIMER2_COMPA_vect) //triggered when Timer2 counts to 124 { cli(); // disable interrupts while we do this Signal = analogRead(pulsePin); // read the Pulse Sensor sampleCounter += 2; // keep track of the time in mS with this variable int N = sampleCounter - lastBeatTime; // monitor the time since the last beat to avoid noise // find the peak and trough of the pulse wave if(Signal < thresh && N > (IBI/5)*3) // avoid dichrotic noise by waiting 3/5 of last IBI { if (Signal < T) // T is the trough { T = Signal; // keep track of lowest point in pulse wave } }

if(Signal > thresh && Signal > P) { // thresh condition helps avoid noise P = Signal; // P is the peak } // keep track of highest point in pulse wave

// NOW IT'S TIME TO LOOK FOR THE HEART BEAT // signal surges up in value every time there is a pulse if (N > 250) { // avoid high frequency noise if ( (Signal > thresh) && (Pulse == false) && (N > (IBI/5)*3) ) { Pulse = true; // set the Pulse flag when we think there is a pulse digitalWrite(blinkPin,HIGH); // turn on pin 13 LED IBI = sampleCounter - lastBeatTime; // measure time between beats in mS lastBeatTime = sampleCounter; // keep track of time for next pulse if(secondBeat) { // if this is the second beat, if secondBeat == TRUE secondBeat = false; // clear secondBeat flag for(int i=0; i<=9; i++) // seed the running total to get a realisitic BPM at startup { rate[i] = IBI; } } if(firstBeat) // if it's the first time we found a beat, if firstBeat == TRUE { firstBeat = false; // clear firstBeat flag secondBeat = true; // set the second beat flag sei(); // enable interrupts again return; // IBI value is unreliable so discard it } // keep a running total of the last 10 IBI values word runningTotal = 0; // clear the runningTotal variable

for(int i=0; i<=8; i++) { // shift data in the rate array rate[i] = rate[i+1]; // and drop the oldest IBI value runningTotal += rate[i]; // add up the 9 oldest IBI values }

rate[9] = IBI; // add the latest IBI to the rate array runningTotal += rate[9]; // add the latest IBI to runningTotal runningTotal /= 10; // average the last 10 IBI values BPM = 60000/runningTotal; // how many beats can fit into a minute? that's BPM! QS = true; // set Quantified Self flag // QS FLAG IS NOT CLEARED INSIDE THIS ISR } }

if (Signal < thresh && Pulse == true) { // when the values are going down, the beat is over digitalWrite(blinkPin,LOW); // turn off pin 13 LED Pulse = false; // reset the Pulse flag so we can do it again amp = P - T; // get amplitude of the pulse wave thresh = amp/2 + T; // set thresh at 50% of the amplitude P = thresh; // reset these for next time T = thresh; }

if (N > 2500) { // if 2.5 seconds go by without a beat thresh = 512; // set thresh default P = 512; // set P default T = 512; // set T default lastBeatTime = sampleCounter; // bring the lastBeatTime up to date firstBeat = true; // set these to avoid noise secondBeat = false; // when we get the heartbeat back }

sei(); // enable interrupts when youre done! }// end isr