아두이노 손가락 심장박동 감지 센서 (KY-039)
해당 센서는 적외선 송수신을 이용하여 심장박동을 측정 가능한 센서이다.
측정된 값의 정확도는 어느정도 인지는 확인되지 않는다.
측정된 값을 bpm으로 변환하는 예제도 아래에 있다.
<예제소스 1>
int sensorPin = A0; double alpha = 0.75; int period = 50; double change = 0.0; double minval = 0.0; void setup () { Serial.begin(9600); } void loop () { static double oldValue = 0; static double oldChange = 0; int rawValue = analogRead(sensorPin); double value = alpha * oldValue + (1 - alpha) * rawValue; Serial.print(rawValue); Serial.print(","); Serial.println(value); oldValue = value; delay(period); }
오른쪽 상단 돋보기 아이콘을 클릭하면 시리얼 모니터 창이 뜬다
아두이노를 실행하면 결과가 출력이 된다
아래의 구성되로 아두이노와 센서를 연결한다.
노란선 Signal에 연결하고 아두이노의 아날로그 A0핀에 연결한다.
센서에 손가락을 대면 센서에서 심장박동을 인식하는걸 확인할 수 있다.
아래는 측정된값을 BPM값으로 변경하는 소스이다.
<예제소스 2 - bpm 계산>
//////////////////////////////////////////////////////////////////////// /// Copyright (c)2015 Dan Truong /// Permission is granted to use this software under the MIT /// licence, with my name and copyright kept in source code /// http://http://opensource.org/licenses/MIT /// /// KY039 Arduino Heartrate Monitor V1.0 (April 02, 2015) //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// @param[in] IRSensorPin Analog pin on which IR detector is connected /// @param[in] delay (msec) delay between calls to this method. It is /// best to call it at least 5 times per beat, aka /// no slower than 150msec for 70bpm. An ideal value /// is 60ms or faster to handle up to 200 BPM. /// /// @brief /// True if heartbeat is detected on the sensor. /// This code is trivial and just does a peak detection, instead of /// trying to detect the heart's pulse waveform. /// Note: I am fudging sensor data with the delay to make the integer /// math after that uses constants, somewhat independant of the sleep /// delay used in the main loop. Otherwise if maxValue decays too slow /// or too fast, it causes glitches and false beat detection. //////////////////////////////////////////////////////////////////////// //#define HBDEBUG(i) i #define HBDEBUG(i) bool heartbeatDetected(int IRSensorPin, int delay) { static int maxValue = 0; static bool isPeak = false; int rawValue; bool result = false; rawValue = analogRead(IRSensorPin); // Separated because analogRead() may not return an int rawValue *= (1000/delay); HBDEBUG(Serial.print(isPeak); Serial.print("p, ")); HBDEBUG(Serial.print(rawValue); Serial.print("r, ")); HBDEBUG(Serial.print(maxValue); Serial.print("m, ")); // If sensor shifts, then max is out of whack. // Just reset max to a new baseline. if (rawValue * 4L < maxValue) { maxValue = rawValue * 0.8; HBDEBUG(Serial.print("RESET, ")); } // Detect new peak if (rawValue > maxValue - (1000/delay)) { // Only change peak if we find a higher one. if (rawValue > maxValue) { maxValue = rawValue; } // Only return true once per peak. if (isPeak == false) { result = true; Serial.print(result); Serial.print(", *"); } isPeak = true; } else if (rawValue < maxValue - (3000/delay)) { isPeak = false; // Decay max value to adjust to sensor shifting // Note that it may take a few seconds to re-detect // the signal when sensor is pushed on meatier part // of the finger. Another way would be to track how // long since last beat, and if over 1sec, reset // maxValue, or to use derivatives to remove DC bias. maxValue-=(1000/delay); } HBDEBUG(Serial.print("\n")); return result; } //////////////////////////////////////////////////////////////////////// // Arduino main code //////////////////////////////////////////////////////////////////////// //int ledPin=13; int analogPin=0; void setup() { // Built-in arduino board pin for the display LED //pinMode(ledPin,OUTPUT); // Init serial console Serial.begin(9600); Serial.println("Heartbeat detection sample code."); } const int delayMsec = 60; // 100msec per sample // The main loop blips the LED and computes BPMs on serial port. void loop() { static int beatMsec = 0; int heartRateBPM = 0; if (heartbeatDetected(analogPin, delayMsec)) { heartRateBPM = 60000 / beatMsec; //digitalWrite(ledPin,1); // Print msec/beat and instantaneous heart rate in BPM Serial.print(beatMsec); Serial.print(", "); Serial.println(heartRateBPM); beatMsec = 0; } else { //digitalWrite(ledPin,0); } // Note: I assume the sleep delay is way longer than the // number of cycles used to run the code hence the error // is negligible for math. delay(delayMsec); beatMsec += delayMsec; }
<결과>