مستشعر نبضات القلب
شرح
مبسط عن المستشعر المستخدم في المشروع
مستشعر
النبض هو مستشعر معدل ضربات القلب منخفض الطاقة مصمم جيدًا للتوصيل والتشغيل ل 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
تعليقات
إرسال تعليق