• 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.

I guess we are officially off topic now. In my piston a/c, I threw a (>K:TOGGLE_ENGINE1_FAILURE) to kill the engine and had to do it again before I could restart the engine. Toggle.

Bill, you mention adding blinkie lights to let you know whats happening while you are debugging your gauge. Does that mean you do not make use of any of these: Robbie's Blackbox, Tom's XMLTools, or Doug's xml vars? Can't imagine building gauges without one of these tools to help debug logic. Furthermore, using the SIMVARS class in XMLTools, I believe you might be able to set (A:TURB ENG ITT:1, celsius) above the critical temp for testing purposes instead of consuming the time to fly the sim. Tom will know for sure. Maybe setting that A:Var is possible through simconnect too, for those that know how to use simconnect, which I don't.

Bob
 
Last edited:
Glad you finally made it work :coffee:

Now I leave you another issue to take into account:

For the engine to fail, a reaching overtemp condition is necessary alone to trigger the failure after 15 seconds, or the overtemp condition must remain for 15 seconds to make it fail?

Current code depicts the first situation.

Tom

PS: maybe would be better to open a new thread if this has to continue; I think we would be a little off topic here.
Tom,
The 15 seconds was just to see if everything worked. The engine limitations schedule is quite complex so an actual failure is less likely to happen. I'm also thinking of incorporating a random code both for a potential failure and in the reset algorithm which will determine whether the engine can be restarted in the air or after landing.
 
Yes, with Tom's code there is the problem of not resetting. In that my example was for too high an N2 percentage for a period of time. That works fine, but if the throttle is cut back the engine still shuts down which it shouldn't even though variables have been reset.
Code:
<!-- Engine Limitations Exceeded -->

<Element>
      <Select>
         <Value>
             (A:Turb eng1 N2, percent) 104.9 &gt; (L:eng1_stop,number) 0 == and
              if{ @SetElapsed(time1,seconds) 1 (>L:eng1_stop,number) }
          </Value>
      </Select>
</Element>

<Element>
      <Select>
         <Value>
            @GetElapsed(time1,seconds) 15 > (L:eng1_stop,number) 1 == and
            if{ (>K:TOGGLE_ENGINE1_FAILURE) 2 (>L:eng1_stop,number) }
         </Value>
      </Select>
</Element>

<Element>
      <Select>
         <Value>
             (A:Turb eng1 N2, percent) 70 &lt; (L:eng1_stop,number) 2 == and
              if{ 0 (>L:eng1_stop,number) }
          </Value>
      </Select>
</Element>

For example if the engine is at 105% for just a few seconds (not 15 as in the above test) it still shuts down. It seems that once the macro is envoked that's it! My guess is that it sits in -
Code:
<Element>
      <Select>
         <Value>
            @GetElapsed(time1,seconds) 15 > (L:eng1_stop,number) 1 == and
            if{ (>K:TOGGLE_ENGINE1_FAILURE) 2 (>L:eng1_stop,number) }
         </Value>
      </Select>
</Element>

Until the 15 seconds are up. so it never gets to see the reset.
 
Last edited:
Whether this is the right way or not but "a" solution in my case is to replace-
Code:
<Element>
      <Select>
         <Value>
            @GetElapsed(time1,seconds) 15 > (L:eng1_stop,number) 1 == and
            if{ (>K:TOGGLE_ENGINE1_FAILURE) 2 (>L:eng1_stop,number) }
         </Value>
      </Select>
</Element>

with -------

Code:
Element>
      <Select>
         <Value>
            @GetElapsed(time1,seconds) 15 > (L:eng1_stop,number) 1 == and
            if{ (A:Turb eng1 N2, percent) 104.9 &gt; if{ (>K:TOGGLE_ENGINE1_FAILURE) 2 (>L:eng1_stop,number) }  els{ 0 (>L:eng1_stop,number) } }
         </Value>
      </Select>
</Element>

This seems to break out of the timer loop if the overspeed is less than 15. If there's a better way?
 
This seems to break out of the timer loop if the overspeed is less than 15. If there's a better way?

This could be a similar approach, all in a single <Element>:

