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.
Arduino-Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 |
// ============================================================= // 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"); } |