Spirometer mit Arduino und Drucksensor MPX5010

Gast #6335122
Lesenswert?

Hallo!

Ein Projekt habe ich noch in der Warteschleife und zwar ein 
Strömungsmessgerät, welches dann als Spirometer zur Bestimmung des 
Lungenvolumens dienen soll. Als Sensor kommt der MPX5010 zum Einsatz. 
Dieser besitzt zwei Druckeingänge, um den Differenzdruck messen zu 
können. Die Empfindlichkeit beträgt 0.45V/kPa. Ein erster Funktionstest 
verlief erfolgreich. Konnte durch Einsaugen schön Spannungen bis 4.5V 
erzielen bei 5V Versorgungsspannung.

Zur Messung des Lungenvolumens muss natürlich der aktuelle Volumsfluss 
dV/dt bekannt sein. Diesen könnte ich mit einem gewöhnlichen 
Strömungsmessgerät basierend auf einem Schaufelrad bestimmen nur ist 
dies mMn viel zu ungenau, da sich zum Beispiel das Schaufelrad aufgrund 
der Trägheit noch weiterdreht, auch wenn keine Strömung mehr vorliegt. 
Deshalb habe ich mich für die Druckmessung entschieden. Der Gesamtdruck 
besteht ja aus statischen, dynamischen und Schweredruck 
(Bernoulligleichung). Die Summe der drei Drücke ist entlang eines 
Strömungspfades konstant. Gehe ich von einer Höhendifferenz h = 0 aus, 
so fällt der Schweredruck weg. Übrig bleibt die Summe aus statischen und 
dynamischen Druck, also die Gleichung

 p_stat_1 + 0.5  ro  v_1² = p_stat_2 + 0.5  ro  v_2²

Nun messe ich einen statischen Druck außerhalb des Spirometerrohres, wo 
v_1 = 0 gilt. Daraus folgt für die Gleichung:

 p_stat_1 = p_stat_2 + 0.5  ro  v_2²

Umgeformt nach v_2 ergibt sich der Ausdruck:

 v_2 = Wurzel[2 * (p_stat_1 - p_stat_2) / ro]

Die Druckdifferent p_stat_1 - p_stat_2 wird eben mit dem MPX5010 
gemessen. Dessen Ausgangsspannung hat einen geringen (ca. 0.2V) offset, 
welcher von der ausgegebenen Spannung abgezogen werden muss. Die 
Empfindlichkeit beträgt wie oben erwähnt 0.45V/kPa.

Daraus folgt die Beziehung:

 p_stat_1 - p_stat_2 = 1000 * [(U_out - U_offset) / 0.45]

Eingesetzt in die obige Gleichung für v_2 ergibt sich der finale 
Ausdruck

 v_2 = Wurzel[(2000 / (0.45 * ro)) * (U_out - U_offset)]

mit ro = Luftdiche = ca. 1.25 kg/m³

Aus v_2 und dem Strömungsquerschnitt A_2 ergibt sich der momentane 
Volumsfluss dV/dt = A_2 * v_2.

Für das innerhalb der Zeit dt durchströmende Volumen dV gilt dann:

 dV = A_2  v_2  dt

Diese Volumselemente müssen im Arduinoprogramm nur noch aufsummiert 
werden, um das Lungenvolumen V zu erhalten. Als Zeitschrittweite werde 
ich dt = ca. 1ms wählen.

Der Sensor um ca. 14 Euro ist bereits aus China eingetroffen. Als 
nächstes werde ich mich um den Bau der Venturidüse kümmern... ;)
Gast #6338204
Lesenswert?

So, nachdem heute der 4mm-Schlauchverbinder angekommen ist, konnte ich 
die Venturidüse fertigstellen. Der Spannungsoffset beträgt bei 5V 
Versorgung rund 0.2V. Wenn ich durchpuste steigt die Spannung auf ca. 
0.5V an. Das ist zwar nicht die Welt aber mit der 5mV-Auflösung vom 
Arduino geht das schon einigermaßen in Ordnung. Verstärker werde ich 
daher wohl keinen zusätzlich anschließen...
Gast #6339067
Lesenswert?

Das Spirometer ist fertig und hat die Feuertaufe bestanden...

Weil ich nicht genau weiß, wie sich die Strömungsgeschwindigkeit im Rohr 
radial verteilt (Stichwort Gesetz von Hagen-Poiseuille) und wohl zum 
Rand hin wo gemessen wird abnimmt, habe ich noch einen Korrekturfaktor k 
in die Berechnung der Geschwindigkeit eingebaut. Bekomme aber eigentlich 
sehr vernünftige Messwerte (um die 2 Liter ohne in der Lunge 
verbleibendes Restvolumen).
1
// =============================================================
2
// Programm zur Messung des Lungenvolumen mit dem Sensor MPX5010
3
// =============================================================
4

