diff --git a/Aircraft/Generic/Oxygen/oxygen.nas b/Aircraft/Generic/Oxygen/oxygen.nas new file mode 100644 index 000000000..b4e0f2333 --- /dev/null +++ b/Aircraft/Generic/Oxygen/oxygen.nas @@ -0,0 +1,155 @@ +############################################################################### +## +## Oxygen system module for FlightGear. +## +## Copyright (C) 2010 Vivian Meazza (vivia.meazza(at)lineone.net) +## This file is licensed under the GPL license v2 or later. +## +############################################################################### + + +# Properties under /consumables/fuel/tank[n]: +# + level_cu_ft - Current free oxygen content. Must be set by user code. +# + capacity_cu_ft - Tank volume +# + selected - boolean indicating tank selection. +# + name ...........- string +# + pressure - OUTPUT ONLY property, do not try to set + +# Properties under /controls/oxygen/ +# + altitude-norm - the selected supply altitude normalized 0 - 100% oxygen +# + flowrate_cu_ft_ps - Max (100%) Oxygen flow rate + +# + flowrate considerations: +# ref http://en.wikipedia.org/wiki/Human_lung +# +# when maximum (100%) oxygen is selected, we wish to deliver enough oxygen to fill +# the pilot's lungs, with slight overpressure. +# +# let the tidal flow volume - that is the amount of gas which flows +# into and out of the lungs on each breath = T ft^3; +# and the number of breaths per minute at rest= N min^-1; +# but we need to consider a pilot under stress factor = 1.5 +# +# so flowrate (ft^3.sec^-1) = (T*1.5*N)/60 +# +# substituting the values from the reference +# +# flowrate = 0.01765 * 1.5 * 20 / 60 = 0.008828 +# +# rounding up to provide overpressure +# +# flowrate = 0.01 (ft^3.sec^-1) + + +#========================= Initialize =============================== +var MAXTANKS = 20; +var INHG2PSI = 0.491154077497; + +var initialize = func { + + print( "Initializing Oxygen System ..." ); + + props.globals.initNode("/systems/oxygen/serviceable", 1, "BOOL"); + props.globals.initNode("/sim/freeze/oxygen", 0, "BOOL"); + props.globals.initNode("/controls/oxygen/altitude-norm", 0.0, "DOUBLE"); + props.globals.initNode("/controls/oxygen/flowrate-cu-ft-ps", 0.01, "DOUBLE"); + + for (var i = 0; i < MAXTANKS; i += 1){ + props.globals.initNode("/consumables/oxygen/tank["~ i ~ "]/capacity-cu-ft", 0.01, "DOUBLE"); + props.globals.initNode("/consumables/oxygen/tank["~ i ~ "]/level-cu-ft", 0, "DOUBLE"); + props.globals.initNode("/consumables/oxygen/tank["~ i ~ "]/selected", 0, "BOOL"); + props.globals.initNode("/consumables/oxygen/tank["~ i ~ "]/pressure-psi", 50, "DOUBLE"); + } + + oxygen(); + +} #end init + +#========================= Oxygen System ============================ +var oxygen = func { + + var freeze = getprop("/sim/freeze/oxygen"); + var serviceable =getprop("/systems/oxygen/serviceable"); + + if(freeze or !serviceable) { return; } + + var dt = getprop("sim/time/delta-sec"); + var oxygen_alt = getprop("controls/oxygen/altitude-norm"); + var flowrate_cu_ft_ps = getprop("controls/oxygen/flowrate-cu-ft-ps"); + var Pa = getprop("environment/pressure-inhg") * INHG2PSI; + + var flow_cu_ft = flowrate_cu_ft_ps * oxygen_alt * dt; + + var contents = 0; + var cap = 0; + var availableTanks = []; + var selected = 0; + var pressure = 2000; + +# Build a list of available tanks. An available tank is both selected, has +# oxygen remaining.and pressure < ambient. + var AllTanks = props.globals.getNode("consumables/oxygen").getChildren("tank"); + + foreach( var t; AllTanks) { + cap = t.getNode("capacity-cu-ft", 1).getValue(); + contents = t.getNode("level-cu-ft", 1).getValue(); + selected = t.getNode("selected", 1).getBoolValue(); + pressure = t.getNode("pressure-psi", 1).getValue(); + + if(cap != nil and cap > 0.01 ) { +# print ("Pressure ", pressure, " " , Pa); + + if(selected and pressure > Pa) { + append(availableTanks, t); + } + + } + + } + +# print("flow_cu_ft ", flow_cu_ft," " ,size(availableTanks)); + +# Subtract flow_cu_ft from tanks, set auxilliary properties. Set out-of-gas +# when all tanks are empty. + var outOfGas = 0; + + if(size(availableTanks) == 0) { + outOfGas = 1; + } else { + flowPerTank = flow_cu_ft / size(availableTanks); + foreach( var t; availableTanks ) { + cu_ft = t.getNode("level-cu-ft").getValue(); + cu_ft -= flowPerTank; + cap = t.getNode("capacity-cu-ft", 1).getValue(); + + if(cu_ft < 0) { cu_ft = 0;} + +# print ("pressure ", calcPressure(cu_ft, cap)); + + t.getNode("level-cu-ft").setDoubleValue(cu_ft); + t.getNode("pressure-psi").setDoubleValue(calcPressure(cu_ft, cap)); + } + } + + settimer(oxygen, 0.3); + +} #end oxygen + +# We apply Boyle's Law to derive the pressure in the tank fom the capacity of the +# tank and the contents. We ignore the effects of temperature. + +var calcPressure = func (cu_ft, cap){ + var Vc = cap; + var Va = cu_ft; + var Pa = 14.7; + +# print (Vc, " ", Va, " ", Pa); + + Pc = (Pa * Va)/Vc; + return Pc; +} #end calcPressure + +setlistener("sim/signals/fdm-initialized", initialize); + +# end +