• Which the release of FS2020 we see an explosition of activity on the forun and of course we are very happy to see this. But having all questions about FS2020 in one forum becomes a bit messy. So therefore we would like to ask you all to use the following guidelines when posting your questions:

    • Tag FS2020 specific questions with the MSFS2020 tag.
    • Questions about making 3D assets can be posted in the 3D asset design forum. Either post them in the subforum of the modelling tool you use or in the general forum if they are general.
    • Questions about aircraft design can be posted in the Aircraft design forum
    • Questions about airport design can be posted in the FS2020 airport design forum. Once airport development tools have been updated for FS2020 you can post tool speciifc questions in the subforums of those tools as well of course.
    • Questions about terrain design can be posted in the FS2020 terrain design forum.
    • Questions about SimConnect can be posted in the SimConnect forum.

    Any other question that is not specific to an aspect of development or tool can be posted in the General chat forum.

    By following these guidelines we make sure that the forums remain easy to read for everybody and also that the right people can find your post to answer it.

FSXA Adding a timer.

Zeiten

Resource contributor
Messages
444
Country
norway
Hi.

Really need help with this one as I never really understood the timer thingy.

What I want is that the engines will fail whenever ITT temperatures is over 906 degrees from over 5 minutes.

Code:
    (A:TURB ENG ITT:1, celsius) 907 > if{ (>K:TOGGLE_ENGINE1_FAILURE) }
    (A:TURB ENG ITT:2, celsius) 907 > if{ (>K:TOGGLE_ENGINE2_FAILURE) }

Where do I add the timer?
Do I put the time into a variable and then set it of when that reaches 5 min?
 
You would put the "timer" in between the overtemp condition and the failure command.
Code:
(A:TURB ENG ITT:1, celsius) 907 >
   if{ timer > 5 min
      if{ (>K:TOGGLE_ENGINE1_FAILURE) }
     }
 
Like this?

Code:
(A:TURB ENG ITT:1, celsius) 907 > if{ (E:ABSOLUTE TIME, seconds) 10 > if{ (>K:TOGGLE_ENGINE1_FAILURE) } }

Because the engine fails as soon as it hits 907
 
This is my timer for a blinker.

(P:Absolute time,seconds) 2 % 1 > !

And here is one that Bill Leaming did that is a 'every 90 seconds' trigger timer.

(P:Absolute time,seconds) 180 % 90 > !
 
Here is a cool one. This is another by Bill Leaming (of course) which runs a boot screen. It also has an 'initializer' system which you might be interested in. For instance, if throttle goes back under ITT parameters, reset timer to zero. Restart when back into the ITT red zone. Just change the counter though to work for 5 min's. Note, its an L:var. (Man, if that doesnt confuse a newbi in gauge making and timers, lol).

Code:
<!-- BOOT SCREEN -->
     <!-- Initialize all variables when power is OFF -->
        <Element>
            <Select>
                <Value>
                    (A:Avionics Master Switch,bool) 0 == if{
                    0 (>L:3308BootScreen,enum)
                    0 (>L:3308BootTime,enum) }
                </Value>
            </Select>
        </Element>
     <!-- Start timer and increment when both battery and avionics are ON -->
        <Element>
            <Select>
                <Value>
                    (A:Avionics Master Switch,bool) 1 ==
                    (A:Electrical Master Battery,bool) 1 ==
                    and
                    if{
                        (L:3308BootTime,enum) ++ (>L:3308BootTime,enum) 1 (>L:3308BootScreen,enum) }
                </Value>
            </Select>
        </Element>
     <!-- Stop timer after 20 seconds -->
        <Element>
            <Select>
                <Value>
                    (L:3308BootTime,enum) 260 >
                    (A:Electrical Master Battery,bool) 1 ==
                    and           
                    if{
                        0 (>L:3308BootScreen,enum) }
                </Value>
            </Select>
        </Element>
     <!-- While the "bootscreen" variable is ON and battery is ON, display the bootscreen bitmap -->
        <Element>
            <Visible>(L:3308BootScreen,enum) 1 == (A:Electrical Master Battery,bool) 1 == and</Visible>
             <Position X="0" Y="0"/>
            <Image Name="Garming_G1000_MFD_Background_Full_Boot.bmp" ImageSizes="1000,698" Bright="Yes">
            </Image>
        </Element>
 
Timers can be Blinker or Elapsed Time (cumulative time) variety. There's a good wiki entry that discusses the blink-type timers a little more thoroughly. The Elapsed Time types can be based on cycle counting or P:Absolute Time.

