KY-039 Herzschlag Sensor Modul
Aus SensorKit X40 Wiki
Inhaltsverzeichnis
Bild
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.
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.
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 in den folgenden Bildern gezeigt:
Um die Empfindlichkeit des Sensors zu erhöhen, empfehlen wir den Sensor mittels eines Pflasters / Klebebandes / Isolierbandes an der Fingerkuppe zu fixieren.
Der Herzschlag wird besonders gut aufgezeichnet/registriert, wenn sich der Sensor über einen größeren Blutgefäß befindet - um das Signal zu verbessern, empfehlen wir zudem die Position des Sensors gegeben falls auf der Fingerkuppe zu verändern.
Pin-Belegung
Kabelbelegung:
- Grau -> GND
- Weiß -> +V
- Schwarz -> Signal
Codebeispiel Arduino
Das folgende Code-Beispiel stammt aus der Feder von Dan Truong, welcher diesen Code unter [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.
Dieser Code stellt eine sog. Peak-Detection dar. Es wird kein Herzschlagverlauf aufgezeichnet, sondern es wird innerhalb der aufgezeichneten Daten nach "Peaks" (Spitzen) gesucht, als Herschlag erkannt und per LED angezeigt. Mittels der bekannten Delay Abstände, kann somit grob der Puls errechnet werden.
Wird der Finger beim messen neu aufgelegt oder stark bewegt, so kann es etwas dauern, bis das Programm sich auf die neue Gegebenheit kalibriert und wieder den richtigen Wert ausgibt.
//////////////////////////////////////////////////////////////////////// /// 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) //////////////////////////////////////////////////////////////////////// // German Comments by Joy-IT //////////////////////////////////////////////////////////////////////// /// @param[in] IRSensorPin Analog PI an welchen der Sensor angeschlossen ist /// @param[in] delay (msec) Die Verzoegerung zwischen den Aufrufen der Abtastfunktion. // Die besten Ergebnisse erhaelt man, wenn man 5 mal Pro Herzschlag abtastet. /// Nicht langsamer als 150mSec für z.B. 70 BPM Puls /// Besser waere 60 mSec für z.B. bis zu einen Puls von 200 BPM. /// /// @Kurzbeschreibung /// Dieser Code stellt eine sog. Peak-Detection dar. /// Es wird kein Herzschlagverlauf aufgezeichnet, sondern es /// wird innerhalb der aufgezeichneten Daten nach "Peaks" (Spitzen) gesucht, /// und per LED angezeigt. Mittels der bekannten Delay Abstaende, kann somit /// grob der Puls errechnet werden. //////////////////////////////////////////////////////////////////////// int rawValue; bool heartbeatDetected(int IRSensorPin, int delay) { static int maxValue = 0; static bool isPeak = false; bool result = false; rawValue = analogRead(IRSensorPin); // Hier wird der aktuelle Spannungswert am Fototransistor ausgelesen und in der rawValue-Variable zwischengespeichert rawValue *= (1000/delay); // Sollte der aktuelle Wert vom letzten maximalen Wert zu weit abweichen // (z.B. da der Finger neu aufgesetzt oder weggenommen wurde) // So wird der MaxValue resetiert, um eine neue Basis zu erhalten. if (rawValue * 4L < maxValue) { maxValue = rawValue * 0.8; } // Detect new peak if (rawValue > maxValue - (1000/delay)) { // Hier wird der eigentliche Peak detektiert. Sollte ein neuer RawValue groeßer sein // als der letzte maximale Wert, so wird das als Spitze der aufgezeichnten Daten erkannt. if (rawValue > maxValue) { maxValue = rawValue; } // Zum erkannten Peak soll nur ein Herzschlag zugewiesen werden if (isPeak == false) { result = true; } isPeak = true; } else if (rawValue < maxValue - (3000/delay)) { isPeak = false; // Hierbei wird der maximale Wert bei jeden Durchlauf // etwas wieder herabgesetzt. Dies hat den Grund, dass // nicht nur der Wert sonst immer stabil bei jedem Schlag // gleich oder kleiner werden wuerde, sondern auch, // falls der Finger sich minimal bewegen sollte und somit // das Signal generell schwaecher werden wuerde. maxValue-=(1000/delay); } return result; } //////////////////////////////////////////////////////////////////////// // Arduino main code //////////////////////////////////////////////////////////////////////// int ledPin=13; int analogPin=0; void setup() { // Die eingebaute Arduino LED (Digital 13), wird hier zur Ausgabe genutzt pinMode(ledPin,OUTPUT); // Serielle Ausgabe Initialisierung Serial.begin(9600); Serial.println("Heartbeat Detektion Beispielcode."); } const int delayMsec = 60; // 100msec per sample // Das Hauptprogramm hat zwei Aufgaben: // - Wird ein Herzschlag erkannt, so blinkt die LED kurz aufgesetzt // - Der Puls wird errechnet und auf der serriellen Ausgabe ausgegeben. void loop() { static int beatMsec = 0; int heartRateBPM = 0; if (heartbeatDetected(analogPin, delayMsec)) { heartRateBPM = 60000 / beatMsec; // LED-Ausgabe bei Herzschlag digitalWrite(ledPin,1); // Serielle Datenausgabe Serial.print("Puls erkannt: "); Serial.println(heartRateBPM); beatMsec = 0; } else { digitalWrite(ledPin,0); } delay(delayMsec); beatMsec += delayMsec; }
Anschlussbelegung Arduino:
Sensor Signal | = | [Analog Pin 0] |
Sensor +V | = | [5V] |
Sensor - | = | [Pin GND] |
Beispielprogramm Download
KY-093-HeartBeatDetector original by DanTruong
KY-039-HeartBeatDetector deutsche Version by Joy-It
KY-039-HeartBeatDetector english version by Joy-It
Codebeispiel Raspberry Pi
!! Achtung !! Analoger Sensor !! Achtung !!
Der Raspberry Pi besitzt im Gegensatz zum Arduino keine analogen Eingänge bzw. es ist kein ADC (analog digital Converter) im Chip des Raspberry Pi's integriert. Dies schränkt den Raspberry Pi ein, wenn man Sensoren einsetzen möchte, wo nicht digital Werte ausgegeben werden [Spannungswert überschritten -> digital EIN | Spannungswert unterschritten -> digital AUS | Beispiel: Knopf gedrückt [EIN] Knopf losgelassen [AUS]], sondern es sich hier um einen kontinuierlichen veränderlichen Wert handeln sollte (Beispiel: Potentiometer -> Andere Position = Anderer Spannungswert)
Um diese Problematik zu umgehen, besitzt unser Sensorkit X40 mit dem KY-053 ein Modul mit 16 Bit genauen ADC, welches Sie am Raspberry nutzen können, um diesen um 4 analoge Eingänge erweitern zu können. Dieses wird per I2C an den Raspberry Pi angeschlossen, übernimmt die analoge Messung und gibt den Wert digital an den Raspberry Pi weiter.
Somit empfehlen wir, bei analogen Sensoren dieses Sets das KY-053 Modul mit dem besagten ADC dazwischenzuschalten. Nähere Informationen finden Sie auf der Informationsseite zum KY-053 Analog Digital Converter
!! Achtung !! Analoger Sensor !! Achtung !!
Das Programm sieht vor, dass im Abstand der eingestellten "delayTime" (Standard: 10ms) die Funktion zur Herzschlagdetektion aufgerufen wird. Wurde ein Herzschlag erkannt, so wird der Puls ausgegeben. Zusätzlich kann man am eingestellten LED_Pin (Standard: GPIO24) eine LED anschließen, um den detektierten Herzschlag auch visuell auszugeben.
Wird der Finger beim messen neu aufgelegt oder stark bewegt, so kann es etwas dauern (3-5 Sekunden), bis das Programm sich auf die neue Gegebenheit kalibriert und wieder den richtigen Wert ausgibt.
Das Programm nutzt zur Ansteuerung des ADS1115 ADC die entsprechenden ADS1x15 und I2C Python-Libraries der Firma Adafruit. Diese wurden unter dem folgenden Link https://github.com/adafruit/Adafruit_CircuitPython_ADS1x15] unter der MIT-Lizenz [Link] veröffentlicht. Die benötigten Libraries sind im unteren Download-Paket enthalten.
#!/usr/bin/python # coding=utf-8 ############################################################################################################# ### Copyright by Joy-IT ### Published under Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License ### Commercial use only after permission is requested and granted ### ### KY-053 Analog Digital Converter - Raspberry Pi Python Code Example ### ############################################################################################################# import time import board import busio import adafruit_ads1x15.ads1115 as ADS from adafruit_ads1x15.analog_in import AnalogIn # Create the I2C bus i2c = busio.I2C(board.SCL, board.SDA) # Create the ADC object using the I2C bus ads = ADS.ADS1115(i2c) # Create single-ended input on channels chan0 = AnalogIn(ads, ADS.P0) chan1 = AnalogIn(ads, ADS.P1) chan2 = AnalogIn(ads, ADS.P2) chan3 = AnalogIn(ads, ADS.P3) if __name__ == '__main__': # initialization GAIN = 2/3 curState = 0 thresh = 525 # mid point in the waveform P = 512 T = 512 stateChanged = 0 sampleCounter = 0 lastBeatTime = 0 firstBeat = True secondBeat = False Pulse = False IBI = 600 rate = [0]*10 amp = 100 lastTime = int(time.time()*1000) # Main loop. use Ctrl-c to stop the code while True: # read from the ADC Signal = chan0.value #TODO: Select the correct ADC channel. I have selected A0 here curTime = int(time.time()*1000) sampleCounter += curTime - lastTime; # # keep track of the time in mS with this variable lastTime = curTime N = sampleCounter - lastBeatTime; # # monitor the time since the last beat to avoid noise #print N, Signal, curTime, sampleCounter, lastBeatTime ## find the peak and trough of the pulse wave if Signal < thresh and N > (IBI/5.0)*3.0 : # # 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 and 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) and (Pulse == False) and (N > (IBI/5.0)*3.0) : Pulse = True; # set the Pulse flag when we think there is a pulse 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 i in range(0,10): # 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 continue # IBI value is unreliable so discard it # keep a running total of the last 10 IBI values runningTotal = 0; # clear the runningTotal variable for i in range(0,9): # 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! print ('BPM: {}'.format(BPM)) if Signal < thresh and Pulse == True : # when the values are going down, the beat is over 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 print ("no beats found") time.sleep(0.005)
Anschlussbelegung Raspberry Pi:
Sensor KY-039
Signal | = | Analog 0 | [Pin A0 (ADS1115 - KY-053)] |
+V | = | 3,3V | [Pin 1] |
GND | = | Masse | [Pin 6] |
ADS1115 - KY-053:
VDD | = | 3,3V | [Pin 01] |
GND | = | Masse | [Pin 09] |
SCL | = | GPIO03 / SCL | [Pin 05] |
SDA | = | GPIO02 / SDA | [Pin 03] |
A0 | = | s.o. | [Sensor: Signal] |
Beispielprogramm Download
KY-0039_RPi_HeartBeatDetector.zip
Zu starten mit dem Befehl:
sudo python3 KY-0039_HeartBeatDetector.py