Änderungen

KY-039 Herzschlag Sensor Modul

10.160 Byte hinzugefügt, 15:40, 29. Apr. 2016
/* Codebeispiel Arduino */
==Codebeispiel Arduino==
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 [[http://opensource.org/licenses/MIT |MIT OpenSource Lizenz zur ]] 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. <pre class="brush:cpp">////////////////////////////////////////////////////////////////////////
/// Copyright (c)2015 Dan Truong
/// Permission is granted to use this software under the MIT
/// KY039 Arduino Heartrate Monitor V1.0 (April 02, 2015)
////////////////////////////////////////////////////////////////////////
 
// German Comments by Joy-IT
 
////////////////////////////////////////////////////////////////////////
/// @param[in] IRSensorPin Analog pin on which IR detector is connectedPI an welchen der Sensor angeschlossen ist/// @param[in] delay (msec) delay between calls to this methodDie Verzoegerung zwischen den Aufrufen der Abtastfunktion. It is/// best to call it at least 5 times per beat Die besten Ergebnisse erhaelt man, akawenn man 5 mal Pro Herzschlag abtastet./// no slower than 150msec for 70bpmNicht langsamer als 150mSec für z. An ideal valueB. 70 BPM Puls/// is 60ms or faster to handle up to Besser waere 60 mSec für z.B. bis zu einen Puls von 200 BPM.
///
/// @briefKurzbeschreibung/// True if heartbeat is detected on the sensorDieser Code stellt eine sog. Peak-Detection dar./// This code is trivial and just does a peak detectionEs wird kein Herzschlagverlauf aufgezeichnet, instead ofsondern es/// 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 constantswird innerhalb der aufgezeichneten Daten nach "Peaks" (Spitzen) gesucht, somewhat independant of the sleep/// delay used in the main loopund per LED angezeigt. Otherwise if maxValue decays too slowMittels der bekannten Delay Abstaende, kann somit/// or too fast, it causes glitches and false beat detectiongrob der Puls errechnet werden.
////////////////////////////////////////////////////////////////////////
#define HBDEBUG(i) i//#define HBDEBUG(i)
int rawValue;
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 intHier wird der aktuelle Spannungswert am Fototransistor ausgelesen und in der rawValue-Variable zwischengespeichert
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 whackSollte der aktuelle Wert vom letzten maximalen Wert zu weit abweichen // (z.B. da der Finger neu aufgesetzt oder weggenommen wurde) // Just reset max to a new baselineSo wird der MaxValue resetiert, um eine neue Basis zu erhalten. 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 oneHier 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;
}
// Only return true once per peak.Zum erkannten Peak soll nur ein Herzschlag zugewiesen werden
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 shiftingHierbei wird der maximale Wert bei jeden Durchlauf // Note that it may take a few seconds to re-detectetwas wieder herabgesetzt. Dies hat den Grund, dass // the signal when sensor is pushed on meatier partnicht nur der Wert sonst immer stabil bei jedem Schlag // of the finger. Another way would be to track howgleich oder kleiner werden wuerde, sondern auch, // long since last beat, and if over 1sec, resetfalls der Finger sich minimal bewegen sollte und somit // maxValue, or to use derivatives to remove DC biasdas Signal generell schwaecher werden wuerde.
maxValue-=(1000/delay);
}
HBDEBUG(Serial.print("\n"));
return result;
}
void setup()
{
// Built-in arduino board pin for the display Die eingebaute Arduino LED(Digital 13), wird hier zur Ausgabe genutzt
pinMode(ledPin,OUTPUT);
// Init serial consoleSerielle Ausgabe Initialisierung
Serial.begin(9600);
Serial.println("Heartbeat detection sample codeDetektion Beispielcode.");
}
const int delayMsec = 60; // 100msec per sample
// The main loop blips the Das Hauptprogramm hat zwei Aufgaben: // - Wird ein Herzschlag erkannt, so blinkt die LED and computes BPMs on serial portkurz auf// - Der Puls wird errechnet und auf der serriellen Ausgabe ausgegeben
void loop()
{
if (heartbeatDetected(analogPin, delayMsec)) {
heartRateBPM = 60000 / beatMsec;
// LED-Ausgabe bei Herzschlag
digitalWrite(ledPin,1);
// Print msec/beat and instantaneous heart rate in BPMSerielle Datenausgabe
Serial.print(rawValue);
Serial.print(", ");
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;
}
</pre>
 
'''Anschlussbelegung Arduino:'''
 
{| style="height: 58px; padding-left: 30px;" width="228"
|-
||Sensor Signal
||=
||[Pin 0]
|-
||Sensor +V
||=
||[5V]
|-
||Sensor -
||=
||[Pin GND]
|}
 
'''Beispielprogramm Download<br />'''
 
[[Medium:KY-039-HeartBeatDetector_original_byDanTruong.zip|KY-039-HeartBeatDetector original by DanTruong]]
----
[[Medium:KY-039-HeartBeatDetector_GermanComments_byJoyIt.zip|KY-039-HeartBeatDetector deutsche Version by Joy-It]]
 
==Codebeispiel Raspberry Pi==
<span style="color: #ff6600;">!! <span style="color: #ff0000;">Achtung</span> !! <span style="color: #99cc00;">Analoger Sensor</span>  !! <span style="color: #ff0000;">Achtung</span> !!</span>
 
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 [<span style="color: #99cc00;">EIN</span>] Knopf losgelassen [<span style="color: #ff0000;">AUS</span>]], 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|'''KY-053'''   Analog Digital Converter]]
 
