Industrielle Fertigung
Industrielles Internet der Dinge | Industrielle Materialien | Gerätewartung und Reparatur | Industrielle Programmierung |
home  MfgRobots >> Industrielle Fertigung >  >> Manufacturing Technology >> Herstellungsprozess

Von KY-039 zur Herzfrequenz

Komponenten und Verbrauchsmaterialien

Arduino UNO
× 1
KY-039 Herzschlagsensor
× 1
Jumper (generisch)
× 1

Über dieses Projekt

Im Set von 37 Sensoren für Arduino , es gibt einen Herzschlagsensor. Der Name verspricht zu viel. Die Leute neigen dazu zu denken, dass es eine digitale Zahl über I2C oder etwas Ähnliches liefert, eine Zahl, die die Herzschlagfrequenz ist. Was der Sensor liefert, ist nur ein "analoger" Wert von 0 bis 1023, der angibt, wie viel Infrarotlicht der Lichtsensor empfängt, oder tatsächlich wie viel etwas den Lichtsensor abschattet . Je höher der Wert, desto weniger Infrarotlicht.

Kurz gesagt:Legen Sie Ihren Finger zwischen die IR-LED und den Lichttransistor des Sensors. Ihr Herzschlag erweitert die Blutgefäße in Ihrem Finger, wodurch die Infrarotstrahlung gefiltert wird. Dadurch entsteht ein pulsierendes Signal.

In diesem Projekt beschreibe ich, wie dieses Signal in eine Herzschlagfrequenz wie 66 BPM (Beats per Minute) umgewandelt wird.

Die einfachen Schritte

Wenn Sie nur die Werte des KY-039-Sensors lesen und grafisch darstellen, erhalten Sie etwa Folgendes:

Die Werte sind ganzzahlige Werte. Nicht sehr genau. Berechnen Sie stattdessen einen Durchschnitt einer Reihe von ihnen und zeichnen Sie den Durchschnitt auf. Sie erhalten dies:

Hier sieht man schon den Puls des Herzens. Ermitteln Sie die Zeitdifferenz zwischen jedem signifikanten Anstieg des Pulses. Daraus kannst du die Herzfrequenz in BPM berechnen.

(Das kleine Zick-Zack-Muster im Bild oben ist auf künstliches Licht zurückzuführen, 50 Hz, eine andere Sache, mit der man sich beschäftigen muss.)

Schritte erklärt

Hier ist ein einfacher Code, um einfach alles auszugeben, was Sie vom KY-039-Sensor lesen:

 // Pulsmonitor Test Scriptint sensorPin =0;void setup () { Serial.begin (9600);}void loop () { while (1) { Serial.print (analogRead (sensorPin)); Serial.print ('\n'); }}  

Was Sie erhalten könnten, ist etwa so:

Da dies eine Bildunterschrift aus dem seriellen Monitorfenster ist, die die serielle Ausgabe Ihres Arduino bei 9600 Baud liest, wird der gesamte Prozess von Serial.print() . getaktet Funktion, die eine Rate zum Lesen und Plotten der Werte festlegt. Jedenfalls ist die Kurve sehr gezackt, da sie zwischen 360 und 383 schwankt und nur ganzzahlige Werte hat.

Glätten

Um eine glattere Ausgabe zu erhalten, nehmen Sie durchschnittlich etwa 20 letzte Messwerte vom Sensor. So mache ich es. Ich definiere eine Konstante, die mir sagt, wie viele Lesungen ich möchte:

#define samp_siz 20 

Dann habe ich ein Array mit dieser Anzahl von Messwerten:

int liest[samp_siz];  

Für jeden neuen Messwert ziehe ich den ältesten Messwert von einer Summe ab und addiere den neuesten Messwert zur Summe. Im Array ersetze ich den ältesten Messwert durch den neuesten Messwert.

 Leser =analogRead (sensorPin); // Sensorsumme lesen -=reads[ptr]; // den ältesten Messwert von der Summe subtrahieren +=Leser; // den neuesten Messwert zur Summe hinzufügen reads[ptr] =reader; // den neuesten Messwert im Array speichern last =float(sum) / samp_siz; // jetzt den Durchschnitt berechnen ptr++; // Aktualisieren Sie den Index für das Array, verwenden Sie ptr %=samp_siz; // es wird bei Bedarf bei 0 neu gestartet 

Bei einer Array-Größe von 20 und einer Baudrate von 9600 im seriellen Monitor könnte ich eine Darstellung wie diese erhalten:

Hier sehen Sie die tatsächlichen Herzschläge als steil ansteigende Kurve. Sie sehen aber auch ein kleines Zick-Zack-Muster. Der kleinere Zickzack kommt von meiner Küchenlampe, drei LED-Lampen beleuchten den Raum. Das Stromnetz in meinem Haus ist 240 V, 50 Hz AC. 50 mal pro Sekunde steigt also die Lichtintensität an, anscheinend auch im IR-Band. Ich möchte das 50 Hz-Rauschen glätten. Es sollte funktionieren, wenn ich über einen Zeitraum von 20 ms Werte vom Sensor auslese und einen Durchschnitt aller Werte nehme. Mal sehen...

 n =0; start =millis(); Leser =0.; do { Leser + =analogRead (sensorPin); // Werte lesen und hinzufügen... n++; jetzt =millis(); } while (jetzt  

Mit diesem Ausschnitt nehme ich die Sensormesswerte in 20 ms-Blöcken auf, wodurch das durch Kunstlicht verursachte 50 Hz-Flimmern ausgeglichen wird. Wenn Sie in einem Land mit 60 Hz leben, verwenden Sie stattdessen 16,67 ms-Chunks. Oder 16667µs.

Da ich die Kurve bereits in 20-ms-Abschnitten glätte, brauche ich das Array, das ich zuvor verwendet habe, eigentlich nicht, aber da es da ist und leicht in der Größe geändert werden kann, lasse ich es dort. Und die Verwendung einer Array-Größe von 5 scheint das letzte störende Rauschen auszugleichen. Das habe ich jetzt:

Das letzte, was ich tun muss, ist, irgendeinen Teil des sich wiederholenden Musters zu erkennen. Da die Steigung regelmäßiger ist, gehe ich dafür. Beachten Sie, dass die Werte der y-Achse in allen Diagrammen sehr unterschiedlich sind. Auf absolute Werte kann ich mich wirklich nicht verlassen. Ich kann mich nur auf das Steigen und Fallen der Kurve verlassen. Mathematiker würden über die Ableitung sprechen. Ich bin zufrieden, wenn ich n finde aufeinanderfolgend steigende Werte, wobei n könnte ein praktischer einstellbarer Wert sein. Ich beginne mit 5. Dafür habe ich den rise_threshold im Code definierte Konstante. Wenn ich 5 aufeinanderfolgende steigende Werte finde, weiß ich, dass ich am unteren Ende der Kurve nach oben bin. Ich nehme mir Zeit. Ich warte auf eine fallende Kurve, dann warte ich auf die nächsten 5 steigenden Werte und notiere die Zeit. Dann drucke ich den entsprechenden BPM aus.

Ich habe einen Test gemacht und gezählt wie viele aufeinanderfolgend aufstehen Werte dort sind in die Kurve und gefunden aus dort waren zwischen 10 und 15. Also wenn Ich zählen zu 5, Ich wird die meisten sicher wissen Ich habe gefunden die starten von die Herzschlag.

Da ich nur nach jedem Herzschlag drucke, wird nicht viel gedruckt. Es bleibt mehr Zeit zum Auslesen des Sensors. Es kann sein, dass ich häufiger Rauschen höre, das ich nicht sehe, weil der Plotter nicht eingeschaltet ist. Mal sehen, wie es funktioniert.

Der endgültige Code

#define samp_siz 4#define rise_threshold 5// Pulsmonitor Test Scriptint sensorPin =0;void setup() { Serial.begin(9600);}void loop (){ float reads[samp_siz], sum; long int jetzt, ptr; Float zuletzt, Leser, Start; float first, second, Third, before, print_value; bool steigt; int rise_count; int n; long int last_beat; for (int i =0; i  before) { rise_count++; if (!rising &&rise_count> rise_threshold) { // Ok, wir haben eine steigende Kurve erkannt, was impliziert ein Herzschlag. // Zeichne die Zeit seit dem letzten Schlag auf, verfolge die beiden vorherigen // Zeiten (erster, zweiter, dritter), um einen gewichteten Durchschnitt zu erhalten. // Das steigende Flag verhindert, dass wir denselben Anstieg erkennen // mehr als einmal steigend =wahr, zuerst =millis () - letzter_Beat; last_beat =millis(); // Berechnen Sie den gewogenen Durchschnitt der Herzfrequenz // nach den drei letzten Schlägen print_value =60000. / (0,4 * erster + 0,3 * zweiter + 0,3 * dritter); Serial.print (print_value); Serial.print ('\n'); dritte =zweite; zweite =erste; } } else { // Ok, die Kurve fällt steigend =false; rise_count =0; } vorher =zuletzt; ptr++; ptr %=samp_siz; }}  

Es funktioniert ziemlich gut. Hier ist ein Video.

Beachten Sie, dass die winzige RX-LED auf dem Arduino synchron mit meinem Herzen blinkt. Ganz einfach, weil bei einem Herzschlag die Rate berechnet und auf die Seriennummer gedruckt wird, die die LED blinkt. Wenn sich der Finger ein wenig bewegt, werden Fehleranzeigen angezeigt.

Weiterentwicklung

Im Moment wird die gedruckte Rate basierend auf den letzten drei Schlägen berechnet. Es könnte jedoch angemessener sein, es basierend auf einer Periode von beispielsweise 15 s zu berechnen. Ich könnte 15 aufeinanderfolgende Kurswerte speichern, den Mittelwert berechnen, dann die fünf Werte weglassen, die am weitesten vom Mittelwert entfernt sind, und einen neuen Mittelwert berechnen. Dies würde eine ziemlich zuverlässige und stetige Messung der Herzfrequenz ergeben.

Ich habe den Sensor nur an meiner Frau und an mir getestet. Jeder Schritt zur Verbesserung des Signals habe ich basierend auf den vorherigen Messwerten gemacht. Jemand anderes könnte eine andere Art von Herzschlag haben, der eine anders geformte Kurve verursacht, die einen anderen Ansatz benötigt, um den Schlag zu finden. Vielleicht ist es die fallende Kurve, die leichter zu erkennen ist. Oder ganz oben. Und was passiert, wenn der Puls 180 - 200 BPM beträgt? Die steigende Kurve zu finden könnte schwieriger sein.

Code

  • Endgültige Version
Endgültige VersionC/C++
Das Programm liest den Heartbeat und druckt die Rate im seriellen Fenster.
#define samp_siz 4#define rise_threshold 4// Pulse Monitor Test Scriptint sensorPin =0;void setup() { Serial.begin(9600);}void loop (){ float liest [samp_siz], Summe; long int jetzt, ptr; Float zuletzt, Leser, Start; float first, second, Third, before, print_value; bool steigt; int rise_count; int n; long int last_beat; for (int i =0; i  before) { rise_count++; if (!rising &&rise_count> rise_threshold) { // Ok, wir haben eine steigende Kurve erkannt, was impliziert ein Herzschlag. // Zeichne die Zeit seit dem letzten Schlag auf, behalte die zwei vorherigen // Zeiten (erste, zweite, dritte) im Auge, um einen gewichteten Durchschnitt zu erhalten. // Das steigende Flag verhindert, dass wir denselben Anstieg mehr als einmal erkennen. steigend =wahr; zuerst =millis() - letzter_Beat; last_beat =millis(); // Berechnen Sie den gewogenen Durchschnitt der Herzfrequenz // nach den drei letzten Schlägen print_value =60000. / (0,4 * erster + 0,3 * zweiter + 0,3 * dritter); Serial.print (print_value); Serial.print ('\n'); dritte =zweite; zweite =erste; } } else { // Ok, die Kurve fällt steigend =false; rise_count =0; } vorher =zuletzt; ptr++; ptr %=samp_siz; }} 

Schaltpläne


Herstellungsprozess

  1. Farbsensor – Funktionsweise und Anwendungen
  2. OPT3007 Ultradünner Umgebungslichtsensor
  3. Streamen von Sensordaten von einer ppDAQC-Pi-Platte mit InitialState
  4. Raspberry Pi Temperatur- und Lichtsensor
  5. Solar-Einfahrtsbeleuchtung zum MSP430 Wireless Sensor Node
  6. Sprach– und SMS–aktivierter Lichtsensor mit Raspberry Pi und Twilio
  7. Windows 10 IoT Core – Lesen von Herzfrequenzpulsen
  8. Raspberry Pi-Lichtsensor:Eine einfache LDR-Anleitung
  9. Digitaler Lichtsensor
  10. Ferngesteuerter Herzfrequenzmesser