Bulhmann decompression calculator (ZH16B)

Contributions to this software library are always welcome. Please ensure that you post program listings rather than .raw files. They give a reasonable idea of what your program does without having to load them into a DM42 and you can also include comments in your code. Check out the following link for a decoder/encoder: https://technical.swissmicros.com/decoders/dm42/

You can then copy/paste the listing and post it in "code" tags.
Post Reply
Boub65
Posts: 147
Joined: Tue Sep 12, 2017 4:34 pm
Location: Rabat, Morocco

Bulhmann decompression calculator (ZH16B)

Post by Boub65 »

=========================================
DISCLAIMER :
"zh16b" is a DM42 deco program is given for educational
purpose only (RPN deco calculations)
IT SHOULD NOT BE USED TO PLAN YOUR DIVES...
... although it gives same results (around 99%) as MULTIDECO ANDROID commercial planner!
=========================================

Version changes :
- 26/07/2021 : added surface interval and second dive computing
- 25/07/2021 : Corrected some bugs and documentation errors, split original program in 3 parts, documented code, added mix change during deco stops, added Trimix mixes using Erik Baker's gradient factors
- 21/07/2021 : First release with only Nitrox mixes, no deco mixe changes

Introduction :
This is the first version of a RPN deco planner using the Buhlmann algorithm, the ZH16B algorithm to be precise.
(https://en.m.wikipedia.org/wiki/B%C3%BC ... _algorithm)
The Buhlmann ZH16B algorithm uses a base of 16 M-Values (A and B) for Nitrogen and Helium decompression TABLES.
The program also uses Erik Baker's gradient factors when computing ceiling using Trimix (https://wrobell.dcmod.org/decotengu/model.html)

KNOWN LIMITATIONS : (beware that some are voluntary limitations)
- this version is using Air/Nitrox mixes only (Helium mixes not included but on it's way in some next releases)
(not true anymore in last release)
- this version of the program is limited to only one off-gasing mix (deco mix) (not true anymore in last release)
- the program is METRIC only (but is it really a limitation 🤔)
- the program is limited to 99 meters and 999 minutes
- deco is calculated at sea level in fresh water (but internal data can be changed to accommodate altitude diving in fresh water)
- descent speed is 20m/min, ascent speed is 10m/min, between stops speed is 10m/min (but internals can be changed to accommodate any speed)
- there is NO CHECK on valid/invalid gaz usage in this version. Narcosis and High/Low Oxygen levels are still managed by the computer available between your ears!

DIVE MODEL :
A dive is modeled by a succession of flat segments (legs?), an ascent to the first deco stop, and deco stops until surface is reached.
You can add as many flat segments (legs?) as you need to modelize your dive, each segment with it's own diving mix.
Once you decide to "call the dive", the program calculates the ascent to the first deco stop, first deco stop and each successive stops until surface is reached.
Deco can also be done with different deco mixes, you can change dexo mix at the end of any stop.
When at surface, you can add a surface interval, then a second dive.

WARNING :
1) As usual during the dive (with travel/bottom mixes)...
- Descent time in INCLUDED in segment time and is retrieved form time spent at depth
- Ascent time is EXCLUDED in segment time and time spent at depth is unchanged
- you change mix once arrived at the flat portion of the segment/leg
2) As usual during deco stops (with deco mixes)...
- Ascent time to the following stop is included in following deco stop time
- deco mix is changed at the bottom and ascent to first stop is done with deco mix

HINTS :
A) Bottom/Travel or Deco Mix change :
You can always force a mix change, at any point of the dive, inserting a "0 minute" segment/leg during the dive when prompted with "(?)"
Example :
Y = oo.hh new mix (oo = 02% and hh = HE%)
X = dd.000 where dd is current depth with 0 minutes
Then hit R/S to compute the dive

B) Message prompt in ALHPA
When ALPHA prompt a message including a :
- "(?)" => then the program asks you for a new segment data or to "call the dive"
- "(R/S)" => then the program asks you to hit R/S to get more travel/deco info

C) Each segment/leg is keyed in as this :
1) the mix used for the segment in Y as oo.hh, oo being the O2 percentage in the mix, hh being the He percentage in the mix (21.00 for air, 32.00 for a 32% Nitrox, 50.00 for a 50% deco gas, 18.30 for a 18/30 Trimix for example)
2) the next diving segment in X as dd.mmm , dd being the depth reached in meters and mmm being the duration in minutes of the dive segment (duration INCLUDING descent time and EXCLUDING ascent time)
3) then you hit "R/S" to add the segment to calculations

D) 2 results are show when adding a segment :
1) First result is ascent/descent management to targeted depth shown with a "DIVE ⬇️ (R/S)" or a "DIVE ⬆️ (R/S)" message in ALPHA
- total diving time in Z, often called RUN time (in minutes)
- current mix used by program in Y (as oo.hh)
- dd.mmm in X, depth as nn and mmm as real time spent in ascent/descent ONLY
Hit "R/S" to continue (as shown in ALHPA message)
2) Second result is time spent at depth shown with a "DIVE ➡️ (?)" message in ALPHA
- total diving time in Z (in minutes)
- current mix used by program in Y (as oo.hh)
- dd.mm in X, depth as dd and real time spent at depth in mmm (time spent in ascent or descent from previous depth is removed from segment time)

E) You can add as many segments as you need to simulate your dive.

F) "calling the dive" or computing the deco stops
When you "call the dive", you have to key :
- the first mix used during deco in Y as oo.he (see explanation up somewhere)
- 0 in X because you are asking to reach the surface (0 meters)
- then hit R/S to calculate first deco stop
1) You get first an ascent to the first deco stop, then as many information as there is stops in the deco (every 3 meters)
1.1) First the result is ascent to the first stop with a "ASCENT (R/S)" message in ALPHA
- total dive time still in Z (in minutes)
- Mix used during deco in Y (as oo.hh)
- dd.mmm in X, dd as depth of first deco stop and mmm as duration of the first stop INCLUDING ascent time from last segment
Hit R/S to continue and get all the deco stops informations
1.2) Following results are all the deco stops
- total dive time still in Z (in minutes)
- Mix used during deco in Y (as oo.hh)
- dd.mmm in X, dd as depth of deco stop and mmm as duration of the first stop INCLUDING ascent time from last stop
1.3) after each stop you have two choices
1.3.1) You either hit R/S to continue the deco with the same mix,
1.3.2) Or you enter a new deco mix
- the new mix used during deco in Y as oo.he (see explanation up somewhere)
- 00.000 in X because you are still asking to reach the surface
- then hit R/S to calculate next deco stop with new deco mix

