Herzfrequenz messen mit dem KY-039 Arduino-Sensor
Komponenten und Zubehör
| Komponente | Menge |
|---|---|
| Arduino UNO | 1 |
| KY-039 Herzschlag-Sensor | 1 |
| Jumper-Kabel (beliebig) | 1 |
Über dieses Projekt
Im 37-Sensor-Kit für Arduino befindet sich ein „Herzschlag-Sensor“. Der Name verspricht zu viel: Er liefert keine digitale Herzfrequenz per I²C, sondern nur einen analogen Wert (0–1023), der angibt, wie viel Infrarotlicht der Fototransistor empfängt – also wie stark der Finger das Licht abschattet. Höherer Wert = weniger IR-Licht.
Funktionsprinzip: Man legt den Finger zwischen IR-LED und Fototransistor. Der Herzschlag erweitert die Blutgefäße im Finger, was die IR-Durchlässigkeit moduliert. Daraus entsteht ein pulsierendes Signal.
Dieses Projekt zeigt, wie man aus diesem Rohsignal eine Herzfrequenz in BPM (Schläge pro Minute) berechnet.
Die einfachen Schritte
Rohdaten direkt geplottet ergeben ein stark rauschendes Signal (Ganzzahlwerte, z. B. 360–383).
Bildet man einen gleitenden Mittelwert (z. B. über 20 Werte), wird der Puls sichtbar:
Die Zeitdifferenz zwischen zwei signifikanten Anstiegen ergibt die Herzfrequenz.
Hinweis: Das kleine Zickzack-Muster stammt von 50-Hz-Netzflackern (künstliches Licht).
Schritte im Detail
Rohdaten auslesen
int sensorPin = 0;
void setup() { Serial.begin(9600); }
void loop() {
while (1) {
Serial.print(analogRead(sensorPin));
Serial.print('\n');
}
}
Gleitender Mittelwert (Smoothing)
Array der letzten samp_siz Messwerte halten, Summe aktualisieren:
#define samp_siz 20
int reads[samp_siz];
int ptr = 0;
long sum = 0;
int reader = analogRead(sensorPin);
sum -= reads[ptr];
sum += reader;
reads[ptr] = reader;
float last = (float)sum / samp_siz;
ptr = (ptr + 1) % samp_siz;
Ergebnis: Deutlich glattere Kurve, aber noch 50-Hz-Rauschen.
50-Hz-Störunterdrückung durch 20-ms-Mittelung
In einem 20-ms-Fenster (eine Periode bei 50 Hz) alle Samples mitteln:
int n = 0;
unsigned long start = millis();
float reader = 0;
do {
reader += analogRead(sensorPin);
n++;
} while (millis() < start + 20);
reader /= n;
Bei 60 Hz entsprechend 16,67 ms verwenden. Danach reicht ein kleines Array (z. B. Größe 5) für finales Smoothing.
Peak-Detection (Anstiegserkennung)
Wir suchen rise_threshold (z. B. 5) aufeinanderfolgend steigende Werte. Das markiert den Fußpunkt der Pulswelle. Zeitstempel speichern, gewichtetes Mittel der letzten drei Intervalle bilden → BPM.
Finaler Code
#define samp_siz 4
#define rise_threshold 5
int sensorPin = 0;
void setup() {
Serial.begin(9600);
}
void loop() {
float reads[samp_siz], sum = 0;
long int now, ptr = 0;
float last, reader, start;
float first, second, third, before = 0, print_value;
bool rising = false;
int rise_count = 0;
int n;
long int last_beat = 0;
for (int i = 0; i < samp_siz; i++) reads[i] = 0;
while (1) {
// 20-ms-Mittelung gegen 50-Hz-Rauschen
n = 0;
start = millis();
reader = 0;
do {
reader += analogRead(sensorPin);
n++;
now = millis();
} while (now < start + 20);
reader /= n;
// Gleitender Mittelwert über Array
sum -= reads[ptr];
sum += reader;
reads[ptr] = reader;
last = sum / samp_siz;
// Anstiegserkennung
if (last > before) {
rise_count++;
if (!rising && rise_count > rise_threshold) {
rising = true;
first = millis() - last_beat;
last_beat = millis();
// Gewichtete Durchschnitts-BPM (letzte 3 Schläge)
print_value = 60000.0 / (0.4 * first + 0.3 * second + 0.3 * third);
Serial.print(print_value);
Serial.print('\n');
third = second;
second = first;
}
} else {
rising = false;
rise_count = 0;
}
before = last;
ptr = (ptr + 1) % samp_siz;
}
}
Der Code funktioniert gut. Die winzige RX-LED auf dem Arduino blinkt im Takt des Herzschlags (serieller Output). Bei Fingerbewegungen treten Artefakte auf.
Weiterentwicklung
- Statt der letzten drei Schläge: gleitendes Fenster von 15 s, Ausreißer entfernen, Mittelwert bilden.
- Verschiedene Pulskurvenformen (steiler Abfall, sehr hohe Frequenz 180–200 BPM) erfordern evtl. andere Detektionsstrategien (z. B. Fallende Flanke oder Peak-Erkennung).
Schaltplan

Herstellungsprozess
- Farbsensoren: Funktionsweise und Schlüsselanwendungen
- OPT3007 Ultra-dünner Umgebungslichtsensor – Präzise Lichtmessung für Smart Devices
- Echtzeit-Temperaturdaten vom ppDAQC Pi‑Plate zu InitialState streamen – Headless Raspberry Pi
- Multi-Sensor Temperatur- & Licht-Überwachung mit Raspberry Pi & DS18B20
- Aus 4$ Solar-Licht wird smarter Wireless-Sensorknoten: MSP430 + nRF24L01+ für Garten-Monitoring
- Raspberry Pi Badezimmer-Belegungssensor mit Sprach- & SMS-Benachrichtigung via Twilio
- Herzfrequenz mit Windows 10 IoT Core auf Raspberry Pi auslesen – Schritt-für-Schritt-Anleitung
- Raspberry Pi Lichtsensor Tutorial – LDR verdrahten und Lichtpegel mit Python auslesen
- Digitaler Lichtsensor – LED per Umgebungslicht steuern mit Windows 10 IoT Core
- Fern-Herzfrequenz-Überwachung mit AWS IoT Alarmen