KY-039 Herzschlag Sensor Modul: Unterschied zwischen den Versionen

Aus Linkerkit.de

Wechseln zu: Navigation, Suche
(Codebeispiel Arduino)
Zeile 41: Zeile 41:
  
 
==Codebeispiel Arduino==
 
==Codebeispiel Arduino==
<pre class="brush:cpp">
+
Das folgende Code-Beispiel stammt aus der Feder von Dan Truong, welcher diesen Code unter [[Https://forum.arduino.cc/index.php?topic=209140.msg2168654|folgenden Link]] veröffentlicht hat. Dieser steht unter der MIT OpenSource Lizenz zur Verfügung. Die unten stehende Version ist die übersetzte deutsche Fassung - das original steht unten zum Download zur Verfügung.
  
 +
 +
<pre class="brush:cpp">
 
////////////////////////////////////////////////////////////////////////
 
////////////////////////////////////////////////////////////////////////
 
/// Copyright (c)2015 Dan Truong
 
/// Copyright (c)2015 Dan Truong
Zeile 91: Zeile 93:
 
   // If sensor shifts, then max is out of whack.
 
   // If sensor shifts, then max is out of whack.
 
   // Just reset max to a new baseline.
 
   // Just reset max to a new baseline.
   if (rawValue * 4L < maxValue) {
+
   if (rawValue * 4L < maxValue) {   maxValue = rawValue * 0.8;
    maxValue = rawValue * 0.8;
+
 
     HBDEBUG(Serial.print("RESET, "));
 
     HBDEBUG(Serial.print("RESET, "));
 
     rawValue = rawValue *4L;
 
     rawValue = rawValue *4L;

Version vom 1. April 2016, 15:01 Uhr

Bild

ky-039.jpg

Technische Daten / Kurzbeschreibung

Wird ein Finger zwischen der Infrarot-Leuchtdiode und dem Foto-Transistor gehalten, so kann am Signalausgang der Puls detektiert werden.


Die Funktionsweise eines Fototransistors ist wie folgt erklärt: Dieser funktioniert in der Regel wie ein normaler Transistor - so wird ein höherer Strom durch ihn durchgelassen, je höher die Steuerspannung ist, die an ihn angelegt wird. Bei einem Fototransistor stellt jedoch das einfallende Licht die Steuerspannung dar - je höher das einfallende Licht, so höher der durchgelassene Strom. 


Phototransistor.png
Schaltet man vor dem Transistor einen Widerstand in Reihe, so ergibt sich folgendes Verhalten, wenn man die Spannung über den Transistor misst: Scheint auf den Transistor viel Licht bzw. ist es außen hell, so kann man eine niedrige Spannung nahe 0V gemessen - ist der Transistor im Dunklen, so lässt dieser einen relativ kleinen Strom durch und man misst eine Spannung nahe +V.


Der bei diesem Sensormodul aufgebaute Messaufbau mit Infrarotdiode und Fototransistor ermöglicht uns nun den Puls zu messen, indem ein Finger zwischen Diode und Transistor gelegt wird. Erklärung: Genau so wie man es von der Taschenlampe kennt, kann die Haut an der Hand durchleuchtet werden. Trifft man beim Durchleuchten auf eine Blutader, so kann man ganz schwach das Pumpen des Blutes erkennen. Dieses Pumpen erkennt man, da das Blut an unterschiedlichen Stellen in der Ader eine andere Dichte besitzt und somit Helligkeitsunterschiede beim Blutfluss erkennbar sind. Genau diese Unterschiede in der Helligkeit kann man mit dem Sensormodul aufnehmen und somit den Puls erkennen. Deutlich wird dieses beim Betrachten des folgenden Oszilloskop-Bildes.


DS1Z QuickPrint1.png


Dieses zeigt auf der Y-Achse die Veränderung der Spannung am Fototransistor - somit die Helligkeitsveränderungen hervorgerufen durch das fließende Blut. Die oben gekennzeichneten Spitzen ergeben somit das Schlagen vom Herz. Rechnet man nun die registrierten Schläge pro aufgenommener Zeit, so kommt man auf einen Puls von ca. 71 Schläge/Minute (bpm)


Wie man auf dem oberen Oszilloskop-Bild zudem sehen kann, ist das aufgenommene Signal relativ klein bzw. der Transistor sehr empfindlich, um das schwache Signal aufnehmen zu können.Um ein optimales Ergebnis zu erhalten, empfehlen wir das Modul zum messen so vorzubereiten, wie im folgenden Bild gezeigt:

KY-0039 1.jpg


Zudem sollte beim messen am besten der kleine Finger verwendet werden, sowie darauf geachtet werden, dass zwischen Diode und Transistor kein blockierender Knochen sondern eher größenteils die Haut aufgenommen wird.


KY-0039 2.jpg



Pin-Belegung

3 G V S.png

Codebeispiel Arduino

Das folgende Code-Beispiel stammt aus der Feder von Dan Truong, welcher diesen Code unter [Link] veröffentlicht hat. Dieser steht unter der MIT OpenSource Lizenz zur Verfügung. Die unten stehende Version ist die übersetzte deutsche Fassung - das original steht unten zum Download zur Verfügung.


////////////////////////////////////////////////////////////////////////
/// 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)
int rawValue;


bool
heartbeatDetected(int IRSensorPin, int delay)
{
  static int maxValue = 0;
  static bool isPeak = false;
  HBDEBUG(Serial.print(maxValue); Serial.print("xp, "));
  
  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, "));
    rawValue = rawValue *4L;
    HBDEBUG(Serial.print(rawValue); Serial.print("rw, "));
  }
  
  // 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;
      HBDEBUG(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;
      Serial.println(rawValue);
  if (heartbeatDetected(analogPin, delayMsec)) {
    heartRateBPM = 60000 / beatMsec;
    digitalWrite(ledPin,1);

    // Print msec/beat and instantaneous heart rate in BPM
    Serial.print(rawValue);
    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;
}