G) Reaching surface, surface interval and second dive
When you reach 0m you get a "SURFACE (?)" message in ALPHA and X is showing 00.000 and Y is showing 21.00 (we suppose you are breathing Air at surface)
You can add a surface segment/leg with 00.mmm where 0 is for surface and mmm the surface interval, you get a "SURFACE ➡️ (?)" asking either for another surface interval segment or a second dive

EXAMPLE OF A DIVE :
You want to plan the following dive :
- Segment 1 : 30 minutes at 30m with air
- Segment 2 : 30 minutes at 20m with 32% Nitrox
- Then you call the dive USING a 50% Nitrox mix for deco
- At 6m stop, you SWITCH to 100% Oxygen deco mix

Launch "zh16b" program
you get a "SURFACE (?)" message in ALHPA
21.00 (air as travel/bottom mix)
ENTER
30.030 (30m, 30 minutes)
R/S
you get a "DIVE ⬇️ (R/S)" message in ALPHA with
Z = 1.5 min (RUN time)
Y = 21.00 (air used)
X = 30.002 (2 minutes descent time from surface to 30m)
HIT R/S
you get a ""DIVE ➡️ (?)" message in ALPHA with
Z = 30 min (RUN time)
Y = 21.00 (air used)
X = 30.029 (29 minutes spent at 30m depth)
You key in
32.00 (new travel/bottom mix)
ENTER
20.030 (20m, 30 minutes)
R/S
You get a "DIVE ⬆️ (R/S)" message in ALPHA
Z = 31 min (RUN time)
Y = 21.00 (air used up to next flat segment)
X = 20.001 (1 minutes ascent time from 30m to 20m)
HIT R/S
you get a "DIVE ➡️ (?)" message in ALPHA with
Z = 61 minute (RUN time)
Y = 32.00 (32% Nitrox used)
X = 20.030 (30 minutes spent at 20m)
You key in
50.00 (we switch to a 50% Nitrox mix for deco)
ENTER
0 (request deco stops computing)
R/S
you get a "ASCENT (R/S)" message in ALPHA
Z = 62.1 (RUN time)
50.00 (50% Nitrox used)
9.001 (first stop is 9m and one minute ascent between 20m and 9m)
HIT R/S
you get a "STOP (R/S)" message in ALPHA
Z = 63 (RUN time)
50.00 (50% Nitrox used)
9.001 (first stop is 9m and one minute stop at 9m, including the ascent time)
You key in
100.00 (we switch to a 100% Oxygen mix for deco)
ENTER
0 (request following deco stops computing)
R/S
you get a "STOP (R/S)" message in ALPHA
Z = 64 (RUN time)
100.00 (100% Oxygen used)
6.001 (next stop is 6m and one minute stop at 6m, including the ascent time)
HIT R/S
you get a "STOP (R/S)" message in ALPHA
Z = 69 (RUN time)
100.00 (100% Oxygen used)
3.005 (next stop is 3m and 5 minutes stop at 3m, including the ascent time)
HIT R/S
you get a "SURFACE" message in ALPHA
Z = 69 (RUN time)
100.00 (100% Oxygen used)
0.000 (you reached surface)

===================================
I will keep in this post short with only the informations to run the ZH16B program on DM42
=> all the program internal informations in a following post to allow anyone to tune their deco scheme
=> all test dives and comparison with the ANDOID commercial MULTIDECO program in a following post
===================================

I have splitted the (very long program) into 3 parts :
zh16b.raw
(1.64 KiB) Downloaded 1 time
zhtools.raw
(412 Bytes) Downloaded 2 times
zhinit.raw
(1.19 KiB) Downloaded 1 time
===============================================

Code: Select all

