BASIC4MCU | 질문게시판 | ad8232를 이용한 bpm 제발 도와주세요 부탁드립니다
페이지 정보
작성자 아누이노생초보 작성일2020-11-25 15:36 조회2,424회 댓글1건첨부파일
본문
안녕하세요 ad8232를 이용하여 1분동안의 bpm을 측정하기 위한 프로그램을 작성하기 위해 여기저기 인터넷을 검색하고 있는 아누이노 생초보입니다. 인터넷을 검색하다보니 보통 다 ad8232만을 이용하지 않고 프로세싱을 이용하거나 lcd 또는 oled 등을 이용하여 bpm을 보이게 하는 코딩이 있던데
저는 오로지 ad8232만으로 시리얼모니터에 bpm값이 나오고, 시리얼 플로터창에는 심박측정이 되는 파형이 보이게 만들고 있습니다.
여기저기 찾아다니며 블로그를 찾아서 그대로 코딩을 해봤는데 bpm값이 200은 족히 넘는 값이 나오네요. 도와주세요
output핀은 아날로그 a0핀, lo+핀은 디지털 11번핀, lo-핀은 디지털 10번에 연결하였습니다. 그라운드와 3.3v도 연결해줬습니다.
// VARIABLES
int pulsePin = 0; // Pulse Sensor purple wire connected to analog pin 0
// these variables are volatile because they are used during the interrupt service routine!
volatile int BPM; // used to hold the pulse rate
volatile int Signal; // holds the incoming raw data
volatile int IBI = 600; // holds the time between beats, the Inter-Beat Interval
volatile boolean Pulse = false; // true when pulse wave is high, false when it's low
volatile boolean QS = false; // becomes true when Arduoino finds a beat.
volatile int rate[10]; // used to hold last ten IBI values
volatile unsigned long sampleCounter = 0; // used to determine pulse timing
volatile unsigned long lastBeatTime = 0; // used to find the inter beat interval
volatile int P =512; // used to find peak in pulse wave
volatile int T = 512; // used to find trough in pulse wave
volatile int thresh = 512; // used to find instant moment of heart beat
volatile int amp = 100; // used to hold amplitude of pulse waveform
volatile boolean firstBeat = true; // used to seed rate array so we startup with reasonable BPM
volatile boolean secondBeat = true; // used to seed rate array so we startup with reasonable BPM
void setup() {
// initialize the serial communication:
Serial.begin(9600);
interruptSetup();
pinMode(3, INPUT); // Setup for leads off detection LO +
pinMode(11, INPUT); // Setup for leads off detection LO -
pinMode(pulsePin, INPUT);
delay(1000);
}
void loop() {
if((digitalRead(3) == 1)||(digitalRead(11) == 1)){
Serial.println('!');
}
else{
// send the value of analog input 0:
sendDataToProcessing('S', Signal); // send Processing the raw Pulse Sensor data
if (QS == true){ // Quantified Self flag is true when arduino finds a heartbeat
sendDataToProcessing('B',BPM); // send heart rate with a 'B' prefix
QS = false; // reset the Quantified Self flag for next time
}
delay(20);
}
//Wait for a bit to keep serial data from saturating
// Serial.println(Signal);
}
void sendDataToProcessing(char symbol, int data ){
Serial.print(symbol); // symbol prefix tells Processing what type of data is coming
Serial.println(data); // the data to send culminating in a carriage return
}
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
}
// THIS IS THE TIMER 2 INTERRUPT SERVICE ROUTINE.
// Timer 2 makes sure that we take a reading every 2 miliseconds
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
// Cautare semnal de puls
// 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
// turn on pin 13 LED
IBI = sampleCounter - lastBeatTime; // measure time between beats in mS
lastBeatTime = sampleCounter; // keep track of time for next pulse
if(firstBeat){ // if it's the first time we found a beat, if firstBeat == TRUE
firstBeat = false; // clear firstBeat flag
return; // IBI value is unreliable so discard it
}
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;
}
}
// 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
// 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 = true; // when we get the heartbeat back
}
sei(); // enable interrupts when youre done!
}
댓글 1
조회수 2,424master님의 댓글
master 작성일lcd 또는 oled 등을 이용하여 bpm을 보이게 하는 코딩이 있던데 <-- 이 소스를 시리얼모니터에 출력하도록 수정하세요