Here's a simple elapsed time example based on gauge update cycle counting. It assumes an update rate of 18 cycles per second and is analogous to the cycle counting approach used in Bill Leaming's script above -- and note this is the logic structure suggested by Bill in his reply#2:
Code:
<Update Frequency="18">
  (A:TURB ENG ITT:1, celsius) 906 &gt;
      if{ (L:Eng1Exceed906CNumCycles, enum) ++ (>L:Eng1Exceed906CNumCycles, enum) }
     els{ (L:Eng1Exceed906CNumCycles, enum) 0.5 - 0 max (>L:Eng1Exceed906CNumCycles, enum) }
  (L:Eng1Exceed906CNumCycles, enum) 18 60 * 5 * &gt;= if{ (>K:TOGGLE_ENGINE1_FAILURE) 0 (>L:Eng1Exceed906CNumCycles, enum) }
</Update>
In this example, the els{ ... 0.5 - 0 max ... } line is inserted to accomodate engine cooling that could occur before the 5 minute failure point is reached. Maybe not quite realistic, but you get the idea.

Hope this adds to both Bill's responses.

Bob
 
Last edited:
I have a question regarding (>K:TOGGLE_ENGINE1_FAILURE).
Once it has been activated and the engines has run down is it necessary to toggle again for the engine to restart,
or will the engine restart normally? One assumes being a toggle that I would have to toggle again in order to restart the engine.
 
My engines run cold and too fast. I either go into overspeed or in a steep climb, to heat the engines, I get to high-atmo and they are cooled down from Ambient temps. :( Would have been nice to have this. arrgh...
 
Here's a simple elapsed time example based on gauge update cycle counting. It assumes an update rate of 18 cycles per second and is analogous to the cycle counting approach used in Bill Leaming's script above -- and note this is the logic structure suggested by Bill in his reply#2:
[

Bob,

Making elapsed time based on gauge update cycle is simple to code and easy to understand. However, you can't use it without taking into account another group of control variables, otherwise it will fail. For example, using it without checking if a sim if paused, or if the current sim rate is different than 1x will lead to errors. Remember that no matter the current FS state, gauge code always run at 18 cycles per second, or at a particular Frequency explicit in <Update>.

I have posted many examples of elapsed timers based on elapsed time managed inside macros, the last one being here:

http://www.fsdeveloper.com/forum/threads/setting-fuel-flow-order.430781/ post #17

A similar group of macros, but with an universal score could be :

Code:
<Macro Name="GetElapsed">
   (P:Absolute time,@2) (L:@1,@2) - abs
</Macro>

<Macro Name="SetElapsed">
   (P:Absolute time,@2) (>L:@1,@2)
</Macro>

And the using:

@SetElapsed(name_of_var,unit)
@GetElapsed(name_of_var,unit)


For example (pseudocode):

Code:
<Update>
   
    (A:TURB ENG ITT:1, celsius) 907 >
    if{  @SetElapsed(MyTimer,minutes)  }
    ...
    ...
    @GetElapsed(MyTimer,minutes) 5 >
    if{ do something }
    ...
</Update>

Both macros can be copied and pasted on every gauge so to have elapsed timers available for the entire code.


Tom
 
Nice upgrade! And I do recall that you have posted examples of such timers in the past, I just didn't remember where. Would be good if that wiki was expanded to include elapsed time timers so there is an easy place to point to for those macros. Blink code is already there.
 
Last edited:
Code:
<Update Frequency="18">
  (A:TURB ENG ITT:1, celsius) 906 &gt;
      if{ (L:Eng1Exceed906CNumCycles, enum) ++ (>L:Eng1Exceed906CNumCycles, enum) }
     els{ (L:Eng1Exceed906CNumCycles, enum) 0.5 - 0 max (>L:Eng1Exceed906CNumCycles, enum) }
  (L:Eng1Exceed906CNumCycles, enum) 18 60 * 5 * &gt;= if{ (>K:TOGGLE_ENGINE1_FAILURE) 0 (>L:Eng1Exceed906CNumCycles, enum) }
</Update>

I did understand that code and it works.
Thanks!

(L:Eng1Exceed906CNumCycles, enum) increments with every gauge cycle.
(L:Eng1Exceed906CNumCycles, enum) 18 60 * 5 * &gt; = 5 min.

Maybe a stupid question, but what is actually a macro?
 
A macro is simple idea - it's a literal substitution of script used out of convenience to save the programmer some time when writing XML and to clean up, sometimes substantially, the appearance of the XML script.

A macro consists of a definition, <Macro Name="Example">expressions, algorithms, etc</Macro>, and the 'shorthand' that invokes the macro, @Example, which is often used repetitively in the gauge - expressions/algorithms, etc, that are used frequently in a gauge lend themselves to the creation of a macro to clean things up.

Bill Leaming wrote a wiki about Using Macros, including examples, and it can be found here. Additional information about passing variables to macros can be found at the bottom of this wiki, again courtesy Bill Leaming.

Use of macros does not affect performance. When a gauge loads, the content of the macros is substituted back into the body of the script. A section of macro definitions is often found at the top of a gauge's script, but macro definitions be located elsewhere as long as the macro definition preceeds use of the @macro call.

My observation is that the professionals and the XML experts make frequent and creative use of macros, like in Tom's example above. Well, that's my understanding of the subject anyway. Bill, Tom, ... help please :)
 
Here's a timer code that could be adapted for a changing engine state. In this case it's for cabin depressurisation and whether the captain has donned his mask in time to avoid hypoxia.
Code:
<!-- Hypoxia settings-->
    <Element>
      <Select>
         <Value>(L:Cabin_Alt_Ind, number) 40000 &gt; (L:Oxy_Charged,bool) 1 == and (L:oxygen mask not pulled,number) 0 == and
if{ 1 (>L:emergency,bool) (P:local time,seconds) 12 + (>L:oxygen mask not pulled,number) }</Value>
      </Select>
   </Element>


<!-- Oxygen Mask donned -->
   <Element>
      <Select>
         <Value>(L:OxyFlow,number) 0 &gt; (L:Don_Mask,number) 1 == and (L:crew_level,number) 2 &gt; and
if{ 2 (>L:Sound_mask,enum) } els{ 0 (>L:Sound_mask,enum) }</Value>
      </Select>
   </Element>



<!-- Oxygen Mask not Pulled in time -->
   <Element>
      <Select>
         <Value>(L:blackout,number) 0 == (L:oxygen mask not pulled,number) 0 &gt; and (L:Don_Mask,number) 0 == and (L:emergency,bool) 1 == and
if{ (L:oxygen mask not pulled,number) (P:local time, seconds) &gt;
if{ 280 (>K:PANEL_ID_OPEN) } els{ 1 (>L:blackout,number) 11025 (>K:PANEL_ID_OPEN) 1 (&gt;K:SOUND_OFF) } }</Value>
      </Select>
   </Element>


<!-- Hypoxia recovery-->
   <Element>
      <Select>
         <Value>(L:blackout,number) 1 == (L:emergency,bool) 1 == and (L:Cabin_Alt_Ind, number) 15000 &lt; and
if{ 0 (>L:blackout,number) 0 (>L:emergency,bool) 1 (>K:SOUND_ON) 11025 (>K:PANEL_ID_CLOSE) }</Value>
      </Select>
   </Element>
 
So you basically put a script into the "macro" then read it over and over again without needing to write the script over and over again.
Something similar to G:vars and <Copy> statement in the modeldef entries?

@vololiberista
When will be flying this amazing machine of yours? :)
 
