Multi Function Shield mit Modul KY-039 als Pulsmesser verwenden

Das Multi Function Shield, das ich ja bereits vorgestellt habe und das mittlerweile ja auch um einen Drehgeber erweitert wurde, bietet mit der Möglichkeit zur einfachen Anzeige von Daten auf seinem 4-fach-7-Segment-Display und den freien Anschlusspins eine gute Grundlage, Sensoren ausprobieren.

Ein Bauteil meiner 37-in-one-Sensoren-Bulk-Bestellung (natürlich ohne Beschreibung, nicht mal auf chinesisch) mit 2 klaren LEDs (eine rund, eine rechteckig) gab mir Rätsel auf, bis ich es auf einem Foto wiedererkennen konnte: Das Modul KY-039 dient zur Pulsmessung.

Hardware: Modul KY-039


Das Modul kam "zusammengefaltet" bei mir an. Der runde LED-Körper lag mit dem Kopf auf dem eckigen "LED-Körper" auf, der wiederum um die Ecke der Platine gefaltet war.

Wozu war dieses Modul bloß gut? Es hatte keine Bezeichnung und schon gar keine Beschreibung. Zuerst einmal auseinanderfalten. Die 5mm LED stellte sich durch einen Test mit der Kamera schnell als Infrarot-LED heraus, die IR-Licht abgibt. Die kleine rechteckige LED machte sich verdächtig, weil sie die Data-Leitung beeinflußt, je nachdem ob Licht auf sie fällt. Und stellte sich schließlich als Fototransistor heraus.

Also haben wir es hier mir einer Infrarot-Lichtschranke zu tun, war mein erster Gedanke. Und so in der Art ist das schon richtig. Denn der eigentliche Zweck des Moduls ist die Pulsmessung, die auf folgende Weise funktioniert:

Die Fingerkuppe gehört zwischen die kleine, runde Erhebung des Fototransistors und die LED. Die LED sendet Licht durch den Finger und der Fototransistor fängt dieses auf. Nur wie soll das bei der Pulsmessung helfen? Nun, es ist so, dass im Finger Blutgefäße sind, die sich mit jedem Herzschlag ausdehnen und wieder zusammenziehen - deshalb können wir auch einen Puls am Handgelenk oder am Hals erfühlen - hier bewegt sich etwas. Je nachdem, in welchem Zustand das Blutgefäßt in der Fingerkuppe gerade ist, lässt es mehr oder weniger Licht hindurch. Das ist zwar minimal, aber messbar.


Allerdings ist das vorliegende Modul alles andere als ideal dafür gebaut. Streulicht von den Seiten sollte tunlichst nicht auf den Fototransistor fallen, das würde die Daten verfälschen. Darum habe ich ihn auf der Rückseite mit schwarzem Isolierband beklebt.

Desweiteren ist es sicher auch nicht gut, wenn man einen zusätzlichen Widerstand ins Spiel bringt, nämlich den Finger, den man ja irgendwo ablegen muss. Und da sind die Leiterbahnen und Kontakte der Platine sicher kein guter Platz - es sei denn, man isoliert diese auch. Was ich getan habe.

Das Modul wird wie folgt an das Multi Function Shield angeschlossen (wie abgebildet Ausgänge rechts, von oben nach unten): Modul KY-039 Kabelfarbe MFS/Arduino (GND) schwarz GND (3x4 Header) (+5V) rot +5V (3x4 Header) (DATA) grün A5 (3x4 Header) Um die Sensordaten zu analysieren, benutzt man am besten den Serial Plotter aus der Arduino IDE, der einem eine kontinuierliche Kurve des ausgegeben Wertes anzeigt, was man z. B. mit Serial.println (analogRead(A5)); erreichen kann. Wenn das Modul angeschlossen ist, man aber keinen Finger eingeschoben hat, dann sieht die Kurve so aus:



Mit der Fingerkuppe am richtigen Platz ergibt sich dann idealerweise das folgende Bild:



Hier ist eine schöne Kurve zu erkennen, die den Herzschlag abbildet. Das ist gar nicht so einfach hinzubekommen, denn man muss den Finger absolut ruhig halten. Drückt man ein bisschen fester (oder weniger fest) auf, dann springt die Kurve gleich in einen anderen Bereich fort und verschiebt sich um hunderte Einheiten. Außerdem muss die IR-LED im richtigen Winkel auf den Phototransistor "scheinen" und der Finger an der richtigen Position sein (pulsierendes Blutgefäß dazwischen).

Das ist auch das größte Manko des Moduls: es ist nicht idotensicher und deshalb auch nicht sonderlich genau. Man muss quasi mit dem Plotter die Fingerhaltung üben, um zu verwertbaren Ergebnissen zu kommen.

Wird der Finger ruhig gehalten und bekommt man solch eine schöne Kurve, dann ist der Rest zur Pulsanzeige nicht schwierig: man misst die Zeitspanne zwischen zwei Peaks und rechnet diese in Einheiten pro Minuten um, in der der Puls normalerweise angegeben wird.

Software

