Homepage von Peter Rachow Startseite - Home

Software zur Berechnung von Dekompressionstauchgängen

Quellcode in PASCAL

Dieses Beispiel soll zeigen, wie eine einfache Umsetzung des Bühlmann-Algorithmus in PASCAL exemplarisch aussehen könnte:

(*------------------------------------------------------------------*)
(* Berechnung von Dekompressionsdaten für Tauchgänge mit Pressluft *)
(* und Nitrox *)
(* *)
(* (C) 1999 by Peter Rachow *)
(*------------------------------------------------------------------*)
Program DecoSim;

Uses Crt, Dos;

Const
e = 2.71820469;
kx = -1.629315; (*nach Bühlmann: -0.69315, erzeugt zu kurze Zeiten!!!*)

Var
a,b: Array [1..16] Of Real;
tchalf: Array [1..16] Of Real;
pig_te: Array [1..16] Of Real;
deko: Array [1..100] Of Word;

dt_sta: Array [1..30] Of Word;
dt_end: Array [1..30] Of Word;
dt_step: Array [1..30] Of Word;

dive_depth : Word;
dive_time : Word;
air_pressure: Word;
fig : Word;

amv : Word;
t1 : Word;

ch :Char;
k :Real;

(* Wasserdruck in gegebener Tiefe berechnen *)
(*-------------------------------------------*)
Function GetWaterPr(f_depth: Real): Real;
Begin
GetWaterPr := (f_depth / 10) + (air_pressure / 1000);
End;

(*Gewebepartialdrücke für Inertgas ausrechnen*)
(*-------------------------------------------*)
Procedure CalcPIOnTime(depth: Real; tE: Real);
Var
piig: Real;
t1: Integer;
exponent: Real;
Begin
(*Inertgaspartialdruck f�r alle 16 Kompartimente berechnen*)

(*Konstante abhängig von Tiefe definieren*)
k := 3;

If depth <= 15 Then
k := 2.7;
If depth <= 12 Then
k := 2.6;
If depth <= 9 Then
k := 2.5;
If depth <= 6 Then
k := 2.2;
If depth <= 3 Then
k := 1.6;

For T1 := 1 To 16 Do
Begin

(*Inspiratorischer Inertgasdruck in den Lungenalveolen*)
piig := (GetWaterPr(depth) - 0.063) * fig / 100;

(*Inertgasdruck im Kompartiment (mit spec. t1/2) nach geg. Expositionszeit*)
exponent := k * -1 * tE / tchalf[T1] * ln(e);
pig_te[T1] := pig_te[T1] + (piig - pig_te[T1]) * (1 - exp(exponent));

End;
End;

Function GetDecoStep(Metr: Real): Integer;
(*--------------------------------------*)
Var
T1: Integer;
Begin
For T1 := 1 To 99 Do
If (deko[T1] < Metr) And (deko[T1 + 1] > = Metr) Then
Begin
GetDecoStep := T1 + 1;
Exit;
End;

GetDecoStep := 1

End;

Function LSpace(s: string; max_len: Integer): String;
(*-------------------------------------------------*)
Var

t1: Integer;
s2: String;

Begin

s2 := '';

For t1 := 1 To max_len - Length(s) Do
s2 := ConCat(s2, ' ');

LSpace := ConCat(s2, s);

End;