Code:
Element>
      <Select>
         <Value>
             (A:Turb eng1 N2, percent) 104.9 >
             if{
                  (L:eng1_stop,number) @GetElapsed(time1,seconds) + (>L:eng1_stop,number)
                  (L:eng1_stop,number) 15 >
                  if{ (>K:TOGGLE_ENGINE1_FAILURE)   0 (>L:eng1_stop,number) }
                }
            els{ 0 (>L:eng1_stop,number) }
            @SetElapsed(time1,seconds)
         </Value>
      </Select>
</Element>

In this code the condition resets as long as Turb eng1 N2 falls and/or remains behind 104.9 %.

Similar logic could be used in case there is no linear reset but a deaccumulation of time when Turb eng1 N2 leaves the overspeed, like in Bob's previous example.

Tom

EDIT: an optimized version:

Code:
....
         <Value>
              (L:eng1_stop,number) @GetElapsed(time1,seconds) + 
             (A:Turb eng1 N2, percent) 104.9 > *
             d (>L:eng1_stop,number) 15 >
             if{ (>K:TOGGLE_ENGINE1_FAILURE) 0 (>L:eng1_stop,number) }
            @SetElapsed(time1,seconds)
         </Value>
.....
 
Last edited:
This could be a similar approach, all in a single <Element>:

Code:
Element>
      <Select>
         <Value>
             (A:Turb eng1 N2, percent) 104.9 >
             if{
                  (L:eng1_stop,number) @GetElapsed(time1,seconds) + (>L:eng1_stop,number)
                  (L:eng1_stop,number) 15 >
                  if{ (>K:TOGGLE_ENGINE1_FAILURE)   0 (>L:eng1_stop,number) }
                }
            els{ 0 (>L:eng1_stop,number) }
            @SetElapsed(time1,seconds)
         </Value>
      </Select>
</Element>

In this code the condition resets as long as Turb eng1 N2 falls and/or remains behind 104.9 %.

Similar logic could be used in case there is no linear reset but a deaccumulation of time when Turb eng1 N2 leaves the overspeed, like in Bob's previous example.

Tom

EDIT: an optimized version:

Code:
....
         <Value>
              (L:eng1_stop,number) @GetElapsed(time1,seconds) +
             (A:Turb eng1 N2, percent) 104.9 > *
             d (>L:eng1_stop,number) 15 >
             if{ (>K:TOGGLE_ENGINE1_FAILURE) 0 (>L:eng1_stop,number) }
            @SetElapsed(time1,seconds)
         </Value>
.....

Thanks for that Tom. :)
 
For the RR Conway engines the maximum allowed n2 is 105% for 20 seconds. I have extended that to 45 seconds as a measure of reliability plus I have added a random factor to further increase that. The random factor has also been added to the restart in case of failure in flight to determine if the engine(s) can be restarted in the air. I'll have to add a bit more so that in that case they can be restarted once on the ground. At the moment the random factors for each engine are almost the same. I'll probably change that a little to differentiate each engine performance. Thanks again to Tom for the code.

Code:
<!-- Engine Limitations Exceeded -->

<!-- Engine One -->
<Element>
      <Select>
        <Value>
              (L:RandomNumber,number) 0.115 &lt; if{ (L:eng1_stop,number) @GetElapsed(time1,seconds) +
             (A:Turb eng1 N2, percent) 104.9 > *
             d (>L:eng1_stop,number) 45 >
             if{ (>K:TOGGLE_ENGINE1_FAILURE) 0 (>L:eng1_stop,number) 1 (>L:restart1,bool) }
            @SetElapsed(time1,seconds) }
         </Value>
      </Select>
</Element>


<Element>
      <Select>
         <Value>
             (L:RandomNumber,number) 0.100 &lt; if{ (A:Turb eng1 N2, percent) 70 &lt; (L:restart1,bool) 1 == and
              if{ 0 (>L:eng1_stop,number) 0 (>L:restart1,bool) (>K:TOGGLE_ENGINE1_FAILURE) } }
          </Value>
      </Select>
</Element>

