# A3XX Icing System # Jonathan Redpath (legoboyvdlp) # Copyright (c) 2020 Josh Davidson (Octal450) ### Ice sensitive components definition. var Iceable = { new: func(node) { var m = { parents: [Iceable] }; m.ice_inches = node.getNode("ice-inches", 1); m.sensitivity = node.getNode("sensitivity", 1); var deice_prop = node.getValue("salvage-control"); m.deice = deice_prop ? props.globals.getNode(deice_prop, 1) : nil; var output_prop = node.getValue("output-property"); m.output = output_prop ? props.globals.getNode(output_prop, 1): nil; return m; }, update: func(factor, melt) { var icing = me.ice_inches.getValue(); if(me.deice != nil and me.deice.getBoolValue()) { icing += melt; } else { icing += factor * me.sensitivity.getValue(); } if(icing < 0) icing = 0; me.ice_inches.setValue(icing); if(me.output != nil) me.output.setValue(icing); }, }; ### Icing parameters computation. # Environmental parameters of the icing model. var environment = { dewpoint: props.globals.getNode("environment/dewpoint-degc"), temperature: props.globals.getNode("environment/temperature-degc"), visibility: props.globals.getNode("environment/effective-visibility-m"), visibLclWx: props.globals.getNode("environment/visibility-m"), }; var effects = { frost_inch: props.globals.getNode("environment/aircraft-effects/frost-inch", 1), frost_norm: props.globals.getNode("environment/aircraft-effects/frost-level"), }; # Icing factor computation. var maxSpread = 0; var severity_factor_table = [ -0.00000166, 0.00000277, 0.00000277, 0.00000554, 0.00001108, 0.00002216, ]; var melt_factor = -0.00005; var icing_factor = func() { var temperature = environment.temperature.getValue(); var dewpoint = environment.dewpoint.getValue(); var visibility = environment.visibility.getValue(); var visibLclWx = environment.visibLclWx.getValue(); # Do we create ice? var spread = temperature - dewpoint; # freezing fog or low temp and below dp or in advanced wx cloud var icingCond = ((spread < maxSpread or visibility < 1000 or visibLclWx < 5000) and temperature < 0); # todo: turn this into a table or something var severity = 0; if (icingCond) { if (temperature >= -2) { severity = 1; } else if (temperature >= -12) { severity = 3; } else if (temperature >= -30) { severity = 5; } else if (temperature >= -40) { severity = 3; } else if (temperature >= -99) { severity = 1; } } return severity_factor_table[severity]; } var speed = 0; var pause = 0; var windowprobe = 0; var wingBtn = 0; var wingFault = 0; var wingAnti = 0; var PSI = 0; var wowl = 0; var wowr = 0; var PitotIcing = 0; var PitotFailed = 0; var lengBtn = 0; var lengFault = 0; var rengBtn = 0; var rengFault = 0; var lengAnti = 0; var rengAnti = 0; var WingHasBeenTurnedOff = 0; var GroundModeFinished = 0; var windowprb = 0; var stateL = 0; var stateR = 0; var iceables = []; var icingInit = func { setprop("controls/switches/windowprobeheat", 0); setprop("controls/switches/wing", 0); setprop("controls/switches/wingfault", 0); setprop("controls/switches/leng", 0); setprop("controls/switches/lengfault", 0); setprop("controls/switches/reng", 0); setprop("controls/switches/rengfault", 0); setprop("controls/deice/wing", 0); setprop("controls/deice/lengine", 0); setprop("controls/deice/rengine", 0); setprop("controls/deice/windowprobeheat", 0); setprop("systems/pitot/icing", 0.0); setprop("systems/pitot/failed", 1); setprop("controls/deice/WingHasBeenTurnedOff", 0); setprop("controls/deice/GroundModeFinished", 0); iceables = props.globals.getNode("sim/model/icing", 1).getChildren("iceable"); forindex(var i; iceables) { iceables[i] = Iceable.new(iceables[i]); } icing_timer.start(); } var icingModel = func { speed = getprop("velocities/airspeed-kt"); pause = getprop("sim/freeze/master"); windowprobe = getprop("controls/deice/windowprobeheat"); wingBtn = getprop("controls/switches/wing"); wingFault = getprop("controls/switches/wingfault"); wingAnti = getprop("controls/deice/wing"); PSI = getprop("systems/pneumatic/total-psi"); wowl = getprop("gear/gear[1]/wow"); wowr = getprop("gear/gear[2]/wow"); PitotIcing = getprop("systems/pitot/icing"); PitotFailed = getprop("systems/pitot/failed"); lengBtn = getprop("controls/switches/leng"); lengFault = getprop("controls/switches/lengfault"); rengBtn = getprop("controls/switches/reng"); rengFault = getprop("controls/switches/rengfault"); lengAnti = getprop("controls/deice/lengine"); rengAnti = getprop("controls/deice/rengine"); WingHasBeenTurnedOff = getprop("controls/deice/WingHasBeenTurnedOff"); GroundModeFinished = getprop("controls/deice/GroundModeFinished"); var factor = icing_factor(); foreach(iceable; iceables) { iceable.update(factor, melt_factor); } effects.frost_norm.setDoubleValue(effects.frost_inch.getValue() * 50); if (WingHasBeenTurnedOff and !wowl and !wowr and GroundModeFinished) { setprop("controls/deice/wing", 1); setprop("controls/switches/WingHasBeenTurnedOff", 0); } # If we have low pressure we have a fault if (PSI < 10) { setprop("controls/switches/wingfault", 1); setprop("controls/deice/wing", 0); } if (PSI > 10 and wingFault) { setprop("controls/switches/wingfault", 0); if (wingBtn) { setprop("controls/deice/wing", 1); } } if (PitotIcing > 0.03) { if (!PitotFailed) { setprop("systems/pitot/failed", 1); } } else if (PitotIcing < 0.03) { if (PitotFailed) { setprop("systems/pitot/failed", 0); } } # if ((getprop("systems/electrical/bus/dc-1") == 0 or getprop("systems/electrical/bus/dc-2") == 0) and getprop("fdm/jsbsim/position/wow") == 0) { # setprop("controls/switches/leng", 1); # setprop("controls/switches/reng", 1); # } #if (getprop("systems/electrical/bus/dc-ess-shed") == 0) { # setprop("controls/switches/wing", 0); #} } ################# # LEng Anti-Ice # ################# setlistener("/controls/switches/leng", func { if (getprop("controls/switches/leng") == 1 and getprop("engines/engine[0]/state") == 3) { setprop("controls/switches/lengfault", 1); settimer(func() { setprop("controls/switches/lengfault", 0); setprop("controls/deice/lengine", 1); }, 0.5); } else if (getprop("controls/switches/leng") == 0) { setprop("controls/switches/lengfault", 1); settimer(func() { setprop("controls/switches/lengfault", 0); setprop("controls/deice/lengine", 0); }, 0.5); } }); setlistener("/engines/engine[0]/state", func { if (getprop("engines/engine[0]/state") != 3) { setprop("controls/switches/leng", 0); } }); ################# # REng Anti-Ice # ################# setlistener("/controls/switches/reng", func { if (getprop("controls/switches/reng") == 1 and getprop("engines/engine[1]/state") == 3) { setprop("controls/switches/rengfault", 1); settimer(func() { setprop("controls/switches/rengfault", 0); setprop("controls/deice/rengine", 1); }, 0.5); } else if (getprop("controls/switches/reng") == 0) { setprop("controls/switches/rengfault", 1); settimer(func() { setprop("controls/switches/rengfault", 0); setprop("controls/deice/rengine", 0); }, 0.5); } }); setlistener("/engines/engine[1]/state", func { if (getprop("engines/engine[1]/state") != 3) { setprop("controls/switches/reng", 0); } }); ################## # Probe Anti-Ice # ################## setlistener("/controls/switches/windowprobeheat", func { windowprb = getprop("controls/switches/windowprobeheat"); if (windowprb == 0.5) { # if in auto wowl = getprop("gear/gear[1]/wow"); wowr = getprop("gear/gear[2]/wow"); stateL = getprop("engines/engine[0]/state"); stateR = getprop("engines/engine[1]/state"); if (!wowl or !wowr) { setprop("controls/deice/windowprobeheat", 1); } else if (stateL == 3 or stateR == 3) { setprop("controls/deice/windowprobeheat", 1); } } else if (windowprb == 1) { # if in ON setprop("controls/deice/windowprobeheat", 1); } else { setprop("controls/deice/windowprobeheat", 0); } }); ################# # Wing Anti-Ice # ################# # Switching on the wing anti-ice setlistener("/controls/switches/wing", func { wowl = getprop("gear/gear[1]/wow"); wowr = getprop("gear/gear[2]/wow"); wingBtn = getprop("controls/switches/wing"); if (wowl and wowr and wingBtn) { setprop("controls/switches/wingfault", 1); settimer(func() { setprop("controls/switches/wingfault", 0); setprop("controls/deice/wing", 1); }, 0.5); settimer(func() { setprop("controls/deice/WingHasBeenTurnedOff", 1); setprop("controls/deice/wing", 0); }, 30.5); settimer(func() { setprop("controls/deice/GroundModeFinished", 1); }, 31); } else if (wingBtn and !wowl and !wowr) { # In the air setprop("controls/switches/wingfault", 1); settimer(func() { setprop("controls/switches/wingfault", 0); setprop("controls/deice/wing", 1); }, 0.5); } else if (!wingBtn) { setprop("controls/switches/wingfault", 1); settimer(func() { setprop("controls/switches/wingfault", 0); setprop("controls/deice/wing", 0); }, 0.5); } }); ################### # Update Function # ################### var update_Icing = func { icingModel(); } var icing_timer = maketimer(0.2, update_Icing); icing_timer.simulatedTime = 1;