<span style="color: #ff6600;">!! <span style="color: #ff0000;">Achtung</span> !! <span style="color: #99cc00;">Analoger Sensor</span>  !! <span style="color: #ff0000;">Achtung</span> !!</span>
 
 
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-Raspberry-Pi-Python-Code https://github.com/adafruit/Adafruit-Raspberry-Pi-Python-Code]] unter der BSD-Lizenz [[https://opensource.org/licenses/BSD-3-Clause Link]] veröffentlicht. Die benötigten Libraries sind im unteren Download-Paket enthalten.
 
 
 
<pre class="brush:py">#!/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
###
### Parts of Code based on Dan Truong's KY039 Arduino Heartrate Monitor V1.0
### [https://forum.arduino.cc/index.php?topic=209140.msg2168654] Message #29
#############################################################################################################
 
 
# Dieser Code nutzt die ADS1115 und die I2C Python Library fuer den Raspberry Pi
# Diese ist unter folgendem Link unter der BSD Lizenz veroeffentlicht
# [https://github.com/adafruit/Adafruit-Raspberry-Pi-Python-Code]
from Adafruit_ADS1x15 import ADS1x15
from time import sleep
 
# Weitere benoetigte Module werden importiert und eingerichtet
import time, signal, sys, os
import RPi.GPIO as GPIO
GPIO.setmode(GPIO.BCM)
GPIO.setwarnings(False)
 
# Benutzte Variablen werden initialisiert
beatsPerMinute = 0
isPeak = False
result = False
delayTime = 0.01
maxValue = 0
schwelle = 25
beatTime = 0
oldBeatTime = 0
 
# Adresszuweisung ADS1x15 ADC
 
ADS1015 = 0x00 # 12-bit ADC
ADS1115 = 0x01 # 16-bit
 
# Verstaerkung (Gain) wird ausgewaehlt
gain = 4096 # +/- 4.096V
# gain = 2048 # +/- 2.048V
# gain = 1024 # +/- 1.024V
# gain = 512 # +/- 0.512V
# gain = 256 # +/- 0.256V
 
# Abtasterate des ADC (SampleRate) wird ausgewaehlt
sps = 8 # 8 Samples pro Sekunde
# sps = 16 # 16 Samples pro Sekunde
# sps = 32 # 32 Samples pro Sekunde
# sps = 64 # 64 Samples pro Sekunde
# sps = 128 # 128 Samples pro Sekunde
# sps = 250 # 250 Samples pro Sekunde
# sps = 475 # 475 Samples pro Sekunde
# sps = 860 # 860 Samples pro Sekunde
 