<!-- Engine Two -->
<Element>
      <Select>
        <Value>
              (L:RandomNumber,number) 0.111 &lt; if{ (L:eng2_stop,number) @GetElapsed(time2,seconds) +
             (A:Turb eng2 N2, percent) 104.9 > *
             d (>L:eng2_stop,number) 45 >
             if{ (>K:TOGGLE_ENGINE2_FAILURE) 0 (>L:eng2_stop,number) 1 (>L:restart2,bool) }
            @SetElapsed(time2,seconds) }
         </Value>
      </Select>
</Element>


<Element>
      <Select>
         <Value>
             (L:RandomNumber,number) 0.99 &lt; if{ (A:Turb eng2 N2, percent) 70 &lt; (L:restart2,bool) 1 == and
              if{ 0 (>L:eng2_stop,number) 0 (>L:restart2,bool) (>K:TOGGLE_ENGINE2_FAILURE) } }
          </Value>
      </Select>
</Element>


<!-- Engine Three -->
<Element>
      <Select>
        <Value>
              (L:RandomNumber,number) 0.101 &lt; if{ (L:eng3_stop,number) @GetElapsed(time3,seconds) +
             (A:Turb eng3 N2, percent) 104.9 > *
             d (>L:eng3_stop,number) 45 >
             if{ (>K:TOGGLE_ENGINE3_FAILURE) 0 (>L:eng3_stop,number) 1 (>L:restart3,bool) }
            @SetElapsed(time3,seconds) }
         </Value>
      </Select>
</Element>


<Element>
      <Select>
         <Value>
             (L:RandomNumber,number) 0.100 &lt; if{ (A:Turb eng3 N2, percent) 70 &lt; (L:restart3,bool) 1 == and
              if{ 0 (>L:eng3_stop,number) 0 (>L:restart3,bool) (>K:TOGGLE_ENGINE3_FAILURE) } }
          </Value>
      </Select>
</Element>

<!-- Engine Four -->
<Element>
      <Select>
        <Value>
              (L:RandomNumber,number) 0.125 &lt; if{ (L:eng4_stop,number) @GetElapsed(time4,seconds) +
             (A:Turb eng4 N2, percent) 104.9 > *
             d (>L:eng4_stop,number) 45 >
             if{ (>K:TOGGLE_ENGINE4_FAILURE) 0 (>L:eng4_stop,number) 1 (>L:restart4,bool) }
            @SetElapsed(time4,seconds) }
         </Value>
      </Select>
</Element>


<Element>
      <Select>
         <Value>
             (L:RandomNumber,number) 0.101 &lt; if{ (A:Turb eng4 N2, percent) 70 &lt; (L:restart4,bool) 1 == and
              if{ 0 (>L:eng4_stop,number) 0 (>L:restart4,bool) (>K:TOGGLE_ENGINE4_FAILURE) } }
          </Value>
      </Select>
</Element>
 
Last edited:
Nice....! I must check this out!

Volo, I was going to say, mine was doing that also, no matter what I did. Timer wasnt letting go. Thanks Tom for adjusting.
 
I guess we are officially off topic now. In my piston a/c, I threw a (>K:TOGGLE_ENGINE1_FAILURE) to kill the engine and had to do it again before I could restart the engine. Toggle.

Bill, you mention adding blinkie lights to let you know whats happening while you are debugging your gauge. Does that mean you do not make use of any of these: Robbie's Blackbox, Tom's XMLTools, or Doug's xml vars? Can't imagine building gauges without one of these tools to help debug logic. Furthermore, using the SIMVARS class in XMLTools, I believe you might be able to set (A:TURB ENG ITT:1, celsius) above the critical temp for testing purposes instead of consuming the time to fly the sim. Tom will know for sure. Maybe setting that A:Var is possible through simconnect too, for those that know how to use simconnect, which I don't.

Bob


I know.. I really should hook one of those up and check things. Time to have a look. I did try to hook up BlackBox and couldnt get it to work. Might be because I am in P3D. I'll give Dougs a try and see if I can get that going on the jet.


Bill
 
Nice....! I must check this out!