5
#include <LiquidCrystal_I2C.h>
6
#include <Wire.h>
7

8
LiquidCrystal_I2C lcd(0x27,16,2);  // ACHTUNG: set the LCD address to 0x20 or 0x27 for a 16 chars and 2 line display!!!
9

10
// Anschlüsse Display:
11
// ===================
12
// GND - GND
13
// VCC - 5V
14
// SDA - ANALOG Pin 4
15
// SCL - ANALOG Pin 5
16

17
// Anschlüsse Drucksensor:
18
// =======================
19
// GND - GND
20
// VCC - 5V
21
// Signal - Analog Pin 0
22

23

24
int sensorPin = A0;
25
int pin_start = 12;     // Pin für Startknopf
26
int i;
27
long t_start,t_end;     // Variablen zur Bestimmung der Zeitschrittweite dt
28

29
float U_sensor, U_offset;
30
float v, A, Volumsfluss;
31
float Lungenvolumen, dt;
32
float k;                // Korrekturfaktor
33

34

35
// =========================
36
// ======== SETUP ==========
37
// =========================
38

39
void setup()
40
   {
41
    Serial.begin(9600);
42

43
    pinMode(pin_start, INPUT);           // start-pin für den Beginn der Messung
44

45
    lcd.begin();        // initialize the lcd
46
    lcd.backlight();
47
        
48
    // Print a message to the LCD.
49
    lcd.setCursor(0,0);
50
    lcd.print("Spirometer");
51

52
    delay(4000);
53

54
    lcd.setCursor(0,0);
55
    lcd.print("          ");
56
    lcd.setCursor(0,0);
57
    lcd.print("press button &");
58
    lcd.setCursor(0,1);
59
    lcd.print("blow then.....");
60
     
61
    
62
    U_offset = (5.0 / 1023) * analogRead(sensorPin);   // Bestimmung des sensor-offsets in Volt
63
    
64
    A = (0.024*0.024) * 3.141592654;                   // Querschnittsfläche des Strömungsrohrs in dm² mit Radius r = 0.024 dm
65

66
    dt = 0.0011605;         // zeitliche Schrittweite dt, genau bestimmt mittels millis()
67

68
    k = 1.4;                // Korrekturfaktor
69

70
   }
71

72

73
// =================================
74
// ======== HAUPTSCHLEIFE ==========
75
// =================================
76

77
void loop()
78
   {
79
    Lungenvolumen = 0.0;
80

81
    while(digitalRead(pin_start) == HIGH)    // Wartet bis Startknopf gedrückt
82

83
    lcd.setCursor(0,0);
84
    lcd.print("blow now        ");
85
    lcd.setCursor(0,1);
86
    lcd.print("                ");
87

88
    //t_start = millis();           // Startzeit für die Bestimmung von dt
89

90

91
    for(i = 0; i < 10000; i++)      // insgesamt 10000*0.001 = 10 sek Abfrage der Sensorwerte
92
       {
93
        // Einlesen des Spannungswerts des Sensors MPX5010
94
        
95
        U_sensor = (5.0 / 1023) * analogRead(sensorPin);   // eingelesener Sensorwert in Volt
96

97
        // Berechnung der Geschwindigkeit in dm/sek
98

99
        if(U_sensor - U_offset > 0.005)      // Abfrage um Werte < Schwelle als 0 zu werten
100
           {      
101
            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
102
           }
103
        else
104
           {
105
            v = 0.0;
106
           }
107

108
        Volumsfluss = A * v;     // Volumsfluss V/t in Liter/sek
109

110
        Lungenvolumen = Lungenvolumen + Volumsfluss * dt;   // Aufsummierung der einzelnen Teilvolumina
111

112
        delay(1);     // 1 ms Verzögerung
113
       
114
       }
115

116
    /*
117
    t_end = millis();     // Endzeit für die Bestimmung von dt
118

119
    Serial.println(t_start);
120
    Serial.println(t_end);
121
    Serial.print("dt = ");
122
    Serial.println((t_end - t_start)/10000.0,4);
123
    */
124
     
125
    lcd.setCursor(0,0);
126
    lcd.print("V =             ");
127
    lcd.setCursor(4,0);
128
    lcd.print(Lungenvolumen,2);
129
    lcd.setCursor(9,0);
130
    lcd.print("Liter");
131

132
    delay(2000);
133

134
    lcd.setCursor(0,1);
135
    lcd.print("button to start");
136
      
137
   }

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren