مستشعر نبضات القلب
شرح
مبسط عن المستشعر المستخدم في المشروع
مستشعر
النبض هو مستشعر معدل ضربات القلب منخفض الطاقة مصمم جيدًا للتوصيل والتشغيل ل Arduino
يمكن استخدامه من قبل الطلاب الذين يرغبون في دمج بيانات معدل
ضربات القلب الحية في مشاريعهم
وأفضل جزء هو
أن هذا المستشعر يتم توصيله مباشرة بـ
Arduino
ويمكن تثبيته بسهولة على طرف الإصبع أو شحمة الأذن
نظره
عامه على الحساس
الجزء الأمامي من المستشعر هو الجانب
الذي يحمل شعار القلب. هذا هو المكان الذي تضع فيه إصبعك سترى على الجانب الأمامي ثقبًا دائريًا صغيرًا حيث يضيء مصباح LED الأخضر
من Kingbright الأخضر المثبت على الجانب الخلفي
يوجد أسفل LED مباشرة
مستشعر صورة صغير للضوء المحيط لضبط سطوع الشاشة في ظروف الإضاءة المختلفه
المستخدم في الهواتف المحمولة والأجهزة اللوحية وأجهزة الكمبيوتر المحمولة
ستجد بقية المكونات بما
في ذلك رقاقة المقاومات والمكثفات التي
تشكل شبكة مرشح R / C   ومجموعة من MCP6001
Op-Amp ي الجزء الخلفي من المستشعر
, يوجد أيضًا صمام ثنائي حماية عكسي لمنع التلف اذا تم عكس أسلاك الطاقة عن
طريق الخطأ.
يعمل الحساس من 3.3 إلى
5V DC
Voltage و إمداد
التيار الكهربائي للتيارالتشغيلي <4Ma
بعض المواصفات الفنيه للحساس
| 
   3.0 - 5.5 فولت  | 
  
   VCC  | 
  
   اقصى
  تصنيفات  | 
 
| 
   <4mA  | 
  
   IMax (أقصى سحب للتيار)  | 
 |
| 
   0.3V vcc  | 
  
   VOut (نطاق الجهد الناتج)  | 
 |
| 
   565 نانومتر  | 
  
   خرج LED  | 
  
                            الطول الموجي  | 
 
| 
   525 نانومتر  | 
  
   مدخلات
  الاستشعار  | 
 
كيف يعمل
مستشعر النبض
عمل
مستشعر النبض أو أي مستشعر ضوئي لمعدل ضربات القلب عن طريق تسليط ضوء أخضر (~ 550
نانومتر) على الإصبع وقياس كمية الضوء المنعكس باستخدام مستشعر ضوئي.
تسمى طريقة اكتشاف النبض من خلال الضوء بالرسم
البياني الضوئي
تميز الهيموغلوبين المؤكسج في الدم
الشرياني بامتصاص الضوء الأخضر. كلما زاد احمرار الدم (كلما ارتفع مستوى
الهيموجلوبين) ، زاد امتصاص الضوء الأخضر. عندما يتم ضخ الدم من خلال الإصبع مع كل
نبضة قلب ، يتغير مقدار الضوء المنعكس ، مما يؤدي إلى تكوين شكل موجة متغير عند
إخراج المستشعر الضوئي.
هذه الإشارة من المستشعر الضوئي صغيرة
بشكل عام ومشوشه, لذلك يتم تمرير الإشارة عبر شبكة مرشح R / C م
يتم تضخيمها باستخدام Op
Amp لإنشاء إشارة أكبر بكثير
وأنظف وأسهل في الكشف.
مداخل ومخرج المستشعر
ا-GND:السلك المتصل بالارضي
2-VCC:يتصل بمصدر جهد5V
او 3,3V 
3-SIGNAL:هو
خرج الاشاره يتصل بالدخل التناظري للاردوينو
الادوات المطلوبه لانشاء مستشعر نبضات
القلب:
1-مستشعر لنبضات القلب
2-شاشه LCD
3-اوردوينو اونو
4-اسلاك توصيل
طريقه توصيل حساس
النبضات بالاردوينو
| 
   مخرج الحساس  | 
  
   مدخل الاردوينو  | 
 
| 
   Vcc  | 
  
   5v  | 
 
| 
   Gnd  | 
  
   Gnd  | 
 
| 
   SIGNAL  | 
  
   A0  | 
 
نقوم بتوصيل مخرج
الحساس vccبمدخل الاردوينو5v لتغذيه الحساس بالجهد
ونوصل مخرج الحساس gndبمدخل الاردوينوgnd
ونوصل خرج الحساس SIGNAL بدخل الاردوينوا A0
توصيل شاشه الLcd16*4 بالاردوينو
نوصل الطرف الاول للشاشه
gnd والطرف الخامس R/W والطرف السادس عشرA بمنفذ الارضي GND في الاردوينو
نوصل الطرف الثاني VCC والطرف الخامس عشر K ب5V للاردوينو
ونوصل الطرف الثالث للشاشهVEE بالمقاومه المتغيره
ونوصل الطرف الرابع RS للشاشه بمنفذ استقبال
البيانات رقم 2 للاردوينو
و الطرف السادس E للشاشه بمنفذ استقبال البيانات رقم 3 للاردوينو
و الطرف الاحدى عشر D4 للشاشه بالمنفذ رقم 4 للاردوينو
والطرف الثاني عشر D5 للشاشه بالمنفذ رقم 5
للاردوينو
والطرف الثالث عشرD6 للشاشه بالمنفذ رقم 6للاردوينو
والطرف الرابع عشرD7 للشاشه بالمنفذ رقم 7 للاردوينو
 
صوره توضح طريقه التوصيل بين القطع
الاكواد المستخدمه لبرمجه الاردوينو:
#include <LiquidCrystal.h>
LiquidCrystal
lcd( 2, 3, 4, 5, 6, 7);
int
pulsePin = A0;                 //
Pulse Sensor purple wire connected to analog pin A0
int
blinkPin = 13;                // pin to
blink led at each beat
//
Volatile Variables, used in the interrupt service routine!
volatile
int BPM;                   //
int that holds raw Analog in 0. updated every 2mS
volatile
int Signal;                // holds the
incoming raw data
volatile
int IBI = 600;             // int that holds
the time interval between beats! Must be seeded! 
volatile
boolean Pulse = false;     // "True" when User's live
heartbeat is detected. "False" when not a "live
beat". 
volatile
boolean QS = false;        // becomes true when Arduoino
finds a beat.
static
boolean serialVisual = true;   // Set to 'false' by Default. 
Re-set to 'true' to see Arduino Serial Monitor ASCII Visual Pulse 
volatile
int rate[10];                 
    // array to hold last ten IBI values
volatile
unsigned long sampleCounter = 0;          // used to
determine pulse timing
volatile
unsigned long lastBeatTime = 0;           // used
to find IBI
volatile
int P = 512;                 
   // used to find peak in pulse wave, seeded
volatile
int T = 512;                 
   // used to find trough in pulse wave, seeded
volatile
int thresh = 525;                //
used to find instant moment of heart beat, seeded
volatile
int amp = 100;                 
 // used to hold amplitude of pulse waveform, seeded
volatile
boolean firstBeat  = true;        // used to seed rate
array so we startup with reasonable BPM
volatile
boolean secondBeat = false;      // used to seed rate array so
we startup with reasonable BPM
void
setup()
{
 
lcd.begin(16,2);
 
pinMode(blinkPin,OUTPUT);// pin that will blink 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
 
    serialOutputWhenBeatHappens(); // A Beat Happened, Output that to
serial.     
 
    QS = false; // reset the Quantified Self flag for next time 
  
 
  }
 
   
 
delay(20); //  take a break
}
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 Found ");  //ASCII Art
Madness
 
   Serial.print("BPM: ");
 
   Serial.println(BPM);
 
   lcd.setCursor(0,0);
 
   lcd.print("Heart Beat Found ");
 
   lcd.setCursor(0,1);
 
   lcd.print("BPM: ");
 
   lcd.print(BPM);
 
   lcd.clear();
 
   delay(300);
 
 }
 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:
}
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
تعليقات
إرسال تعليق