00 { 1673-Byte Prgm }
01▸LBL "ZH16B"
02 XEQ "ZHINIT"
03 "SURFACE (?)"
04▸LBL "LOOP"
05 XEQ "ZHSHOW"
06 STOP
07 X<>Y
08 STO "O2.HE"
09 R↓
@ PROF2 is stored in the format dd.mmm
@ dd = depth and mmm = minutes of the leg
10 STO "PROF2"
11 RCL "O2.HE"
@ did we enter a mix = 0?
12 X=0?
13 GTO 00
@ mix!=0, we extract the mix composition
@ HE2% is just the fractional part of the mix
14 FP
15 STO "%HE2"
@ now we compute the N22% part
@ N2 = (100 - O2)/100 - HE2%
@ we start at N22% = 100%
16 100
@ we retreive O2 part and compute the %
17 RCL "O2.HE"
18 IP
19 -
20 100
21 ÷
@ we retreive now HE2%
22 RCL "%HE2"
23 -
24 STO "%N22"
@ main and no mix change
25▸LBL 00
@ PROF2 is still in the format dd.mmm
@ dd = depth and mmm = minutes of the leg
26 RCL "PROF2"
@ did we request a stop calculcation
@ if yes, we go to stop calculations
27 X=0?
28 GTO "STOPS"
@ not a stop, we add a new leg
@ we extract first the depth and time of the leg
@ PROF2 = dd.mmm
@ T2 = mmm
29 FP
30 1ᴇ3
31 ×
32 STO "T2"
@ PROF2 = dd
33 RCL "PROF2"
34 IP
35 STO "PROF2"
@ now we claculate the depth gradient 
@ new depth - current depth
36 RCL "PROF"
37 -
@ are we ascending (new depth - current depth>0?)
38 X<0?
39 GTO "UP"
@ are we descending (new deth - current detph>0?)
40 X>0?
41 GTO "DOWN"
@ we are staying at same depth! no need to calculate 
@ ascent od descent part of the leg
@ nor ascent or descent values (R=TR=0)
42 0
43 STO "R"
44 STO "TR"
@ no need to calculate PP because of heavy calculations,
@ just copy B => C
45 XEQ "ZHPPB2C"
@ new mix is now current mix
46 RCL "%N22"
47 STO "%N2"
48 RCL "%HE2"
49 STO "%HE"
@ we have now to calculate the horizontal part of leg
50 GTO "HORIZ"
@ case we are ascending
@ we need to calculate tr and R with Vdwn
51▸LBL "UP"
52 "DIVE ↑ (R/S)"
@ we calculate the ascending leg with current mix
@ rule is to use the current mix when ascending
@ (certainly due to risk of high O2 if we use new 
@ mix of the leg)
@ we use V = Vup
53 RCL "VUP"
54 STO "V"
55 GTO 01
@ case we are descending
@ we need to calculate tr and R with Vdwn
56▸LBL "DOWN"
57 "DIVE ↓ (R/S)"
58 RCL "VDWN"
@ is it the first leg?
59 RCL "PROF"
60 X≠0?
61 GTO 04
@ if it is the first leg, the current mix used during
@ decent is the leg mix!
62 RCL "%N22"
63 STO "%N2"
64 RCL "%HE2"
65 STO "%HE"
@ we reset DTR because it is first leg
@ important if we track surface intervals
66 0
67 STO "DTR"
@ now we are sure to have the good mix in %N2 and %HE
68▸LBL 04
@ we calculate the descending with current mix
@ rule is to use the current mix when descending
@ we use k = Vdwn
69 RCL "VDWN"
70 STO "V"
@ all the calculation are now independent of Vup 
@ and Vdwn stored in V
71▸LBL 01
@ tr = (Proff - Profi)/V
@ proff is leg depth
@ profi is current depth
72 RCL "PROF2"
73 RCL "PROF"
74 -
75 RCL "V"
76 ÷
77 STO "TR"
@ R = mtob*N2*V
78 RCL "%N2"
79 RCL "MTOB"
80 ×
81 RCL "V"
82 ×
83 STO "R"
@ Pio2 = (Prof*mtob + Patm - Pwvp)
@ Pio = Pio2 * N2
84 RCL "PATM"
85 RCL "PWVP"
86 -
87 RCL "PROF"
88 RCL "MTOB"
89 ×
90 +
91 STO "PIO2"
92 RCL "%N2"
93 ×
94 STO "PIO"
@ we calculate then PP during ascent/descend
@ PP (Pio, tr, R, Periode, B => C)
95 RCL "TN2"
96 XEQ "ZHPPV"
@ R = mtob*He*V
97 RCL "%HE"
98 RCL "MTOB"
99 ×
100 RCL "V"
101 ×
102 STO "R"
@ Pio = Pio2 * He
103 RCL "PIO2"
104 RCL "%HE"
105 ×
106 STO "PIO"
@ we calculate then PP during ascent/descend
@ PP (Pio, tr, R, Periode, B => C)
107 RCL "THE"
108 XEQ "ZHPPV"
@ dtr = dtr + tr
109 RCL "TR"
110 STO+ "DTR"
111 XEQ "ZHSHOWV"
112 STOP
@ after calculating ascent/descent with current mix,
@ the leg is now calculated with leg mix 
113 RCL "%N22"
114 STO "%N2"
115 RCL "%HE2"
116 STO "%HE"
@ calculate the flat portion of the leg
117▸LBL "HORIZ"
118 "DIVE → (?)"
@ did we dive or is it just a surface interval?
119 RCL "PROF2"
120 X=0?
@ here we know that we are dealing with a surface
@ interval
121 "SURFACE → (?)"
@ is it a "virtual leg" with no time at depth.
@ this is used to change mixes for example
122 RCL "T2"
123 X=0?
124 GTO 02
@ were we ascending ? if we are time during ascent
@ is not retreived from time at depth
@ total leg time is kept unchanged
125 RCL "PROF2"
126 RCL "PROF"
127 -
128 X<0?
129 GTO 03
@ were are descending, so time during descent is
@ included in total leg time
130 RCL "TR"
131 STO- "T2"
@ do we find ourselves with a negative time at depth, 
@ so we need to correct with 0 and skip heavy PP
@ calculations
132 RCL "T2"
133 X>0?
134 GTO 03
135 0
136 STO "T2"
@ we skip heavy PP computing because time in flat 
@ part of the leg is =0
137 GTO 02
@ now we calculate the flat portion of the leg
138▸LBL 03
@ new depth = leg depth
139 RCL "PROF2"
140 STO "PROF"
@ Pio2 = (Prof*mtob + Patm - Pwvp)
@ Pio = Pio2 * N2
141 RCL "PROF"
142 RCL "MTOB"
143 ×
144 RCL "PATM"
145 +
146 RCL "PWVP"
147 -
148 STO "PIO2"
149 RCL "%N2"
150 ×
151 STO "PIO"
@ we calculate PP (Pio, t, Periode, C => B)
152 RCL "TN2"
153 XEQ "ZHPP"
@ Pio = Pio2 * He
154 RCL "PIO2"
155 RCL "%HE"
156 ×
157 STO "PIO"
@ we calculate PP (Pio, t, Periode, C => B)
158 RCL "THE"
159 XEQ "ZHPP"
@ dtr = dtr + t2
160 RCL "T2"
161 STO+ "DTR"
162 GTO "LOOP"
@ in case flat portion of leg is = 0
@ we just copy C => B due to heavy calculation in PP
163▸LBL 02
@ new depth = leg depth (should already be the case!)
164 RCL "PROF2"
165 STO "PROF"
166 XEQ "ZHPPC2B"
@ dtr = dtr + t2 (should be +0!)
167 RCL "T2"
168 STO+ "DTR"
169 GTO "LOOP"
@ ==========================
@ part of the program that computes the end of the dive
@ ==========================
170▸LBL "STOPS"
@ we suppose ceiling is surface
171 0
172 STO "PALIER2"
@ we start with gf = gfmin
173 RCL "GFMIN"
174 STO "GF"
@ calculate the ceiling in Palier2 going from bottom
@ ceiling is calculated for both N2 and He
175 XEQ "ZHCEIL"
176 RCL "PALIER2"
@ new target depth is now the calculated ceiling
177 STO "PROF2"
@ tr = (proff - profi) / Vup
@ proff is first stop
@ profi is bottom depth
178 RCL "PROF2"
179 RCL "PROF"
180 -
181 RCL "VUP"
182 ÷
183 STO "TR"
@ R = Vup*mtob*N2
@ we are still ascending with Vup speed
@ mix used is new deco mix rather than current bottom @ mix so we use %N22 and %HE2
184 RCL "VUP"
185 RCL "%N22"
186 ×
187 RCL "MTOB"
188 ×
189 STO "R"
@ Pio = (prof*mtob + Patm - Pwvp)
@ Pio = Pio2 * N2
@ Prof is bottom
190 RCL "PATM"
191 RCL "PWVP"
192 -
193 RCL "PROF"
194 RCL "MTOB"
195 ×
196 +
197 STO "PIO2"
198 RCL "%N22"
199 ×
200 STO "PIO"
@ we calculate then PP during ascent/descend
@ PP (Pio, tr, R, Periode, B => C)
201 RCL "TN2"
202 XEQ "ZHPPV"
@ R = Vup*mtob*He
@ we are still ascending with Vup speed
203 RCL "VUP"
204 RCL "%HE2"
205 ×
206 RCL "MTOB"
207 ×
208 STO "R"
@ Pio = Pio2*HE
@ Prof is bottom
209 RCL "PIO2"
210 RCL "%HE2"
211 ×
212 STO "PIO"
@ we calculate then PP during ascent/descend
@ PP (Pio, tr, R, Periode, B => C)
213 RCL "THE"
214 XEQ "ZHPPV"
@ dtr = dtr + tr
215 RCL "TR"
216 STO+ "DTR"
@ we need to switch now current mix with new mix 
@ or the display will be wrong showing bottom mix
@ now that we have ascended, we switch to new deco mix
@ for flat leg
217 RCL "%N22"
218 STO "%N2"
219 RCL "%HE2"
220 STO "%HE"
221 "ASCENT (R/S)"
222 XEQ "ZHSHOWV"
223 STOP
@ new depth is first stop depth for flat leg
224 RCL "PROF2"
225 STO "PROF"
@ did we reach surface?
226 X=0?
@ if we reached surface during first ascent
227 GTO 31
@ we didn't reach surface we need to calculate stop time
@ first stop time is was is left from ascent rounded to
@ nearest minute
228 RCL "TR"
229 RCL "TR"
230 IP
231 -
232 STO "TR"
@ we compute now gfsteps using 
@ steps = int(palier/3)
@ gfsteps = (gfmax- gfmin)/steps or 0
233 RCL "PROF"
234 3
235 ÷
236 IP
@ if steps = 0 we do not divide by steps
@ we should NOT have palier = 0!
237 X=0?
238 GTO 22
239 RCL "GFMAX"
240 RCL "GFMIN"
241 -
242 X<>Y
243 ÷
244▸LBL 22
245 STO "GFSTEP"
@ loop on stops until stop <= 0 (surface is reached)
246▸LBL 30
247 RCL "PROF"
@ did we reach surface, then we exit
248 X≤0?
249 GTO 31
@ we didn't reach surface, we compute time spent at stop
@ Pio2 = (palier*mtob + Patm - Pwvp)
250 RCL "PATM"
251 RCL "PWVP"
252 -
253 RCL "PROF"
254 RCL "MTOB"
255 ×
256 +
257 STO "PIO2"
@ t2 -= tr 
@ we remove from first minute of deco time spent 
@ ascending to the stop
258 RCL "TR"
259 +/-
260 STO "T2"
@ Palier2 = palier for the +1minute loop 
261 RCL "PROF"
262 STO "PALIER2"
@ gf += gfstep
263 RCL "GFSTEP"
264 STO+ "GF"
@ loop did we change deco stop adding +1minute
@ in computing
265▸LBL 40
266 RCL "PROF"
267 RCL "PALIER2"
@ did we change stop depth?
@ we get out of the "LBL 40" loop
268 X≠Y?
269 GTO 41
@ we add +1minute to stop time
270 1
271 STO+ "T2"
@ Pio = Pio2 * N2
272 RCL "PIO2"
273 RCL "%N2"
274 ×
275 STO "PIO"
@ we compute PP with one more minute at stop
@ we compute PP (Pio, t, Periode, C => B)
276 RCL "TN2"
277 XEQ "ZHPP"
@ Pio = Pio2 * He
278 RCL "PIO2"
279 RCL "%HE"
280 ×
281 STO "PIO"
@ we compute PP with one more minute at stop
@ we compute PP (Pio, t, Periode, C => B)
282 RCL "THE"
283 XEQ "ZHPP"
284 0
285 STO "PALIER2"
286 XEQ "ZHCEIL"
287 RCL "PALIER2"
288 RCL "PROF"
289 3
290 -
@ did the new ceiling > current depth +3m ?
@ in that case new ceiling is current - 3m
291 X<Y?
292 X<>Y
293 STO "PALIER2"
@ we loop for one more minute?
294 GTO 40
@ we reached enought time to go to next stop
295▸LBL 41
@ DTR = DTR + t2
296 RCL "T2"
297 STO+ "DTR"
298 "STOP (R/S)"
299 XEQ "ZHSHOW"
300 STOP
@ are we requesting a new deco mix beetween stops? @ new deco mix requested with X=0
301 X≠0?
302 GTO 42
@ new mix requested
303 R↓
304 STO "O2.HE"
@ the HE% part is just the frational part
305 FP
306 STO "%HE2"
@ now we compute the N22% part
@ N2 = (100 - O2)/100 - HE2%
@ we start at N22% = 100%
307 100
@ we retreive O2 part and compute the %
308 RCL "O2.HE"
309 IP
310 -
311 100
312 ÷
@ we retreive now HE2%
313 RCL "%HE2"
314 -
315 STO "%N22"
@ we continue to next stop
316▸LBL 42
@ tr = (palier2 - current) / Vpalier
317 RCL "PALIER2"
318 RCL "PROF"
319 -
320 RCL "VPALIER"
321 ÷
322 STO "TR"
@ mix is still the last on ascent one before swithing
@ R = Vpalier*mtob*N2
323 RCL "VPALIER"
324 RCL "MTOB"
325 ×
326 RCL "%N2"
327 ×
328 STO "R"
@ Pio is still ok from last calculation
@ depth for Pio is last stop
329 RCL "PIO2"
330 RCL "%N2"
331 ×
332 STO "PIO"
@ we calculate then PP during ascent/descend
@ PP (Pio, tr, R, Periode, B => C)
333 RCL "TN2"
334 XEQ "ZHPPV"
@ R = Vpalier*mtob*He
335 RCL "VPALIER"
336 RCL "MTOB"
337 ×
338 RCL "%HE"
339 ×
340 STO "R"
@ Pio is still ok from last calculation
341 RCL "PIO2"
342 RCL "%HE"
343 ×
344 STO "PIO"
@ we calculate then PP during ascent/descend
@ PP (Pio, tr, R, Periode, B => C)
345 RCL "THE"
346 XEQ "ZHPPV"
@ now new mix will be used
347 RCL "%N22"
348 STO "%N2"
349 RCL "%HE2"
350 STO "%HE"
@ new depth is current stop
351 RCL "PALIER2"
352 STO "PROF"
@ did we surface => end
353 X=0?
354 GTO 31
@ we didn't surface we add ascent to stop in run time
355 RCL "TR"
356 STO+ "DTR"
@ loop
357 GTO 30
@ end of the dive, we reched surface
358▸LBL 31
@ we reached surface, depth = 0, time leg = 0
359 "SURFACE ↑ (R/S)"
360 0
361 STO "PROF2"
362 STO "PROF"
363 STO "T2"
364 XEQ "ZHSHOW"
365 STOP
@ before looping to surface
@ we put the DTR = 0
@ and reset mix to surface air mix
366 0
367 STO "DTR"
368 STO "%HE2"
369 STO "%HE"
370 RCL "N2SURF"
371 STO "%NE"
372 STO "%NE2"
373 "SURFACE (?)"
374 GTO "LOOP"
375 END
===============================================