# ADC-Channel (1-4) wird ausgewaehlt
adc_channel = 0 # Channel 0
# adc_channel = 1 # Channel 1
# adc_channel = 2 # Channel 2
# adc_channel = 3 # Channel 3
 
# Hier wird der ADC initialisiert - beim KY-053 verwendeten ADC handelt es sich um einen ADS1115 Chipsatz
adc = ADS1x15(ic=ADS1115)
 
# Hier wird der Ausgangs-Pin deklariert, an dem die LED angeschlossen ist.
LED_PIN = 24
GPIO.setup(LED_PIN, GPIO.OUT, initial= GPIO.LOW)
 
 
#############################################################################################################
 
# Hier wird der Ausgangs-Pin deklariert, an dem der Buzzer angeschlossen ist.
def heartBeatDetect(schwelle):
global maxValue
global isPeak
global result
global oldBeatTime
 
# Hier wird der aktuelle Spannungswert am Fototransistor ausgelesen
# und in der rawValue - Variable zwischengespeichert
# Mit "adc_channel" wird der am ADC angeschlossene Channel ausgewaehlt
rawValue = adc.readADCSingleEnded(adc_channel, gain, sps)
 
# Reset der Ergebnis Variable
if result == True:
result = False
 
# 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 * 4 < maxValue: maxValue = rawValue * 0.8; # Hier wurd der eigentliche Peak detektiert. Sollte ein neuer RawValue groeßer sein # als der letzte maximale Wert, so wird das als Spitze der aufgezeichneten Daten erkannt.
if rawValue > (maxValue - schwelle):
 
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 - schwelle:
isPeak = False
# Hierbei wird der maximale Wert bei jedem Durchlauf
# etwas wieder herabgesetzt. Dies hat den Grund, dass
# nicht nur der Wert sonst immer stabil bei jedem Schlag
# gleich oder kleiner als maxValue sein wuerde, sondern auch,
# falls der Finder sich minimal bewegen sollte und somit
# das Signal generell schwaecher sein sollte.
maxValue = maxValue - schwelle/2
 
# Wurde in der oberen Abfrage ein Herzschlag detektiert, so wird nun die Ausgabe freigegeben
if result == True:
 
# Berechnung des Puls
# Hierbei wird bei jedem registrierten Herzschlag die System-Zeit aufgenommen
# Beim naechsten Herzschlag wird dann die aktuelle Systemzeit mit der gespeicherten verglichen
# Die Differenz der beiden ergibt dann die Zeit zwischen den Herz-Schlaegen
# womit man dann auch den Puls berechnen kann.
beatTime = time.time()
timedifference = beatTime - oldBeatTime
beatsPerMinute = 60/timedifference
oldBeatTime = beatTime
 
# Neben der Berechnung des Puls, wird der Herzschlag auch auf eine LED als kurzes Aufblinken ausgegeben
GPIO.output(LED_PIN, GPIO.HIGH)
time.sleep(delayTime*10)
GPIO.output(LED_PIN, GPIO.LOW)
 
# Erechneter Puls wird der Funktion übergeben
return beatsPerMinute
 
#############################################################################################################
 
# ########
# Hauptprogrammschleife
# ########
# 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.
 
try:
while True:
time.sleep(delayTime)
beatsPerMinute = heartBeatDetect(schwelle)
if result == True:
print "---Herzschlag erkannt !--- Puls:", int(beatsPerMinute),"(bpm)"
 
 
 
except KeyboardInterrupt:
GPIO.cleanup()
</pre>
 
'''Anschlussbelegung Raspberry Pi:'''
 
Sensor KY-039
 
{| style="height: 85px; padding-left: 30px;" width="441"
|-
||Signal
||=
||Analog 0
||[Pin A0 (ADS1115 - KY-053)]
|-
||+V
||=
||3,3V
||[Pin 1]
|-
||GND
||=
||Masse
||[Pin 6]
|}
 
ADS1115 - KY-053:
 
{| style="height: 127px; padding-left: 30px;" width="436"
|-
||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'''
 
Zu starten mit dem Befehl:
 
<pre class="brush:bash">sudo python KY-0039_HeartBeatDetector.py
</pre>
Bürokrat, Administrator
611
Bearbeitungen