1
0
Fork 0
fgdata/Aircraft/Generic/Oxygen/oxygen.nas
Vivian Meazza 02f60e0794 Add open-circuit oxygen system.
Signed-off-by: Vivian Meazza <vivian.meazza@lineone.net>
2010-12-18 09:16:04 +00:00

155 lines
4.9 KiB
Text

###############################################################################
##
## 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