Code: Select all

00 { 739-Byte Prgm }
01▸LBL "ZHTOOLS"
02▸LBL "ZHPP"
03 STO "I"
04▸LBL 50
05 RCL "I"
06 RCL 00
07 4
08 ×
09 +
10 STO "J"
11 2
12 LN
13 RCL IND "I"
14 ÷
15 RCL "T2"
16 ×
17 +/-
18 E^X
19 1
20 -
21 RCL IND "J"
22 RCL "PIO"
23 -
24 ×
25 RCL IND "J"
26 +
27 RCL "I"
28 RCL 00
29 3
30 ×
31 +
32 X<>Y
33 STO IND ST Y
34 ISG "I"
35 GTO 50
36 RTN
37▸LBL "ZHPPV"
38 STO "I"
39▸LBL 60
40 RCL "I"
41 RCL 00
42 3
43 ×
44 +
45 STO "J"
46 2
47 LN
48 RCL IND "I"
49 ÷
50 STO "K"
51 RCL "PIO"
52 RCL IND "J"
53 -
54 RCL "R"
55 RCL "K"
56 ÷
57 -
58 RCL "K"
59 RCL "TR"
60 ×
61 +/-
62 E^X
63 ×
64 +/-
65 RCL "PIO"
66 +
67 RCL "TR"
68 RCL "K"
69 1/X
70 -
71 RCL "R"
72 ×
73 +
74 RCL "I"
75 RCL 00
76 4
77 ×
78 +
79 X<>Y
80 STO IND ST Y
81 ISG "I"
82 GTO 60
83 RTN
84▸LBL "ZHPPB2C"
85 RCL "BN2"
86 XEQ 70
87 RCL "BHE"
88 XEQ 70
89 RTN
90▸LBL 70
91 STO "I"
92▸LBL 71
93 RCL "I"
94 RCL 00
95 +
96 STO "J"
97 RCL IND "I"
98 STO IND "J"
99 ISG "I"
100 GTO 71
101 RTN
102▸LBL "ZHPPC2B"
103 RCL "BN2"
104 XEQ 80
105 RCL "BHE"
106 XEQ 80
107 RTN
108▸LBL 80
109 STO "I"
110▸LBL 81
111 RCL "I"
112 RCL 00
113 +
114 STO "J"
115 RCL IND "J"
116 STO IND "I"
117 ISG "I"
118 GTO 81
119 RTN
@ ===========================================
@ we compute ceiling first for N2 then for He
@ ===========================================
120▸LBL "ZHCEIL"
@ we compute the ceiling using Buhlmann equation
@ extended with gradient factors by Erik Baker
121 XEQ 10
@ we have the ceiling in PALIER2
@ we first check if we are near surface
122 RCL "EPSILON"
123 RCL "PALIER2"
124 X<Y?
@ celiling is 0 (surface)
125 GTO 12
@ else we fing the nearest stop (multiple of 3m)
126 3
127 ÷
128 RCL "EPSILON"
129 +
130 IP
131 1
132 +
133 3
134 ×
135 GTO 13
136▸LBL 12
137 0
138▸LBL 13
139 STO "PALIER2"
140 RTN
141▸LBL 10
142 RCL "N2A"
143 LSTO "I"
144 RCL "HEA"
145 LSTO "J"
146▸LBL 11
@ we retreive PBN2b (BN2)
147 RCL "I"
148 RCL 00
149 2
150 ×
151 +
@ PPN2
152 RCL IND ST X
153 LSTO "PN2"
@ P = PPN2 (+ PPHE)
154 LSTO "P"
@ we retreive N2A
155 RCL IND "I"
156 RCL "PN2"
157 ×
@ A = PPN2 x N2A
158 LSTO "A"
@ we retreive PBHEb (BHE)
159 RCL "J"
160 RCL 00
161 2
162 ×
163 +
@ PPHE
164 RCL IND ST X
165 LSTO "PHE"
@ P = PPN2 + PPHE
166 STO+ "P"
@ we retreive HEA
167 RCL IND "J"
168 RCL "PHE"
169 ×
@ A = PPN2 * N2A + PPHE * HEA
170 STO+ "A"
171 RCL "P"
@ A = A/P
172 STO÷ "A"
@ we retreive N2B
173 RCL "I"
174 RCL 00
175 +
@ N2B
176 RCL IND ST X
@ B = N2B * PN2
177 RCL "PN2"
178 ×
179 LSTO "B"
@ we retreive HEB
180 RCL "J"
181 RCL 00
182 +
@ HEB
183 RCL IND ST X
@ B = N2B * PN2 + HEB * PHE
184 RCL "PHE"
185 ×
186 STO+ "B"
187 RCL "P"
@ B = B/P
188 STO÷ "B"
@ we retreive N2A
189 RCL "P"
190 RCL "A"
191 RCL "GF"
192 ×
193 -
194 RCL "GF"
195 RCL "B"
196 ÷
197 1
198 +
199 RCL "GF"
200 -
201 ÷
202 RCL "PATM"
203 -
204 RCL "MTOB"
205 ÷
@ did we find a greater ceiling?
@ if yes, we must store it
206 RCL "PALIER2"
207 X<Y?
208 X<>Y
209 STO "PALIER2"
210 1
211 STO+ "J"
212 ISG "I"
213 GTO 11
214 RTN
215▸LBL "ZHSHOWV"
216 RCL "TR"
217 1ᴇ3
218 ÷
219 RCL "PROF2"
220 +
221 STO "I"
222 RCL "TR"
223 IP
224 STO "J"
225 RCL "TR"
226 FP
227 60
228 ×
229 100
230 ÷
231 STO+ "J"
232 GTO 97
233▸LBL "ZHSHOW"
234 RCL "T2"
235 1ᴇ3
236 ÷
237 RCL "PROF"
238 +
239 STO "I"
240 RCL "T2"
241 IP
242 STO "J"
243 RCL "T2"
244 FP
245 60
246 ×
247 100
248 ÷
249 STO+ "J"
250▸LBL 97
@ we start with 100% O2
251 100
@ we retreive now the N2 part
252 RCL "%N2"
253 100
254 ×
255 IP
256 -
@ we retreive now the HE part
257 RCL "%HE"
258 100
259 ×
260 IP
261 -
@ we add the fractional part of HE%
262 RCL "%HE"
263 +
264 STO "O2.HE"
265 RCL "J"
266 RCL "DTR"
267 RCL "O2.HE"
268 RCL "I"
269 RTN
270 END
===============================================