Volo, I was going to say, mine was doing that also, no matter what I did. Timer wasnt letting go. Thanks Tom for adjusting.
Yes, it was clearly looping without an exit. Tom's "final solution" is much more elegant than my duffers try!
 
Vololiberista, I just tried your code with the engine temp variation, reduced to 15 seconds, and it didnt work. Did I do something wrong?

Code,

Code:
<!-- Engine One -->
<Element>
      <Select>
        <Value>
              (L:RandomNumber,number) 0.115 &lt; if{ (L:eng1_stop,number) @GetElapsed(time1,seconds) +
             (A:TURB ENG ITT:1, celsius) 400 > *
             d (>L:eng1_stop,number) 15 >  
             if{ (>K:TOGGLE_ENGINE1_FAILURE) 0 (>L:eng1_stop,number) 1 (>L:restart1,bool) }
            @SetElapsed(time1,seconds) }
         </Value>
      </Select>
</Element>

<Element>
      <Select>
         <Value>
             (L:RandomNumber,number) 0.100 &lt; if{ (A:TURB ENG ITT:1, celsius) 390 &lt; (L:restart1,bool) 1 == and
              if{ 0 (>L:eng1_stop,number) 0 (>L:restart1,bool) (>K:TOGGLE_ENGINE1_FAILURE) } }
          </Value>
      </Select>
</Element>

* This would mean the seconds that it takes to overheat? ................ d (>L:eng1_stop,number) 15 > (15 being the seconds)


EDIT: I tried this code again, stock but changed high RPM limit to 95% (as my engines cannot do over 100) and again this didnt work. :(

So now that you are getting proficient at timers and triggering events, can you translate this for us back here in this dimension? Can you disect for instance, and explain in detail, how this cool code works?
 
Last edited:
You know what would be a great topper for this, adding a smoke effect to the engine... :D

EDIT: I ended up spending the afternoon trying to attach a couple of smoke effects to the code structure, but oddly, it will not work!? I then created a sort of initializer that turns of (for each engine) when it runs the fail command (for each engine, separately) and then created code blocks for smoke commands that run when the initializers activate. That didnt work either, amazingly.

Cant figure that out.... But, hopefully that will happen.

And tonight, it came to me... What if we could cause (with Timers, main subject here) to have the engines 'start to fail' (lowered RPM via turbine vibration commands), and smoke starts happening, 'and then' the engines shut down....

and also stagger the engine maximums so that perhaps only one dies instead of both. Perhaps one was made on a Friday evening and the other was made on Wednesday morning. ;)


Code:
<Update Frequency="18">


  (A:TURB ENG ITT:1, celsius) 414 &gt;
      if{ (L:Eng1Exceed906CNumCycles, enum) ++ (>L:Eng1Exceed906CNumCycles, enum) }
     els{ (L:Eng1Exceed906CNumCycles, enum) 0.5 - 0 max (>L:Eng1Exceed906CNumCycles, enum) }
  (L:Eng1Exceed906CNumCycles, enum) 18 60 * 15 * &gt;=
     if{ (>K:TOGGLE_ENGINE1_FAILURE)
       0 (>L:Eng1Exceed906CNumCycles, enum)
       1 (>L:LIGHT THE SMOKE FOR ENGINE ONE,bool) }
    
  (A:TURB ENG ITT:2, celsius) 410 &gt;
      if{ (L:Eng2Exceed906CNumCycles, enum) ++ (>L:Eng2Exceed906CNumCycles, enum) }
     els{ (L:Eng2Exceed906CNumCycles, enum) 0.5 - 0 max (>L:Eng2Exceed906CNumCycles, enum) }
  (L:Eng2Exceed906CNumCycles, enum) 18 60 * 15 * &gt;=
     if{ (>K:TOGGLE_ENGINE2_FAILURE)
       0 (>L:Eng2Exceed906CNumCycles, enum)
       1 (>L:LIGHT THE SMOKE FOR ENGINE TWO,bool) }



  (L:LIGHT THE SMOKE FOR ENGINE ONE,bool) 1 ==
      if{ (A:SMOKE ENABLE:14,bool) ! if{ 14 (&gt;K:SMOKE_ON) 0 (>L:LIGHT THE SMOKE FOR ENGINE ONE,bool) } }
     els{ (A:SMOKE ENABLE:14,bool) if{ 14 (&gt;K:SMOKE_OFF) } }

  (L:LIGHT THE SMOKE FOR ENGINE TWO,bool) 1 ==
      if{ (A:SMOKE ENABLE:15,bool) ! if{ 15 (&gt;K:SMOKE_ON) 0 (>L:LIGHT THE SMOKE FOR ENGINE TWO,bool) } }
     els{ (A:SMOKE ENABLE:15,bool) if{ 15 (&gt;K:SMOKE_OFF) } }

</Update>
 
Last edited:
Well, we can write off 'smoke' with the engine failure (on this timer subject), lol... If your engine is off (engine failure timer code) then smoke is inop. :( Took me a few (many) hours to find that out. sigh......

EDIT: Lights! You can add the smoke effect into the Lights section. Use Logo lights circuit (for instance), then activate that when the engine fails. Just linked it in, works perfect.
 
Last edited:
Vololiberista,

I was experimenting with your failure code (timers). How on Earth did you get that to work?? One flight, it crashes at about 20 min's, another at nearly an hour. How do you scatter the times? I cannot see where you get that from in your code...

EDIT: Oddly, now I cannot seem to go to full throttle when on the ground.
 
Last edited:
To any FSX users wondering why Tom's timers won't work:

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

Syntax!
 
Tom's macros in response #9 are written using FS9 xml syntax which is compatible with FSX although you can't mix schemas in the same gauge. I guess a lot of people prefer FS9 schema even when writing for FSX because it's easier to read ... as you eloquently pointed out in the Flaps Movement thread :p

Actually, I am pretty sure you know all this and may be only pointing out how they look in FSX schema ...

Bob
 
Tom's macros in response #9 are written using FS9 xml syntax which is compatible with FSX although you can't mix schemas in the same gauge. I guess a lot of people prefer FS9 schema even when writing for FSX because it's easier to read ... as you eloquently pointed out in the Flaps Movement thread :p

Actually, I am pretty sure you know all this and may be only pointing out how they look in FSX schema ...

I was honestly a bit angry that a thread marked with "FSXA" contains FS9 gauge syntax without ever so much as a hint.
But it shows that I'm dumb enough to use every code that's posted without checking the syntax version first (or whether it's pseudo code or not).




And speaking of me being dumb...my timer code suffers from premature completion. There's an ID10T error somewhere, but I just can't find it.

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

<Update>
<Script>
(L:MP_DEICE_Pitot_R_Switch, Number) 1 &lt;
        (L:MP_DEICE_Pitot_L_Switch, Number) 1 &lt;
        or
  if{ @SetElapsed(Time1,seconds) }

@GetElapsed(Time1,seconds) 30 >
  if{ 20 (&gt;L:SAS ICING, number)  }
</Script>
</Update>


- Edit:

Might want to lock the start time...

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

<Update>
<Script>
(L:MP_DEICE_Pitot_R_Switch, Number) 1 &lt;
(L:MP_DEICE_Pitot_L_Switch, Number) 1 &lt;
or
(L:TIME LOCK, bool) !
and
if{ @SetElapsed(Time1,seconds) 1 (&gt;L:TIME LOCK, bool) }

@GetElapsed(Time1,seconds) 30 >
  if{ 20 (&gt;L:SAS ICING, number)  }

(L:MP_DEICE_Pitot_R_Switch, Number) 1 &gt;
(L:MP_DEICE_Pitot_L_Switch, Number) 1 &gt;
or
if{ 0 (&gt;L:TIME LOCK, bool) }
</Script>
</Update>
 
Last edited:
I was honestly a bit angry that a thread marked with "FSXA" contains FS9 gauge syntax without ever so much as a hint.

I think you were right to be angry. My fault, I should have posted both versions. It's that FSX-schema code is so useless to me that I forget other people are actually working with it.

- Edit:

Might want to lock the start time...

Now you got it :)

Tom
 
Back
Top