(gdb) break *0x972

Debugging, GNU± Linux and WebHosting and ... and ...

Computing Scubadiver Air Consumption

When you're scubadiving, one important thing is to keep track of the air you've got left in your tank, and more importantly, how fast it goes down.

Just a quick reminder for non-scubadiver readers: the deeper you are, the more air you consume, because of the increased pressure. At surface level (1atm/~1bar), your lungs can hold ~7l of air. At 10m (2atm), they'll hold the equivalent of 14l of air. That's 21l at 20m, 28l at 30m and 35l at 40m. That means that if you hold your breath from 40m to surface, you'll literally explode! It also means that you don't consume the same quantity for air depending of your diving depth.

And what I wanted to do is estimating the air consumption speed. Of course I could buy a diving computing connected to the tank gauge, but that's out of my budget. So I programmed it :-) With my dive computer, I do have a report of the dive depth, every 20s :

Dive depth profile

I also know the volume of my tank (12l or 15l, carved on the tank), the initial pressure (usually ~200/230bar) and the end-of-dive pressure (100bar here), read on the gauge. Of course this is approximate, but that's the poor man way! I retrieve the figures of the dive depth and time inside my Subsurface XML divelog, as well as the dive tank information:

<divecomputer model='Suunto Vyper' deviceid='5aa559db' diveid='8f75b186'>
  <depth max='10.058 m' mean='6.601 m' />
  <temperature air='17.0 C' water='17.0 C' />
  <sample time='0:00 min' depth='0.0 m' />
  <sample time='0:20 min' depth='1.829 m' />
  <sample time='0:40 min' depth='2.134 m' />
  <sample time='1:00 min' depth='2.743 m' />
  <sample time='1:20 min' depth='3.353 m' />
  <sample time='1:40 min' depth='3.658 m' />
  <sample time='2:00 min' depth='4.267 m' />
  <sample time='2:20 min' depth='4.572 m' />
  <sample time='2:40 min' depth='4.572 m' />
 <! --... -->

And now, I can start computing my air consumption.

Computing The Air Consumption

What I know for my calculation:

  • at Ti I was at depth Di, and at Ti+1, I was at Di+1, so I assume that I spent Ti+1 - Ti seconds at (Di+1 + Di)/2 meters. I know this is a very simplistic, but as Ti+1 - Ti is 20s for my computer, so no more that a few meters, that's good enough for my purpose.
  • pressure at depth Dmeters is Pi = abs(Di)/10 + 1atm/bar
  • the initial air volume Vstart of my tank depends of its size Stank and its pressure Ptank. Vstart = PtankxStank (for all the tanks used of course)
  • the same applies for the end-of-dive volume, Vstop. I consumed Vconso = Vstart - Vstop litters of air during the dive.

Now, I need to distribute Vconso over the dive, but paying attention to different dive depths. So, for all Ti and Pi,

  • I compute the "equivalent surface time" Teq.surf = Ti * Pi in minutes, which is "the time required at surface level to breath the same quantity of air than Ti minutes at Pi atm".
  • I sum up all these durations
  • and I compute the air consumption by diving the breathed air volume by this surface-equivalent duration.

For my last dives, this gives:

  • 16l/min (1650l pour 98min.eq.surface) (44min, 20m max, 12m avg, water 14/15*)
  • 14l/min (1650l for 113min.eq.surface) (43min, 34m max, 16m avg)
  • 16l/min (1800l for 111min.eq.surface) (45min, 19m max, 14m avg)
  • 16l/min (1500l for 92min.eq.surface) (40min, 19m max, 13m avg)
  • 29l/min (900l for 30min.eq.surface) (short cave dive, 15min 17m max, 10m avg, cold water 13*)
  • 27l/min (1638l for 59min.eq.surface) (shallow dive, 36min 10m max, 6m avg, water 17* but dive suit too large)
  • 18l/min (1740l for 91min.eq.surface) (diving pool, 36min,19m max, 15m avg)

and I didn't write down enough details for the previous ones.

It's hard to tell if the computation is good enough, the last 4 dives (top of the list), where during the same weekend and the consumption are every homogeneous, but the 2 previous ones are surprising. Maybe the cave dive was a bit stressful, even if I didn't notice it, maybe I didn't write correctly the tank sizes correctly (I also had to breath on 2 independent tanks), and for the dive at 27l/min, my suit was too large, I could feel cold water each time I was breathing, I don't know if that explains the figures twice as high ... or my computations are just wrong !

def get_conso(xml_dive, volume):
    surface_eq_time = 0.0

    def subsurface_time_to_minutes(sub_time):
        mn, sc = [int(ent) for ent in sub_time.split(":")]
            return mn + sc/60

    time, depth = 0.0, 0.0
    for sample in xml_dive.find("divecomputer").findall("sample"):
        new_time, new_depth = [sample.get(entry).split()[0]
                               for entry in ("time", "depth")]

        new_time = subsurface_time_to_minutes(new_time)
        duraction = new_time - time

        new_depth = float(new_depth)
        sample_depth = get_sample_depth(depth, new_depth)

        presure = abs(sample_depth) / 10 + 1 # meters to atm presure

        surface_eq_time += presure * duraction

        time, depth = new_time, new_depth

    return int(volume/surface_eq_time)

Actual function is there: http://git.0x972.info/subsurface2jinja.git/tree/subsurface2conso.py