Code: Select all

00 { 1592-Byte Prgm }
01▸LBL "ZHINIT"
02 SIZE 161
03 FIX 03
04 0
05 STO "PROF"
06 STO "DTR"
07 STO "%HE"
08 STO "PROF2"
09 STO "T2"
10 STO "%HE2"
11 0.7902
12 STO "%N2"
13 STO "%N22"
14 STO "N2SURF"
15 20
16 STO "VDWN"
17 10
18 +/-
19 STO "VUP"
22 STO "VPALIER"
20 0
21 STO "V"
23 0.3
24 STO "GFMIN"
25 0.85
26 STO "GFMAX"
27 1ᴇ-6
28 STO "EPSILON"
29 0.0627
30 STO "PWVP"
31 1.01325
32 STO "PATM"
33 0.09985
34 STO "MTOB"
35 16
36 STO "I"
37 STO 00
38 1.01601
39 STO "TN2"
40 STO "I"
41 5
42 STO IND "I"
43 ISG "I"
44 8
45 STO IND "I"
46 ISG "I"
47 12.5
48 STO IND "I"
49 ISG "I"
50 18.5
51 STO IND "I"
52 ISG "I"
53 27
54 STO IND "I"
55 ISG "I"
56 38.3
57 STO IND "I"
58 ISG "I"
59 54.3
60 STO IND "I"
61 ISG "I"
62 77
63 STO IND "I"
64 ISG "I"
65 109
66 STO IND "I"
67 ISG "I"
68 146
69 STO IND "I"
70 ISG "I"
71 187
72 STO IND "I"
73 ISG "I"
74 239
75 STO IND "I"
76 ISG "I"
77 305
78 STO IND "I"
79 ISG "I"
80 390
81 STO IND "I"
82 ISG "I"
83 498
84 STO IND "I"
85 ISG "I"
86 635
87 STO IND "I"
88 17.03201
89 STO "N2A"
90 STO "I"
91 1.1696
92 STO IND "I"
93 ISG "I"
94 1
95 STO IND "I"
96 ISG "I"
97 0.8618
98 STO IND "I"
99 ISG "I"
100 0.7562
101 STO IND "I"
102 ISG "I"
103 0.6667
104 STO IND "I"
105 ISG "I"
106 0.56
107 STO IND "I"
108 ISG "I"
109 0.4947
110 STO IND "I"
111 ISG "I"
112 0.45
113 STO IND "I"
114 ISG "I"
115 0.4187
116 STO IND "I"
117 ISG "I"
118 0.3798
119 STO IND "I"
120 ISG "I"
121 0.3497
122 STO IND "I"
123 ISG "I"
124 0.3223
125 STO IND "I"
126 ISG "I"
127 0.285
128 STO IND "I"
129 ISG "I"
130 0.2737
131 STO IND "I"
132 ISG "I"
133 0.2523
134 STO IND "I"
135 ISG "I"
136 0.2327
137 STO IND "I"
138 33.04801
139 STO "N2B"
140 STO "I"
141 0.5578
142 STO IND "I"
143 ISG "I"
144 0.6514
145 STO IND "I"
146 ISG "I"
147 0.7222
148 STO IND "I"
149 ISG "I"
150 0.7825
151 STO IND "I"
152 ISG "I"
153 0.8126
154 STO IND "I"
155 ISG "I"
156 0.8434
157 STO IND "I"
158 ISG "I"
159 0.8693
160 STO IND "I"
161 ISG "I"
162 0.891
163 STO IND "I"
164 ISG "I"
165 0.9092
166 STO IND "I"
167 ISG "I"
168 0.9222
169 STO IND "I"
170 ISG "I"
171 0.9319
172 STO IND "I"
173 ISG "I"
174 0.9403
175 STO IND "I"
176 ISG "I"
177 0.9477
178 STO IND "I"
179 ISG "I"
180 0.9544
181 STO IND "I"
182 ISG "I"
183 0.9602
184 STO IND "I"
185 ISG "I"
186 0.9653
187 STO IND "I"
188 49.06401
189 STO "BN2"
190 STO "I"
191 RCL "PATM"
192 RCL "PWVP"
193 -
194 RCL "N2SURF"
195 ×
196▸LBL 99
197 STO IND "I"
198 ISG "I"
199 GTO 99
200 65.08001
201 STO "CN2"
202 STO "I"
203 0
204▸LBL 98
205 STO IND "I"
206 ISG "I"
207 GTO 98
208 81.09601
209 STO "THE"
210 STO "I"
211 1.88
212 STO IND "I"
213 ISG "I"
214 3.02
215 STO IND "I"
216 ISG "I"
217 4.72
218 STO IND "I"
219 ISG "I"
220 6.99
221 STO IND "I"
222 ISG "I"
223 10.21
224 STO IND "I"
225 ISG "I"
226 14.48
227 STO IND "I"
228 ISG "I"
229 20.53
230 STO IND "I"
231 ISG "I"
232 29.11
233 STO IND "I"
234 ISG "I"
235 41.20
236 STO IND "I"
237 ISG "I"
238 55.19
239 STO IND "I"
240 ISG "I"
241 70.69
242 STO IND "I"
243 ISG "I"
244 90.34
245 STO IND "I"
246 ISG "I"
247 115.29
248 STO IND "I"
249 ISG "I"
250 147.42
251 STO IND "I"
252 ISG "I"
253 188.24
254 STO IND "I"
255 ISG "I"
256 240.03
257 STO IND "I"
258 97.11201
259 STO "HEA"
260 STO "I"
261 1.6189
262 STO IND "I"
263 ISG "I"
264 1.3830
265 STO IND "I"
266 ISG "I"
267 1.1919
268 STO IND "I"
269 ISG "I"
270 1.0458
271 STO IND "I"
272 ISG "I"
273 0.9220
274 STO IND "I"
275 ISG "I"
276 0.8205
277 STO IND "I"
278 ISG "I"
279 0.7305
280 STO IND "I"
281 ISG "I"
282 0.6502
283 STO IND "I"
284 ISG "I"
285 0.5950
286 STO IND "I"
287 ISG "I"
288 0.5545
289 STO IND "I"
290 ISG "I"
291 0.5333
292 STO IND "I"
293 ISG "I"
294 0.5189
295 STO IND "I"
296 ISG "I"
297 0.5181
298 STO IND "I"
299 ISG "I"
300 0.5176
301 STO IND "I"
302 ISG "I"
303 0.5172
304 STO IND "I"
305 ISG "I"
306 0.5119
307 STO IND "I"
308 113.12801
309 STO "HEB"
310 STO "I"
311 0.4770
312 STO IND "I"
313 ISG "I"
314 0.5747
315 STO IND "I"
316 ISG "I"
317 0.6527
318 STO IND "I"
319 ISG "I"
320 0.7223
321 STO IND "I"
322 ISG "I"
323 0.7582
324 STO IND "I"
325 ISG "I"
326 0.7957
327 STO IND "I"
328 ISG "I"
329 0.8279
330 STO IND "I"
331 ISG "I"
332 0.8553
333 STO IND "I"
334 ISG "I"
335 0.8757
336 STO IND "I"
337 ISG "I"
338 0.8903
339 STO IND "I"
340 ISG "I"
341 0.8997
342 STO IND "I"
343 ISG "I"
344 0.9073
345 STO IND "I"
346 ISG "I"
347 0.9122
348 STO IND "I"
349 ISG "I"
350 0.9171
351 STO IND "I"
352 ISG "I"
353 0.9217
354 STO IND "I"
355 ISG "I"
356 0.9267
357 STO IND "I"
358 129.14401
359 STO "BHE"
360 STO "I"
361 0
362▸LBL 97
363 STO IND "I"
364 ISG "I"
365 GTO 97
366 145.16001
367 STO "CHE"
368 STO "I"
369 0
370▸LBL 96
371 STO IND "I"
372 ISG "I"
373 GTO 96
374 RTN
375 END
=================================================
Last edited by Boub65 on Mon Jul 26, 2021 12:34 pm, edited 9 times in total.
Sincèrement, Sincerely, 73,
Boubker

