DIY Open-Source Pulsoximeter (MAX30102) für COVID-19: Arduino Nano Build
Komponenten und Zubehör
| Bauteil | Menge |
|---|---|
| Arduino Nano R3 | 1 |
| MAX30102 Pulssensor / Herzfrequenz-Sensor | 1 |
| DFRobot Gravity I2C OLED 128×64 Display | 1 |
Benötigte Werkzeuge
- 3D-Drucker (für Gehäuse)
- Lötkolben
Software und Online-Dienste
- Arduino IDE
- Autodesk Fusion 360 (Gehäuse-Design)
Projektbeschreibung
Hintergrund: COVID-19
COVID-19 (SARS-CoV-2) greift primär die Atemwege an. Ein Pulsoximeter misst die Blutsauerstoffsättigung (SpO₂) und Herzfrequenz – wichtige Indikatoren für einen Klinikbesuch. Dieses Open-Source-Gerät hilft, den eigenen Zustand einzuschätzen.
Wichtiger Hinweis: Dieses Gerät ist KEIN medizinisches Diagnosewerkzeug! Es dient nur zur Information und ersetzt keine professionelle Messung.
Elektronik
- MAX30102: Integrierter Pulsoximeter-Sensor (grüne/rote/IR-LEDs, Fotodetektor, AFE). I2C-Interface, 3,3 V / 5 V tolerant.
- OLED 128×64 (SSD1306): I2C, zeigt Herzfrequenz & SpO₂ an.
- Arduino Nano: Steuert Sensor & Display, berechnet Werte.
Schritt-für-Schritt Bauanleitung
1. Gehäuse 3D-drucken & nachbearbeiten
STL-Dateien (im Originalprojekt) mit 70–80 % Infill, mittlere Supports, PLA drucken. Supports entfernen, leicht schleifen für Passgenauigkeit.
2. Elektronik löten
Arduino Nano auf 44×30 mm Lochrasterplatine. Sensor-Leitungen (VIN, GND, SDA, A4; SCL, A5) unter dem Sensorbett hindurch zum Nano führen. OLED-Stecker an Nano anlöten, Kabel zum Display verlegen. Gesamte Einheit in Gehäuse schieben, mit 3 mm Schrauben fixieren.
3. Gerät zusammenbauen
OLED in Deckel einsetzen, Deckel mit Schrauben am Chassis befestigen. Klappmechanik testen (Deckel sanft öffnen/schließen).
4. Sketch hochladen
Benötigte Bibliotheken installieren: MAX30105, spo2_algorithm, SSD1306Ascii. Board: Arduino Nano, Upload.
Code-Ablauf:
- OLED & MAX30102 initialisieren, Fehler melden.
- 100 Samples zur Kalibrierung einlesen.
- Endlosschleife: 25 neue Samples lesen, gleitenden Mittelwert bilden, HR/SpO₂ berechnen (
maxim_heart_rate_and_oxygen_saturation). - Gültige Werte auf OLED ausgeben („HR: xx / SPO2: yy“), sonst „Not valid“.
5. Nutzung
Fingerspitze auf Sensor legen, Deckel vorsichtig schließen. Per USB-Stromversorgung (Powerbank) betreiben. Warten bis Werte stabil angezeigt werden.
Code (C/C++)
/* Hardware: MAX30102 Breakout → Arduino Nano
* VIN = 5V (3,3V möglich), GND = GND, SDA = A4, SCL = A5, INT = offen
*/
#include <Wire.h>
#include "MAX30105.h"
#include "spo2_algorithm.h"
#include "SSD1306Ascii.h"
#include "SSD1306AsciiWire.h"
MAX30105 particleSensor;
SSD1306AsciiWire oled;
#define MAX_BRIGHTNESS 255
#if defined(__AVR_ATmega328P__) || defined(__AVR_ATmega168__)
// Nano/Uno: wenig SRAM → 16-bit Puffer
uint16_t irBuffer[50], redBuffer[50];
#else
uint32_t irBuffer[50], redBuffer[50];
#endif
int32_t spo2; int8_t validSPO2;
int32_t heartRate; int8_t validHeartRate;
void setup() {
Serial.begin(115200);
oled.begin(&Adafruit128x64, 0x3C);
oled.setFont(Arial14);
if (!particleSensor.begin(Wire, I2C_SPEED_FAST)) {
Serial.println(F("MAX30105 nicht gefunden. Verkabelung/Strom prüfen."));
while (1);
}
particleSensor.setup(55, 4, 2, 200, 411, 4096); // LED-Strom 55mA, Sample-Rate 400Hz, etc.
}
void loop() {
// Erste 50 Samples für Initialisierung
for (byte i = 0; i < 50; i++) {
while (!particleSensor.available()) particleSensor.check();
redBuffer[i] = particleSensor.getRed();
irBuffer[i] = particleSensor.getIR();
particleSensor.nextSample();
Serial.print(F("red=")); Serial.print(redBuffer[i]);
Serial.print(F(", ir=")); Serial.println(irBuffer[i]);
}
maxim_heart_rate_and_oxygen_saturation(irBuffer, 50, redBuffer, &spo2, &validSPO2, &heartRate, &validHeartRate);
// Laufende Messung: alle 25 Samples neu berechnen
while (1) {
for (byte i = 25; i < 50; i++) { // Ältere 25 Samples nach vorne schieben
redBuffer[i - 25] = redBuffer[i];
irBuffer[i - 25] = irBuffer[i];
}
for (byte i = 25; i < 50; i++) { // 25 neue Samples
while (!particleSensor.available()) particleSensor.check();
redBuffer[i] = particleSensor.getRed();
irBuffer[i] = particleSensor.getIR();
particleSensor.nextSample();
// Debug-Ausgabe
Serial.print(F("red=")); Serial.print(redBuffer[i]);
Serial.print(F(", ir=")); Serial.print(irBuffer[i]);
Serial.print(F(", HR=")); Serial.print(heartRate);
Serial.print(F(", HRv=")); Serial.print(validHeartRate);
Serial.print(F(", SPO2=")); Serial.print(spo2);
Serial.print(F(", SPO2v=")); Serial.println(validSPO2);
}
maxim_heart_rate_and_oxygen_saturation(irBuffer, 50, redBuffer, &spo2, &validSPO2, &heartRate, &validHeartRate);
printToScreen();
}
}
void printToScreen() {
oled.clear(); oled.setCursor(0, 0);
if (validSPO2 && validHeartRate) {
oled.print(F("HR: ")); oled.println(heartRate);
oled.print(F("SPO2: ")); oled.println(spo2);
} else {
oled.print(F("Not valid"));
}
}
Gehäuse (CAD)
STL-Dateien im Originalprojekt (Fusion 360). Zwei Teile: Basis & Deckel mit Scharnier für Fingereinzug.
Schaltplan
Einfache I2C-Verkabelung: Nano A4/SDA, A5/SCL → MAX30102 & OLED parallel. MAX30102 VIN an 5 V, GND an GND. OLED an 3,3 V / 5 V (je nach Modul).
Herstellungsprozess
- FirePick Delta Projektlog: Open-Source MicroFactory mit OpenPnP aufbauen
- Arduino Digitaler Würfel: LCD-Würfel mit Zufallszahlen (1–6)
- Arduino Iron Man bauen: Komponenten, Sensoren & Schritt-für-Schritt-Anleitung
- Find Me: Smarter Gegenstands-Finder mit Arduino und Bluetooth
- Funktionaler 3D-gedruckter Roboterarm mit Arduino – Schritt-für-Schritt-Anleitung
- Tragbares Pulsoximeter für Notfalleinsätze während COVID-19
- DIY Arduino Luftbefeuchter-Steuerung mit Relais – Sichere Hochspannungs-Installation
- NeoPixel-Matrix Pong auf Arduino Nano: Neon-Pong selbst bauen
- Health Band: Smarter Wearable-Assistent für Senioren
- Warum Open Source Innovation am Edge antreibt – Essential eBook