Mit einem Spirometer untersucht ein Arzt die Lungenfunktion, indem u.a. das Volumen der herausströmenden Atemluft bestimmt wird.
Zur Bestimmung des Volumens macht man sich die Bernoulli-Gleichung zunutze. Sie besagt, dass in einem strömenden Medium (Wasser, Luft…) die Summe aus statischen Druck p + ρ · g · h und dynamischen Druck 1/2 · ρ · v² konstant ist.
Dies hat etwa zur Folge, dass in einem Rohr bei Verringerung des Querschnitts die Geschwindigkeit v bzw. der dynamische Druck zunimmt und daher der statische Druck abnehmen muss. Schnell strömende Gase/Flüssigkeiten erzeugen also einen Unterdruck!
Mein Spirometer verwendet ein Blasrohr, welches in der Mitte einen geringen Querschnitt aufweist. Mit einem Drucksensor (Modell MPX5010DP) wird nun der Druckunterschied am Ort dieser Engstelle und außerhalb des Spirometers (bei v = 0) gemessen. Laut Bernoulli gilt ja bei gleicher Höhe h:
p1 + ρ · g · h + 1/2 · ρ · v1² = p2 + ρ · g · h + 1/2 · ρ · v2²
1/2 · ρ · (v2² – v1²) = p1 – p2
v2² – v1² = 2 · (p1 – p2) / ρ
Ausserhalb des Spirometers wirkt der Druck p1 und die Geschwindigkeit v1 ist dort 0! Dadurch vereinfacht sich die Gleichung zu
v2² = 2 · (p1 – p2) / ρ
v2 = √(2 · (p1 – p2) / ρ)
Man kann also mittels der gemessenen Druckdifferent p1 – p2 auf die Strömungsgeschwindigkeit der Luft in der Engstelle des Blasrohrs schließen.
Das innerhalb der Zeit dt durchströmende Luftvolumen beträgt dann dV = A · v2 · dt, wobei A die Querschnittsfläche der Engstelle ist.
Um auf das Gesamtvolumen zu kommen, müssen einfach die Teilvolumina dV aufsummiert/integriert werden. Dies macht der Arduino. Er misst die Druckdifferenz p1 – p2, berechnet daraus v2, bestimmt dann das Teilvolumen dV und addiert diese auf. Hierzu muss das Programm natürlich die Zeitschrittweite dt wissen. Fügt man ins Programm ein delay zwischen den Messungen von z.B. 1 ms ein, so beträgt das dt = 0.0011605 sek.
Ich habe den zeitlichen Verlauf der Druckdifferenz mit dem Oszilloskop aufgezeichnet. Dabei stellte ich fest, dass das Signal sehr verrauscht ist. Daher würde ich raten, an den Ausgang des Drucksensors noch einen Tiefpass (engl. low-pass-filter) zu installieren.







Bildquelle: https://de.wikipedia.org/wiki/Venturi-Düse












Arduino-Code:
// =============================================================
// Programm zur Messung des Lungenvolumen mit dem Sensor MPX5010
// =============================================================
#include <LiquidCrystal_I2C.h>
#include <Wire.h>
LiquidCrystal_I2C lcd(0x27,16,2); // ACHTUNG: set the LCD address to 0x20 or 0x27 for a 16 chars and 2 line display!!!
// Anschlüsse Display:
// ===================
// GND - GND
// VCC - 5V
// SDA - ANALOG Pin 4
// SCL - ANALOG Pin 5
// Anschlüsse Drucksensor:
// =======================
// GND - GND
// VCC - 5V
// Signal - Analog Pin 0
int sensorPin = A0;
int pin_start = 12; // Pin für Startknopf
int i;
long t_start,t_end; // Variablen zur Bestimmung der Zeitschrittweite dt
float U_sensor, U_offset;
float v, A, Volumsfluss;
float Lungenvolumen, dt;
float k; // Korrekturfaktor
// =========================
// ======== SETUP ==========
// =========================
void setup()
{
Serial.begin(9600);
pinMode(pin_start, INPUT); // start-pin für den Beginn der Messung
lcd.begin(); // initialize the lcd
lcd.backlight();
// Print a message to the LCD.
lcd.setCursor(0,0);
lcd.print("Spirometer");
delay(4000);
lcd.setCursor(0,0);
lcd.print(" ");
lcd.setCursor(0,0);
lcd.print("press button &");
lcd.setCursor(0,1);
lcd.print("blow then.....");
U_offset = (5.0 / 1023) * analogRead(sensorPin); // Bestimmung des sensor-offsets in Volt
A = (0.024*0.024) * 3.141592654; // Querschnittsfläche des Strömungsrohrs in dm² mit Radius r = 0.024 dm
dt = 0.0011605; // zeitliche Schrittweite dt, genau bestimmt mittels millis()
k = 1.4; // Korrekturfaktor
}
// =================================
// ======== HAUPTSCHLEIFE ==========
// =================================
void loop()
{
Lungenvolumen = 0.0;
while(digitalRead(pin_start) == HIGH) // Wartet bis Startknopf gedrückt
lcd.setCursor(0,0);
lcd.print("blow now ");
lcd.setCursor(0,1);
lcd.print(" ");
//t_start = millis(); // Startzeit für die Bestimmung von dt
for(i = 0; i < 10000; i++) // insgesamt 10000*0.001 = 10 sek Abfrage der Sensorwerte
{
// Einlesen des Spannungswerts des Sensors MPX5010
U_sensor = (5.0 / 1023) * analogRead(sensorPin); // eingelesener Sensorwert in Volt
// Berechnung der Geschwindigkeit in dm/sek
if(U_sensor - U_offset > 0.005) // Abfrage um Werte < Schwelle als 0 zu werten
{
v = k * 10.0 * sqrt((2000/(0.45 * 1.25))*(U_sensor - U_offset)); // Berechnung der Strömungsgeschwindigkeit in dm/sek; 0.45 V/kPa = Sensibilität des Sensors; 1.25 kg/m³ = Luftdichte
}
else
{
v = 0.0;
}
Volumsfluss = A * v; // Volumsfluss V/t in Liter/sek
Lungenvolumen = Lungenvolumen + Volumsfluss * dt; // Aufsummierung der einzelnen Teilvolumina
delay(1); // 1 ms Verzögerung
}
/*
t_end = millis(); // Endzeit für die Bestimmung von dt
Serial.println(t_start);
Serial.println(t_end);
Serial.print("dt = ");
Serial.println((t_end - t_start)/10000.0,4);
*/
lcd.setCursor(0,0);
lcd.print("V = ");
lcd.setCursor(4,0);
lcd.print(Lungenvolumen,2);
lcd.setCursor(9,0);
lcd.print("Liter");
delay(2000);
lcd.setCursor(0,1);
lcd.print("button to start");
}