2xDM15L, DM41L, DM42 SN#00855 (+one lost during shipping), DM41X #00707
TI-89 titanium, CASIO fx-cg50 (to play with micropython)

There are three kinds of people in the world: those who know math and those who don't.
Boub65
Posts: 147
Joined: Tue Sep 12, 2017 4:34 pm
Location: Rabat, Morocco

Re: Bulhmann decompression calculator (ZH16B)

Post by Boub65 »

This project started as a DM41X project.

Unfortunately, DM41X cannot handle such a big program with a minimum of 160 Buhlmann data (16x period, a and b values for N2 and same for He).

I should have used Hepax modules to make it possible on DM41X. I refused to go on that path, because the Hepax learning curve is "though" AND it suppresses DM42 compatibility!

So I switched to DM42 just changing registers by variables in first release.
That's why there is no use (yet) of
- Matrices
- Menus

I will improve the progam in the future using 100% of DM42 features, now that DM41X platform is excluded.

Sincerely,
Boubker.
Last edited by Boub65 on Wed Jul 21, 2021 5:49 pm, edited 1 time in total.
Sincèrement, Sincerely, 73,
Boubker

2xDM15L, DM41L, DM42 SN#00855 (+one lost during shipping), DM41X #00707
TI-89 titanium, CASIO fx-cg50 (to play with micropython)