Bob, you do know that any registered user can create and/or edit the Wiki, yes?

In any case, I've done just that for this nifty bit of genius from Tom:
http://www.fsdeveloper.com/wiki/index.php?title=XML:_Macros_-_Universal_Timer
Yup, I do indeed know that. I have added my own or edited 15 of them (including adding a bit to all of the ADF, Xpndr, radio tuning ones)... I was hoping that I could drop the hint and spread the love so more people would get active there... ;)

Just like when Tom mentioned his posts on timers, above, I knew I had seen them, but I didnt remember where. The wiki section helps solve that for me. I'm preaching to the choir - you've put up more wikis than anyone, I think.

And later, I might even add a little to that one you just did. The cycle counting method should be covered, along with its pros and cons. I like Tom's timer macros too and will use them, but there are way more examples of cycle counters out there than absolute time based timers - sometimes cycle counters are obviously the right choice over absolute time.

Bob
 
Last edited:
And later, I might even add a little to that one you just did. The cycle counting method should be covered, along with its pros and cons. I like Tom's timer macros too and will use them, but there are way more examples of cycle counters out there than absolute time based timers - sometimes cycle counters are obviously the right choice over absolute time.

Bob

Bob,

This is extracted from one of my INS gauges (developed in 2008) :

(L:INS ACPower,bool) ! (L:INSPower:1 On, bool) and
if{ (L:INS:1 DCPower Timer,seconds) 0.055 @SimRate * @Paused ! * - 0 max (>L:INS:1 DCPower Timer,seconds) }


Notice the macros in bold, they are the correction factors I've mentioned in my previous post:

Code:
<Macro Name="SimRate">(P:Simulation Rate,number)</Macro>
<Macro Name="Time">(P:Absolute Time,seconds)</Macro>
<Macro Name="Paused">@Time (L:INSisPaused:1,seconds) - 0 ==</Macro>

A proper way to manage cycle counting method.

Tom
 
Back
Top