Da diese Ideal-Kurve aber keinesfalls Standard ist bei diesem Sensormodul, muss man versuchen, den Rest per Software auszugleichen, indem man versucht, die Kurve so gut es geht, zu erkennen und gültige Wiederholungen zu erkennen. Mein Programm misst über einen bestimmten, wiederkehrenden Zeitraum die Minimal und Maximalwerte und schaut sich die Spanne an. Ist diese Spanne (also der Unterschied zwischen Minimum und Maximum) in dem für die Fingermessung üblichem Rahmen, dann wird genauer hingeschaut und ausgewertet, in welcher Hälfte dieser Spanne sich die Kurve über die letzten drei Messungen befand. Wird hier nach einer oberen Kurvenposition eine untere festgestellt, dann wird das als ein Puls gewertet (wenn der letzte nicht kurz zuvor war, um Doppler auszuschließen )und ein Piepton ausgegeben. Der Abstand zwischen zwei Pulsen ergibt den Plus pro Minute-Wert, der errechnet und auf dem Display ausgegeben wird.

Ist der gemessene Wert außerhalb der Spanne, dann wird "FNGR" anngezeigt, kurz für "bitte Finger positionieren". Liegt der Wert im Bereich, leuchtet die erste LED. Befindet sich der Wert in der unteren Hälfte, leuchtet LED 2. In der oberen Hälfte erlischt dann LED 2 und die dritte leuchtet.

Wen das Gepiepe nervt, drückt Taster1, um den Ton ein- und auszuschalten.

Auch diesmal gibt es ein kleines Video, was das Programm macht:



Wie bereits erwähnt. Das Modul KY-039 ist nicht die beste Wahl für eine Pulsmessung, aber dafür eine sehr günstige.

Source-Code

Wer das selbst nachbasteln möchte, hier ist der Source-Code für das gezeigte Programm:

//////////////////////////////////////////////////////// // (C) 2018 by Oliver Kuhlemann // // Bei Verwendung freue ich mich über Namensnennung, // // Quellenangabe und Verlinkung // // Quelle: http://cool-web.de/arduino/ // //////////////////////////////////////////////////////// #include <TimerOne.h> // für Timings und Interrupts #include <MultiFuncShield.h> // API für das Multi Function Shield #define PinData A5 // wo ist Data angeschlossen? #define DurPause 40 // Pause in ms zwischen den Messungen #define ResetAfterCount 60 // min/max neu einmessen nach n Durchgängen #define SpanneMin 3 // ab und bis ... #define SpanneMax 12 // wievielen Einheiten ist die Spanne für Messung gültig? #define UngueltigUnterWert 500 #define UngueltigUeberSpannweite 50 void setup() { Timer1.initialize(); MFS.initialize(&Timer1); // initialize multi-function shield library pinMode (PinData, INPUT); Serial.begin (115200); } void loop() { byte btn = 0; int wert = 0; int wertMin = 1023; int wertMax = 0; int wertMid = 511; int wertWid = 0; int cnt = 0; boolean silence = false; long peak = 0; long peakBefore = 0; int puls = 0; boolean triggered = false; int last[3] = {500,500,500}; MFS.beep(1, 5, 2); // bereit while (1) { if (MFS.getButton() == BUTTON_1_PRESSED) { silence = !silence; if (silence) { MFS.write ("ton-"); delay(1000); } else { MFS.write ("ton+"); delay(1000); } } cnt++; wert = analogRead(PinData); if (wert < wertMin) wertMin = wert; if (wert > wertMax) wertMax = wert; wertMid = wertMax - (wertMax - wertMin) / 2; wertWid= (wertMax - wertMin); last[2]=last[1]; last[1]=last[0]; last[0]=wert; Serial.println (wert); // Plotter if (cnt > ResetAfterCount || cnt == 0) { // neuen Wertebereich festlegen cnt=0; wertMin = 1023; wertMax = 0; triggered = false; //MFS.writeLeds(LED_1, OFF); MFS.writeLeds(LED_2, OFF); MFS.writeLeds(LED_3, OFF); } if ( wert < UngueltigUnterWert || wertWid > UngueltigUeberSpannweite ) { // Finger weg? neu einmessen MFS.write("fngr"); wertMin = 1023; wertMax = 0; triggered = false; MFS.writeLeds(LED_1, OFF); MFS.writeLeds(LED_2, OFF); MFS.writeLeds(LED_3, OFF); } else if ( wertWid >= SpanneMin and wertWid <= SpanneMax) { // Schwankung im erlaubten Bereich MFS.writeLeds(LED_1, ON); // solange in der unteren Hälfte if (wert <= wertMid && last[0] <= wertMid && last[1] <= wertMid && last[2] <= wertMid) { MFS.writeLeds(LED_2, ON); MFS.writeLeds(LED_3, OFF); triggered=false; } else { // obere Hälfte MFS.writeLeds(LED_2, OFF); MFS.writeLeds(LED_3, ON); if (!triggered) { peak=millis(); puls = 60000 / (peak - peakBefore); if (puls < 200) { // doppler ignorieren if (!silence) MFS.beep(1); MFS.write (puls); peakBefore=peak; } triggered=true; } } } delay(DurPause); } } Mit den Define-Konstanten am Anfang des Codes kann man Feintuning betreiben, falls sich das eigenen KY-039-Modul etwas unterschiedlich verhalten sollte: Ist es nicht ganz einfach, die richtigen Werte zu finden. Man sollte nur in kleinen Dimensionen ändern und am besten aufschreiben, was man getan hat, um es gegebenenfalls wieder zurück ändern zu können.