There are three kinds of people in the world: those who know math and those who don't.
Boub65
Posts: 147
Joined: Tue Sep 12, 2017 4:34 pm
Location: Rabat, Morocco

Re: Bulhmann decompression calculator (ZH16B)

Post by Boub65 »

You have read the disclaimer :
=========================================
DISCLAIMER :
this DM42 deco program is given for educational
purpose only (RPN deco calculations)
IT SHOULD NOT BE USED TO PLAN YOUR DIVES...
... although it gives same results (around 99%) as MULTIDECO commercial planner!
=========================================
But...
... nevertheless, here is some dives that were tested against the ANDROID MULTIDECO commercial program with exact same results :
Dive#1 : 30m, 3min, Air
Dive#2 : 40m, 20min, Air
Dive#3 : 35m, 40min, Air
Dive#4 : 40m, 35min, Air
Dive#5 : 20m, 35min, Air
Dive#6 : 20m, 10min, Air
Dive#7 : 20m, 6min, Air
Dive#8 : 20m, 7min, Air
Dive#9 : 26m 25min, Air
Dive#10 : 30m, 30min, Air
Dive#11 : 32m, 15min, 32% Nitrox
Dive#12 : 32m, 50min, 32% Nitrox
Dive#13 : 32m, 25min, 32% Nitrox
Dive#14 : 32m, 49min, 32% Nitrox
Dive#15 : 30m, 10min, Air + 20m, 20min Air
Dive#16 : 36m, 20min, Air + 20m, 20min Air
Dive#17 : 20m, 7min, Air + 36m, 20min, Air
Dive#18 : 60m, 20min, 18/30 Trimix, 50% Nitrox, 100% Oxygen

Some dives give differents results when tested against MULTIDECO, but it's always a +1 or -1 minute difference in a stop and a -1 or +1 difference in next stop.
This is certainly only due to precision difference in deco calculation between different programs.
I could not reproduce a 100% MULTIDECO precision scheme in my program although I did try hard!

Sincerely,
Boubker.
Last edited by Boub65 on Mon Jul 26, 2021 12:33 am, edited 2 times in total.
Sincèrement, Sincerely, 73,
Boubker

2xDM15L, DM41L, DM42 SN#00855 (+one lost during shipping), DM41X #00707
TI-89 titanium, CASIO fx-cg50 (to play with micropython)

There are three kinds of people in the world: those who know math and those who don't.
Boub65
Posts: 147
Joined: Tue Sep 12, 2017 4:34 pm
Location: Rabat, Morocco

Re: Bulhmann decompression calculator (ZH16B)

Post by Boub65 »

Today, I added the ability :
- to use Trimix
- and to switch deco mixes

Example of a Trimix dive :

You want to plan the following dive :
20 minutes at 60m with 18/30 Trimix
You call the dive USING 18/30 Trimix as deco mix
At 21m stop you SWITCH to a 50% Nitrox deco mix
At 6m stop you SWITCH to a 100 Oxygen deco mix

Launch ZH16B, you get a "SURFACE (?)" message in ALHPA
18.30 (18/30 Trimix)
ENTER
60.020
R/S
you get a "DIVE ⬇️ (R/S)" message in ALPHA with
Z = 3 min (RUN time)
Y = 18.30 (18/30 Trimix used)
X = 60.003 (3 minutes descent time from surface to 60m)
HIT R/S
you get a ""DIVE ➡️ (?)" message in ALPHA with
Z = 20 min (RUN time)
Y = 18.30 (18/30 Trimix used)
X = 60.017 (17 minutes spent at 60m depth)
You key in
18.30
ENTER
0
R/S
you get a "ASCENT (R/S)" message in ALPHA
Z = 23 (RUN time)
Y = 18.30 (18/30 Trimix used)
30.003 (first stop is 30m and 3 minute ascent between 60m and 30m)
HIT R/S
you get a "STOP (R/S)" message in ALPHA
Z = 24 (RUN time)
Y = 18.30 (18/30 Trimix used)
30.001 (first stop is 30m and one minute stop at 30m, including the ascent time)
HIT R/S
you get a "STOP (R/S)" message in ALPHA
Z = 25 (RUN time)
Y = 18.30 (18/30 Trimix used)
27.001 (next stop is 27m and one minute stop at 27m, including the ascent time)
HIT R/S
you get a "STOP (R/S)" message in ALPHA
Z = 26 (RUN time)
Y = 18.30 (18/30 Trimix used)
24.001 (next stop is 24m and one minute stop at 24m, including the ascent time)
You then switch deco mix to a 50% Nitrox deco mix
50.00 (50% Nitrox deco mix)
ENTER
0
R/S
you get a "STOP (R/S)" message in ALPHA
Z = 27 (RUN time)
Y = 50.00 (50% Nitrox used)
21.001 (next stop is 21m and one minute stop at 21m, including the ascent time)
HIT R/S
you get a "STOP (R/S)" message in ALPHA
Z = 28 (RUN time)
Y = 50.00 (50% Nitrox used)
18.001 (next stop is 18m and one minute stop at 18m, including the ascent time)
HIT R/S
you get a "STOP (R/S)" message in ALPHA
Z = 30 (RUN time)
Y = 50.00 (50% Nitrox used)
15.002 (next stop is 15m and 2 minute stop at 15m, including the ascent time)
HIT R/S
you get a "STOP (R/S)" message in ALPHA
Z = 33 (RUN time)
Y = 50.00 (50% Nitrox used)
12.003 (next stop is 12m and 3 minute stop at 12m, including the ascent time)
HIT R/S
you get a "STOP (R/S)" message in ALPHA
Z = 37 (RUN time)
Y = 50.00 (50% Nitrox used)
9.004 (next stop is 9m and 4 minute stop at 9m, including the ascent time)
HIT R/S
You then switch deco mix to a 100% Oxygen deco mix
100.00 (100% Oxygen deco mix)
ENTER
0
R/S
you get a "STOP (R/S)" message in ALPHA
Z = 42 (RUN time)
Y = 100.00 (100% Oxygen used)
6.005 (next stop is 6m and 5 minute stop at 6m, including the ascent time)
HIT R/S
you get a "STOP (R/S)" message in ALPHA
Z = 51 (RUN time)
Y = 100.00 (100% Oxygen used)
3.009 (next stop is 3m and 9 minute stop at 3m, including the ascent time)
HIT R/S
Z = 51 (RUN time)
Y = 100.00 (100% Oxygen used)
0.000 (you reached surface)

Here is the same dive on the MULTIDECO Android commercial application (with the exact same results) :
20210725_204123.jpg
20210725_204123.jpg (169.86 KiB) Viewed 100 times
Sincèrement, Sincerely, 73,
Boubker

2xDM15L, DM41L, DM42 SN#00855 (+one lost during shipping), DM41X #00707
TI-89 titanium, CASIO fx-cg50 (to play with micropython)

There are three kinds of people in the world: those who know math and those who don't.
Post Reply