(* Berechnen des Umgebungsdruckes, bei dem gerade noch keine *)
(* Gasblasen auftreten (abh„ngig von der bisher erfolgten *)
(* Aufs„ttigung der Gwebe mit N2 *)
(*-----------------------------------------------------------*)
Function GetTolAmbPress: Real;

Var
t1: Integer;
pambtol, max_p: Real;
Begin
max_p := 0;

For t1 := 1 To 16 Do
Begin
pambtol := (pig_te[T1] - a[T1]) * b[T1];
If pambtol > max_p Then
max_p := pambtol;
End;

GetTolAmbPress := max_p;

End;

(* Dekoberechnung f�r Rechtecktauchgang *)
(*-------------------------------------------*)
Procedure CalcDive;

Var

p_next, p_max, dek1, pambtol: Real;
t1, t2, t_elaps, t_last: Word;
cur_deco_depth, cur_deco_step: Word;
p: String;
t_decotime, t_asctime: Real;
air: Real;
no_deco: Word;

Begin

(*Arrays initialisieren*)
For t1 := 1 To 16 Do
pig_te[T1] := fig / 100;

no_deco := 1;

Writeln('++ Dekoberechnung f�r Tauchgang mit Rechteckprofil ++');
Writeln('------------------------------------------------------');
Writeln;
Writeln('Stickstoffanteil im Atemgas (in%):', fig);
Writeln('Luftdruck am Tauchort [mbar]: ', air_pressure);
Writeln('Tauchtiefe [m]: ', dive_depth);
Writeln('Tauchzeit [min]: ', dive_time);
Writeln('--------------------------------------------------------');
Writeln;

(*-- ABTAUCHPHASE ----------------------------------*)
(* Berechnung nach B�hlmann (nichtintegrierend *)
For t1 := 0 To dive_depth Do
CalcPIOnTime(t1, 0.1);

(*-- GRUNDZEIT -------------------------------------*)
For t1 := 1 To dive_time Do
CalcPIOnTime(dive_depth, 1);

(*--- Aufstiegsphase (y=10m/min.) ------------------*)
t_asctime := 0;

t1 := dive_depth;

Repeat
CalcPIOnTime(t1, 0.1);

t_asctime := t_asctime + 0.1;

If GetTolAmbPress > = GetWaterPr(t1) Then
Begin
textcolor(LightRed);
Writeln('DECO! DECO! DECO! DECO! DECO! DECO! DECO! DECO! ');
textcolor(CYAN);
cur_deco_step := GetDecoStep(t1);
cur_deco_depth := deko[cur_deco_step];
Writeln('1. Deko-Stopp auf: ', cur_deco_depth, ' m');
Writeln('Aufstiegszeit zu dieser Stufe ', t_asctime:2:1, ' min.');
no_deco := 0;
t1 := 0;
End
Else
t1 := t1 - 1;

Until (t1 <= 0);
(*--- Ende Aufstiegsphase ----------------------------*)

If no_deco = 1 Then
Begin
TextColor(LIGHTGREEN);
Writeln('Keine Deko erforderlich!');
Exit;
End;

TextColor(WHITE);
WriteLn('------- Dekompressionsphase --------');
TextColor(YELLOW);

(*Erwarteter Druck auf n„chster Deko-Stufe*)
p_next := GetWaterPr(deko[cur_deco_step]);
p_max := 0;
t_elaps := 0;
t_decotime := 0;
air := 0;

(*Gesamt-Deko berechnen*)

WriteLn('Deko-Stopps');
TextColor(LIGHTBLUE);
While True Do
Begin
t_elaps := t_elaps + 1; (*iterativ im Minutentakt berechnen*)

For t1 := 1 to 10 Do
CalcPIOnTime(deko[cur_deco_step], 0.1);
p_max := GetTolAmbPress;

If p_max <= p_next Then (*Aufsteigen zur n„chsth”heren Deko-Stufe*)
Begin

(* Zwischenents„ttigung w„hrend Aufsteigens zur n„chsten Deko-Stufe *)
(* berechnen v=10m/min. *)
For t1 := Round(deko[cur_deco_step]) DownTo Round(deko[cur_deco_step - 1]) Do
CalcPIOnTime(t1, 0.1);

air := air + amv * GetWaterPr(deko[cur_deco_step]);

WriteLn(t_elaps, ' min. auf ' ,deko[cur_deco_step], ' m');

t_decotime := t_decotime + t_elaps;
t_elaps := 0;
cur_deco_step := cur_deco_step - 1;

If (cur_deco_step < 1) Or (cur_deco_step > 99) Then
Begin
TextColor(WHITE);
WriteLn('--- Ende der Dekompressionsphase ---');
WriteLn('Gesamte Deko-Zeit: ', t_decotime:5:1, ' min. ');
WriteLn('Gesamte Luftmenge f�r Deko-Phase: ', air:5:1, ' ltr.');
Exit;
End;

p_next := GetWaterPr(deko[cur_deco_step]);

End;

End;
TextColor(YELLOW);
End;

Procedure CalcTable;

Var

p_next, p_max, dek1, pambtol: Real;
t1, t2, t_elaps, t_last: Word;
cur_deco_depth, cur_deco_step: Word;
p: String;
air: Real;
no_deco: Word;
dd, dt: Word;
a_dstep, a_dtime: Array [1..20] Of Word;
s: String;
ch: Char;
f: Text;

Begin

Assign(f, 'DEKO.TXT');
Rewrite(f);

WriteLn('Erstelle Deko-Tabelle...');
WriteLn('ESC dr�cken um abzubrechen.');

Writeln(f, '++ Dekoberechnung f�r Tauchgang mit Rechteckprofil ++');
Writeln(f, '------------------------------------------------------');
Writeln(f, '');
Writeln(f, 'Stickstoffanteil im Atemgas (in%):', fig);
Writeln(f, 'Luftdruck am Tauchort [mbar]: ', air_pressure);
Writeln(f, '--------------------------------------------------------');
Writeln(f, '');

For t1 := 1 To 20 Do
a_dstep[t1] := t1 * 3;

dd := 9;
Repeat
dt := dt_sta[Trunc(dd /3)];
For t1 := 1 To 10 Do
a_dtime[t1] := 0;

Write(f, LSpace('Tiefe:', 6));
Str(dd, s);
s := ConCat(s, 'm');
Write(f, LSpace(s, 6));

WriteLn(f, '');
Write('Berechne Dekozeiten f�r Tauchtiefe: ', dd, ' Meter... ');

s := 'GZeit';
Write(f, LSpace(s, 6));

For t1 := 10 DownTo 1 Do
Begin
Str(a_dstep[t1], s);
s := ConCat(s, 'm');
Write(f, LSpace(s, 6));
End;
WriteLn(f, '');

Repeat
(*Arrays initialisieren*)
For t1 := 1 To 16 Do
pig_te[T1] := fig / 100;

no_deco := 1;

(*-- ABTAUCHPHASE ----------------------------------*)
For t1 := 0 To dd Do
CalcPIOnTime(t1, 0.1);

(*-- GRUNDZEIT -------------------------------------*)
(*Kompartimente errechnen f�r Grundzeit *)
For t1 := 1 to dt do
CalcPIOnTime(dd, 1);

(*--- Aufstiegsphase (v=10m/min.) ------------------*)
t1 := dd;

Repeat
CalcPIOnTime(t1, 0.1);

If GetTolAmbPress > = GetWaterPr(t1) Then
Begin
cur_deco_step := GetDecoStep(t1);
cur_deco_depth := deko[cur_deco_step];
no_deco := 0;
t1 := 0;
End
Else
t1 := t1 - 1;
Until t1 <= 0;
(*--- Ende Aufstiegsphase ----------------------------*)

(*Erwarteter Druck auf n„chster Deko-Stufe*)
p_next := GetWaterPr(deko[cur_deco_step]);
p_max := 0;
t_elaps := 0;
air := 0;

(*Gesamt-Deko berechnen*)

While no_deco = 0 Do
Begin
t_elaps := t_elaps + 1; (*iterativ im Minutentakt berechnen*)

CalcPIOnTime(deko[cur_deco_step], 1);
p_max := GetTolAmbPress;

If p_max <= p_next Then (*Aufsteigen zur n„chsth”heren Deko-Stufe*)
Begin

(* Zwischenents„ttigung w„hrend Aufsteigens zur n„chsten Deko-Stufe *)
(* berechnen v=10m/min. *)
For t1 := Round(deko[cur_deco_step]) DownTo Round(deko[cur_deco_step - 1]) Do
CalcPIOnTime(t1, 0.1);

air := air + amv * GetWaterPr(deko[cur_deco_step]);

a_dtime[cur_deco_Step] := t_elaps;
t_elaps := 0;
cur_deco_step := cur_deco_step - 1;

If cur_deco_step < 1 Then
no_deco := 1;

p_next := GetWaterPr(deko[cur_deco_step]);
End;
End;

dt := dt + dt_step[Trunc(dd / 3)];

Str(dt, s);
Write(f, LSpace(s, 6));

For t1 := 10 DownTo 1 Do
Begin
Str(a_dtime[t1], s);
Write(f, LSpace(s, 6));
End;

WriteLn(f, '');

If KeyPressed Then
Begin
ch := Readkey;
If Ord(ch) = 27 Then
Begin
Close(f);
Exit;
end;
End;

Until dt > = dt_end[Trunc(dd / 3)];

WriteLn(' OK');

dd := dd + 3;

WriteLn(f, '');

Until dd > = 81;
Close(f);

WriteLn;
WriteLn('Beendet. Deko-Tabelle wurde gespeichert als DEKO.TXT');

End;

Begin

fig := 78;
amv := 18;
air_pressure := 1015;

For t1 := 1 To 16 Do
pig_te[t1] := fig / 100;

For t1 := 1 To 100 Do
deko[t1] := t1 * 3;

a[1] := 2.2; b[1] := 0.82; tchalf[1] := 2.65;
a[2] := 1.5; b[2] := 0.82; tchalf[2] := 7.95;
a[3] := 1.08; b[3] := 0.825; tchalf[3] := 12.2;
a[4] := 0.9; b[4] := 0.835; tchalf[4] := 18.5;
a[5] := 0.75; b[5] := 0.845; tchalf[5] := 26.5;
a[6] := 0.58; b[6] := 0.86; tchalf[6] := 37;
a[7] := 0.47; b[7] := 0.87; tchalf[7] := 53;
a[8] := 0.455; b[8] := 0.89; tchalf[8] := 79;
a[9] := 0.455; b[9] := 0.89; tchalf[9] := 114;
a[10] := 0.455; b[10] := 0.934; tchalf[10] := 146;
a[11] := 0.455; b[11] := 0.934; tchalf[11] := 185;
a[12] := 0.38; b[12] := 0.944; tchalf[12] := 238;
a[13] := 0.255; b[13] := 0.962; tchalf[13] := 304;
a[14] := 0.255; b[14] := 0.962; tchalf[14] := 397;
a[15] := 0.255; b[15] := 0.962; tchalf[15] := 503;
a[16] := 0.255; b[16] := 0.962; tchalf[16] := 635;

dt_sta[1] := 0; dt_end[1] := 0; dt_step[1] := 0; (*3m
dt_sta[2] := 0; dt_end[2] := 0; dt_step[2] := 0; (* 6m *)
dt_sta[3] := 20; dt_end[3] := 130; dt_step[3] := 5; (* 9m *)
dt_sta[4] := 15; dt_end[4] := 130; dt_step[4] := 5; (* 12m *)
dt_sta[5] := 15; dt_end[5] := 130; dt_step[5] := 5; (* 15m *)
dt_sta[6] := 10; dt_end[6] := 130; dt_step[6] := 5; (* 18m *)
dt_sta[7] := 8; dt_end[7] := 130; dt_step[7] := 4; (* 21m *)
dt_sta[8] := 8; dt_end[8] := 130; dt_step[8] := 4; (* 24m *)
dt_sta[9] := 4; dt_end[9] := 130; dt_step[9] := 4; (* 27m *)
dt_sta[10] := 4; dt_end[10] := 120; dt_step[10] := 4; (* 30m *)
dt_sta[11] := 4; dt_end[11] := 120; dt_step[11] := 4; (* 33m *)
dt_sta[12] := 4; dt_end[12] := 120; dt_step[12] := 4; (* 36m *)
dt_sta[13] := 4; dt_end[13] := 120; dt_step[13] := 2; (* 39m *)
dt_sta[14] := 4; dt_end[14] := 80; dt_step[14] := 2; (* 42m *)
dt_sta[15] := 4; dt_end[15] := 80; dt_step[15] := 2; (* 45m *)
dt_sta[16] := 4; dt_end[16] := 80; dt_step[16] := 2; (* 48m *)
dt_sta[17] := 2; dt_end[17] := 60; dt_step[17] := 2; (* 51m *)
dt_sta[18] := 2; dt_end[18] := 50; dt_step[18] := 2; (* 54m *)
dt_sta[19] := 2; dt_end[19] := 50; dt_step[19] := 2; (* 57m *)
dt_sta[20] := 2; dt_end[20] := 50; dt_step[20] := 2; (* 60m *)
dt_sta[21] := 2; dt_end[21] := 50; dt_step[21] := 2; (* 63m *)
dt_sta[22] := 2; dt_end[22] := 40; dt_step[22] := 2; (* 66m *)
dt_sta[23] := 2; dt_end[23] := 40; dt_step[23] := 1; (* 69m *)
dt_sta[24] := 2; dt_end[24] := 30; dt_step[24] := 1; (* 72m *)
dt_sta[25] := 2; dt_end[25] := 30; dt_step[25] := 1; (* 75m *)
dt_sta[26] := 1; dt_end[26] := 20; dt_step[26] := 1; (* 78m *)
dt_sta[27] := 1; dt_end[27] := 10; dt_step[27] := 1; (* 81m *)

k := -1.629;
ClrScr;
TextColor(CYAN);
WriteLn('Dekompressionsberechnung (C) 1999 Peter Rachow');
WriteLn('Version vom 24.02.99');
WriteLn;
TextColor(LIGHTBLUE);
WriteLn('W„hlen Sie die Programmfunktion.');
TextColor(LIGHTGREEN);
WriteLn(' Einzelnen (T)auchgang berechnen.');
WriteLn(' (D)eko-Tabelle als Datei erstellen.');
WriteLn(' Andere Taste: ENDE.');
ch := UpCase(ReadKey);
Case ch Of
'T': Begin
TextColor(YELLOW);

WriteLn('Tauchtiefe? [m]');
ReadLn(dive_depth);

WriteLn('Grundzeit? [min.]');
ReadLn(dive_time);

WriteLn('Stickstoffanteil am Atemgasgemisch? [%]');
ReadLn(fig);

WriteLn('Umgebungsluftdruck? [mbar]');
ReadLn(air_pressure);

WriteLn('Atemminutenvolumen des Tauchers? [bar*l/min.]');
ReadLn(amv);

ClrScr;

CalcDive;
End;
'D': Begin
TextColor(YELLOW);

WriteLn('Stickstoffanteil am Atemgasgemisch? [%]');
ReadLn(fig);

WriteLn('Umgebungsluftdruck? [mbar]');
ReadLn(air_pressure);

TextColor(CYAN);
WriteLn('Beginne...');
CalcTable;
End;
End;
Ch := ReadKey;

end.