MAX30102 Tutorial: Herzfrequenz & Blutsauerstoff messen – einfach erklärt
In diesem Tutorial zeige ich dir Schritt für Schritt, wie du den MAX30102 Sensor anschließt, programmierst und die Messwerte visualisierst.
Den MAX30100 habe ich bereits im Beitrag „MAX30100 am Arduino: Blutsauerstoff und Herzfrequenz messen leicht gemacht“ ausführlich vorgestellt. In diesem Beitrag gehen wir einen Schritt weiter und schauen uns den Nachfolger, den MAX30102, genauer an.
Du lernst dabei nicht nur, wie du die Werte für Herzfrequenz und Blutsauerstoff ausliest, sondern auch, wie du diese einfach und anschaulich darstellen kannst.
Außerdem werfen wir einen Blick darauf, welche Verbesserungen der MAX30102 gegenüber dem MAX30100 bietet und wie genau die gemessenen Werte in der Praxis sind.
https://youtu.be/rsCE1cKhRQk
Hinweis: Die Idee, mir den MAX30102 genauer anzuschauen, kam übrigens aus einem Kommentar unter meinem Beitrag zum MAX30100. Dort wurde ich gefragt, wie sich der neuere Sensor auslesen lässt.
Ein wichtiger Punkt dabei: Viele Bibliotheken, die für den MAX30100 gedacht sind, sind nicht ohne Weiteres mit dem MAX30102 kompatibel. Deshalb muss man zunächst eine passende Library finden und den Code entsprechend anpassen.
Solltest auch du Fragen, Probleme oder konkrete Wünsche zu einem Projekt haben, kannst du dich jederzeit gerne per E-Mail oder über mein Ticketsystem bei mir melden.
Was ist der MAX30102?
Der MAX30102 ist ein kompakter Sensor zur Messung der Herzfrequenz (Puls) und der Sauerstoffsättigung im Blut (SpO2). Solche Sensoren kommen häufig in Fitness-Trackern oder Smartwatches zum Einsatz und eignen sich auch hervorragend für eigene Mikrocontroller-Projekte mit Arduino oder ESP32.
Die Messung basiert auf dem Prinzip der sogenannten Pulsoximetrie. Dabei wird ausgenutzt, dass sauerstoffreiches und sauerstoffarmes Blut Licht unterschiedlich stark absorbieren.
Im Detail funktioniert das so: Der Sensor verfügt über eine rote und eine infrarote LED sowie eine Photodiode. Diese LEDs senden abwechselnd Licht durch das Gewebe (z. B. deinen Finger). Ein Teil des Lichts wird vom Blut absorbiert, während der Rest von der Photodiode erfasst wird.
👉 Der entscheidende Punkt:
- Sauerstoffreiches Blut absorbiert mehr Infrarotlicht - Sauerstoffarmes Blut absorbiert mehr rotes Licht
Aus dem Verhältnis dieser beiden Messungen kann der Sensor die Sauerstoffsättigung (SpO2) berechnen.
Zusätzlich nutzt der MAX30102 die kleinen Schwankungen im Blutfluss, die durch den Herzschlag entstehen. Dadurch lässt sich gleichzeitig die Herzfrequenz (BPM) bestimmen.
Technische Daten des MAX30102 Moduls
Bevor wir mit der Programmierung starten, werfen wir einen kurzen Blick auf die wichtigsten technischen Daten des MAX30102. Diese geben dir ein gutes Gefühl dafür, was der Sensor leisten kann und worauf du beim Einsatz achten solltest.
EigenschaftWertVersorgungsspannung3.3 – 5 VoltStromaufnahmemax. 20 mA (kontinuierlich)ADC Auflösung14 BitSchnittstelleI2CLogiklevel3.3VI2C Taktfrequenz0 – 400 kHzI2C Adresse (Write)0xAEI2C Adresse (Read)0xAFIR LED Wellenlänge870 – 900 nm (Peak: 880 nm)Red LED Wellenlänge650 – 670 nm (Peak: 660 nm)Temperatursensor Genauigkeit±1 °C bei 25 °CTemperaturbereich-40 °C bis +85 °CTemperatur Messdauerca. 29 msAbmessungen14 x 14 mm
Preis & Beschaffung
Den MAX30102 Sensor gibt es in unterschiedlichen Ausführungen. Häufig findet man Module mit der Aufschrift „MAX3010x“, die sowohl für den MAX30100 als auch den MAX30102 beworben werden.
MAX3010x und MAX30102 Sensor - Vergleich
Mit genau so einem Modul habe ich ebenfalls gestartet – allerdings ohne Erfolg. Der Sensor ließ sich nicht zuverlässig betreiben. Bei der Recherche in verschiedenen Foren bin ich auf ähnliche Erfahrungen gestoßen: Offenbar gibt es Varianten, bei denen die Beschaltung bzw. Spannungsversorgung nicht sauber umgesetzt ist.
Aus diesem Grund bin ich auf ein Modul mit der eindeutigen Bezeichnung MAX30102 gewechselt. Dieses habe ich bei https://www.androegg.de/shop/max30100-max30102-herzfrequenz-haemoglobin-sensor/ bezogen – und hier funktionierte der Sensor direkt ohne Probleme.
Preislich liegt das Modul bei rund 5 €. Damit ist es zwar kein absoluter „China-Billig-Sensor“, aber für Experimente und eigene Projekte definitiv eine solide Wahl.
Anschluss des MAX30102 am Arduino Nano
Der Anschluss des MAX30102 ist denkbar einfach, da der Sensor über die I2C-Schnittstelle kommuniziert.
Schaltung - MAX30102 Sensor am Arduino
Folgende Pins werden benötigt:
MAX30102Arduino NanoVIN3.3VGNDGNDSDAA4SCLA5INToptional Benötige Bauteile für den Aufbau der Schaltung
Im Grunde benötigst du für den Anschluss an einen Mikrocontroller lediglich:
- einen Mikrocontroller (zbsp. Arduino Nano, Arduino UNO), - vier Breadboardkabel, männlich-männlich, 10cm - ein 400 Pin Breadboard
Im späteren verlauf zeige ich dir noch wie man die Werte visualisiert, hier verwende ich dann:
- eine 8x8 LED Punkt Matrix, - fünf Breadboardkabel, männlich-weiblich, 10cm, sowie - einen Buzzer für den typischen Ton bei einem Herzschlag
Hinweis von mir: Die mit einem Sternchen (*) markierten Links sind Affiliate-Links. Wenn du über diese Links einkaufst, erhalte ich eine kleine Provision, die dazu beiträgt, diesen Blog zu unterstützen. Der Preis für dich bleibt dabei unverändert. Vielen Dank für deine Unterstützung!
Benötigte Bibliothek zum auslesen des MAX30102 Sensors in der Arduino IDE
Für den MAX30102 Sensor gibt es diverse Bibliotheken, am zuverlässigsten hat bei mir die MAX3010x-Sensor-Library von Daniel Weise funktioniert welche du entweder über den internen Bibliotheksverwalter der Arduino IDE installieren, oder vom GitHub Repository devxplained/MAX3010x-Sensor-Library als ZIP-Datei laden kannst.
Arduino IDE - MAX30102 Bibliothek installieren
Beispiel - visualisieren des Herzschlags sowie des Blutsauerstoffs im seriellen Plotter der Arduino IDE
Um die beiden Werte für Herzschlag und Blutsauerstoff im seriellen Plotter anzeigen zu lassen müssen wir die Werte für den seriellen Monitor leicht anpassen denn wir möchten zwei Linien im Plotter anzeigen lassen was ein definiertes Format benötigt.
Messwerte vom MAX30102 Sensor im seriellen Plotter der Arduino IDE
Vorher:
Serial.print("Heart Rate:"); Serial.println(average_bpm); Serial.print("SpO2: "); Serial.println(average_spo2);
Nachher:
Serial.print("HeartRate:"); Serial.println(average_bpm); Serial.print("SpO2:"); Serial.println(average_spo2);
Zusätzlich müssen wir noch im Setup die If-Bedingung anpassen damit die Ausgabe "Sensor initialized" nicht mehr erscheint, denn diese würde als zusätzliche Linie (jedoch ohne Werte) erscheinen.
if (!sensor.begin() && !sensor.setSamplingRate(kSamplingRate)) { Serial.println("Sensor not found"); while (1) ; } Programm zum anzeigen des Herzschlags und Blutsauerstoffwertes im seriellen PlotterHerunterladen angepasster Quellcode für das visualisieren der Werte im seriellen Plotter #include #include "filters.h" #include "MATRIX7219.h" // Sensor (adjust to your sensor type) MAX30105 sensor; const auto kSamplingRate = sensor.SAMPLING_RATE_400SPS; const float kSamplingFrequency = 400.0; // Finger Detection Threshold and Cooldown const unsigned long kFingerThreshold = 10000; const unsigned int kFingerCooldownMs = 500; // Edge Detection Threshold (decrease for MAX30100) const float kEdgeThreshold = -2000.0; // Filters const float kLowPassCutoff = 5.0; const float kHighPassCutoff = 0.5; // Averaging const bool kEnableAveraging = false; const int kAveragingSamples = 5; const int kSampleThreshold = 5; void setup() { Serial.begin(9600); if (!sensor.begin() && !sensor.setSamplingRate(kSamplingRate)) { Serial.println("Sensor not found"); while (1) ; } } // Filter Instances LowPassFilter low_pass_filter_red(kLowPassCutoff, kSamplingFrequency); LowPassFilter low_pass_filter_ir(kLowPassCutoff, kSamplingFrequency); HighPassFilter high_pass_filter(kHighPassCutoff, kSamplingFrequency); Differentiator differentiator(kSamplingFrequency); MovingAverageFilter averager_bpm; MovingAverageFilter averager_r; MovingAverageFilter averager_spo2; // Statistic for pulse oximetry MinMaxAvgStatistic stat_red; MinMaxAvgStatistic stat_ir; // R value to SpO2 calibration factors // See https://www.maximintegrated.com/en/design/technical-documents/app-notes/6/6845.html float kSpO2_A = 1.5958422; float kSpO2_B = -34.6596622; float kSpO2_C = 112.6898759; // Timestamp of the last heartbeat long last_heartbeat = 0; // Timestamp for finger detection long finger_timestamp = 0; bool finger_detected = false; // Last diff to detect zero crossing float last_diff = NAN; bool crossed = false; long crossed_time = 0; void loop() { auto sample = sensor.readSample(1000); float current_value_red = sample.red; float current_value_ir = sample.ir; // Detect Finger using raw sensor value if (sample.red > kFingerThreshold) { if (millis() - finger_timestamp > kFingerCooldownMs) { finger_detected = true; } } else { // Reset values if the finger is removed differentiator.reset(); averager_bpm.reset(); averager_r.reset(); averager_spo2.reset(); low_pass_filter_red.reset(); low_pass_filter_ir.reset(); high_pass_filter.reset(); stat_red.reset(); stat_ir.reset(); finger_detected = false; finger_timestamp = millis(); } if (finger_detected) { current_value_red = low_pass_filter_red.process(current_value_red); current_value_ir = low_pass_filter_ir.process(current_value_ir); // Statistics for pulse oximetry stat_red.process(current_value_red); stat_ir.process(current_value_ir); // Heart beat detection using value for red LED float current_value = high_pass_filter.process(current_value_red); float current_diff = differentiator.process(current_value); // Valid values?













