FSX:SE Direct engine parameter manipulation through simConnect

#1
Hello again,

I am currently working on the part of my dll file that will set the engine parameters for my aircraft. I set up a structure to hold all relevant engine variables that have the "settable" tag. E.g. "RECIP ENG MANIFOLD PRESSURE:1", "GENERAL ENG OIL PRESSURE:1", etc. etc. In my simConnect module, I do the usual SimConnect_AddToDataDefinition for all those variables in the structure. To test the functionality I implemented this:
Code:
    if (general_eng_combustion == true) {
        map = 206842.0;
        hr = SimConnect_SetDataOnSimObject(mySimConnect, DEFINITION_ENGINE, SIMCONNECT_OBJECT_ID_USER, 0, 0, sizeof(set_engine), &set_engine);
    }
which is supposed to set the manifold pressure to around 30 psi whenever the engine is turned on. However, this doesn't work, the manifold pressure will still be sim-controlled.

Debugging the code I can confirm that both, the "AddToDataDefinition" as well as the "SetDataOnSimObject" functions return S_OK. In the update function that calls the code above, I initialize the rest of the variables of the engine's data structure with the sim's variables.

Does any one have had any experiences modifying the engine parameters directly? Any ideas why my code doesn't perform?
 

ddawson

Resource contributor
#2
Setting data like manifold pressure does not stop the sim from calculating its own value and updating the variable with that value.
Your only hope here is to change values in the .air or aircraft.cfg file so that the engine will behave as you wish. Alternatively, change the throttle and/or mixture inputs.
 

taguilo

Resource contributor
#4
I am currently working on the part of my dll file that will set the engine parameters for my aircraft.
Hi,

Before doing that, have you considered using XMLTools? A header file (.h) is included in the documentation for interfacing with C++ gauges.

Tom
 
#5
Hey Tom,
Thank you for the suggestion but I don't quite understand the relevancy of your tool in regards to my question. I am trying to overwrite the engine parameters using simConnect within my gauge DLL file, in what way would XMLTools be of assistance in this case? Coul you please clarify?
Cheers
Vitus
 

taguilo

Resource contributor
#6
XMLTools contains SIMVARS class which allows reading/writing AVars (A: ) I think exactly what you need.

For example, this function:

SetSIMVar(xT, s44, sTurb_EngE_Corrected_N1.c_str());

is directly updating (A:Turb Eng Corrected N1:n,percent).

I recommend you download the module and read SIMVARS references and examples

Tom
 
#7
Manipulated Sim variable can't do partially, or it will end up with fighting between sim and your dll gauge.
something need to consider is the Avars in SDK is settable ( Y ).
 
#8
Tom, I read through your documentation and you're right: your tool does what I need. But honestly I'm not keen in implementing it into my system, because most of the functions of the tools are already part of my DLL. Are you instead prepared to give me some guidance how to achieve my goal within my own C++ gauge?


Manipulated Sim variable can't do partially, or it will end up with fighting between sim and your dll gauge.
What do you mean with partially? I'm prepared to overwrite all engine parameters, completely bypassing the sim's calculations and I was hoping to stick with the settable A-variables. The alternative would be on the lines of Doug's suggestion: I do my calculations, pass it to custom L-vars and then overwrite the throttle/mixture axis settings. I'd prefer to stick with the first suggestions though.

something need to consider is the Avars in SDK is settable ( Y ).
yep, all the variables in the struct are settable ones. This is the full declaration:
Code:
struct SET_ENGINE {
    bool    general_eng_combustion;
    double    general_eng_exhaust_gas_temperature;
    double    general_eng_oil_pressure;
    double    general_eng_oil_temperature;
    double    general_eng_fuel_pressure;
    double    recip_eng_manifold_pressure;
    double    recip_eng_brake_power;
    double    recip_eng_starter_torque;
    double    recip_eng_cylinder_head_temperature;
    bool    recip_eng_fuel_available;    //there's also general eng fuel available.
    double    recip_eng_fuel_flow;
    double    recip_carburetor_temperature;
    double    recip_mixture_ratio;
    bool    eng_on_fire;
    double    prop_rpm;
};
 

Heretic

Resource contributor
#9
My only experience is based on XMLTools and XML gauges and I found that some variables can't be controlled despite being labeled as "settable" in the SDK.

Try the variables one by one and start at either end of the processing chain in the FDE, i.e. throttle position or EGT/CHT.


Also make sure that you're not running into SimConnect's reload limitation during testing.
https://www.fsdeveloper.com/forum/t...oystick-axis-proper-usage.441458/#post-785200 (post #3 or #4 onward)
 

taguilo

Resource contributor
#10
Tom, I read through your documentation and you're right: your tool does what I need. But honestly I'm not keen in implementing it into my system, because most of the functions of the tools are already part of my DLL. Are you instead prepared to give me some guidance how to achieve my goal within my own C++ gauge?
That sounds fine. What I was trying to say is, unless you need to use Simconnect for other tasks appart from setting AVars, you would probably save some code in your dll if you call SIMVARS class functions for that.
The only point is you would have to deliver XMLTools with your product, but considering most users would have it already installed it wouldn't be an extra addition.

Ok, going back to your question, I would need more than you posted to provide useful help.
However, looking at you code I can say that I don't find a SimConnect_AddToDataDefinition sentence, are you adding this one for each AVar you want to write?
Besides, in SimConnect_SetDataOnSimObject you seem to be passing a structure as a value - &set_engine - and I don't think it will work as each sim object of this type -an Avar -may receive a standard (double, int, etc) or string value, depending on default unit.

Finally, in your structure, I used green color to highlight the Avars I positively know will accept user writing, an red to highlight the ones in which it does not work even being referenced as settable (Y).


struct SET_ENGINE {
bool general_eng_combustion;
double general_eng_exhaust_gas_temperature;
double general_eng_oil_pressure;
double general_eng_oil_temperature;
double general_eng_fuel_pressure;
double recip_eng_manifold_pressure;
double recip_eng_brake_power;
double recip_eng_starter_torque;
double recip_eng_cylinder_head_temperature;
bool recip_eng_fuel_available; //there's also general eng fuel available.
double recip_eng_fuel_flow;
double recip_carburetor_temperature;
double recip_mixture_ratio;
bool eng_on_fire;
double prop_rpm;
};

Hope this helps.

Tom
 
#11
Hi Bjoern, thanks for your hint to look at the simConnect max-client problem. I don't think I fall into this, since I regularly reload the sim (my developer-potato gets too hot otherwise :rolleyes:). Excuse my ignorance, but what would be the order of the processing chain, and why would it be important to stick to it?

Here's my AddToDataDefinition function:
Code:
void C_ENGINE::AddToDataDefinition(HANDLE simConnectHandle, int engine_index) {
    SimConnect_AddToDataDefinition(simConnectHandle, DEFINITION_ENGINE, ("GENERAL ENG COMBUSTION:"+to_string(engine_index)).c_str(), "bool");
    SimConnect_AddToDataDefinition(simConnectHandle, DEFINITION_ENGINE, ("GENERAL ENG EXHAUST GAS TEMPERATURE:" + to_string(engine_index)).c_str(), "celsius");
    SimConnect_AddToDataDefinition(simConnectHandle, DEFINITION_ENGINE, ("GENERAL ENG OIL PRESSURE:" + to_string(engine_index)).c_str(), "pascal");
    SimConnect_AddToDataDefinition(simConnectHandle, DEFINITION_ENGINE, ("GENERAL ENG OIL TEMPERATURE:" + to_string(engine_index)).c_str(), "celsius");
    SimConnect_AddToDataDefinition(simConnectHandle, DEFINITION_ENGINE, ("GENERAL ENG FUEL PRESSURE:" + to_string(engine_index)).c_str(), "pascal");
    SimConnect_AddToDataDefinition(simConnectHandle, DEFINITION_ENGINE, ("RECIP ENG MANIFOLD PRESSURE:" + to_string(engine_index)).c_str(), "pascal");
    SimConnect_AddToDataDefinition(simConnectHandle, DEFINITION_ENGINE, ("RECIP ENG BRAKE POWER:" + to_string(engine_index)).c_str(), "watt");
    SimConnect_AddToDataDefinition(simConnectHandle, DEFINITION_ENGINE, ("RECIP ENG STARTER TORQUE:" + to_string(engine_index)).c_str(), "newton meter");
    SimConnect_AddToDataDefinition(simConnectHandle, DEFINITION_ENGINE, ("RECIP ENG FUEL AVAILABLE:" + to_string(engine_index)).c_str(), "bool");
    SimConnect_AddToDataDefinition(simConnectHandle, DEFINITION_ENGINE, ("RECIP ENG FUEL FLOW:" + to_string(engine_index)).c_str(), "kilogram per second");
    SimConnect_AddToDataDefinition(simConnectHandle, DEFINITION_ENGINE, ("RECIP ENG CARBURETOR TEMPERATURE:" + to_string(engine_index)).c_str(), "celsius");
    SimConnect_AddToDataDefinition(simConnectHandle, DEFINITION_ENGINE, ("RECIP ENG MIXTURE RATIO:" + to_string(engine_index)).c_str(), "ratio");
    SimConnect_AddToDataDefinition(simConnectHandle, DEFINITION_ENGINE, ("ENG ON FIRE:" + to_string(engine_index)).c_str(), "bool");
    SimConnect_AddToDataDefinition(simConnectHandle, DEFINITION_ENGINE, ("PROP RPM:" + to_string(engine_index)).c_str(), "rpm");
}
Ideally, the main variables I'd like to set would be a combination of mixture ratio, manifold pressure, rpm, torque and bhp. Everything else doesn't matter as much.
 
#12
What do you mean with partially? I'm prepared to overwrite all engine parameters, completely bypassing the sim's calculations and I was hoping to stick with the settable A-variables. The alternative would be on the lines of Doug's suggestion: I do my calculations, pass it to custom L-vars and then overwrite the throttle/mixture axis settings. I'd prefer to stick with the first suggestions though.
yes, just do whole things like your suggestion to do overwrite all engine parameter.

Hi Bjoern, thanks for your hint to look at the simConnect max-client problem. I don't think I fall into this, since I regularly reload the sim (my developer-potato gets too hot otherwise :rolleyes:). Excuse my ignorance, but what would be the order of the processing chain, and why would it be important to stick to it?

Here's my AddToDataDefinition function:
Code:
void C_ENGINE::AddToDataDefinition(HANDLE simConnectHandle, int engine_index) {
    SimConnect_AddToDataDefinition(simConnectHandle, DEFINITION_ENGINE, ("GENERAL ENG COMBUSTION:"+to_string(engine_index)).c_str(), "bool");
    SimConnect_AddToDataDefinition(simConnectHandle, DEFINITION_ENGINE, ("GENERAL ENG EXHAUST GAS TEMPERATURE:" + to_string(engine_index)).c_str(), "celsius");
    SimConnect_AddToDataDefinition(simConnectHandle, DEFINITION_ENGINE, ("GENERAL ENG OIL PRESSURE:" + to_string(engine_index)).c_str(), "pascal");
    SimConnect_AddToDataDefinition(simConnectHandle, DEFINITION_ENGINE, ("GENERAL ENG OIL TEMPERATURE:" + to_string(engine_index)).c_str(), "celsius");
    SimConnect_AddToDataDefinition(simConnectHandle, DEFINITION_ENGINE, ("GENERAL ENG FUEL PRESSURE:" + to_string(engine_index)).c_str(), "pascal");
    SimConnect_AddToDataDefinition(simConnectHandle, DEFINITION_ENGINE, ("RECIP ENG MANIFOLD PRESSURE:" + to_string(engine_index)).c_str(), "pascal");
    SimConnect_AddToDataDefinition(simConnectHandle, DEFINITION_ENGINE, ("RECIP ENG BRAKE POWER:" + to_string(engine_index)).c_str(), "watt");
    SimConnect_AddToDataDefinition(simConnectHandle, DEFINITION_ENGINE, ("RECIP ENG STARTER TORQUE:" + to_string(engine_index)).c_str(), "newton meter");
    SimConnect_AddToDataDefinition(simConnectHandle, DEFINITION_ENGINE, ("RECIP ENG FUEL AVAILABLE:" + to_string(engine_index)).c_str(), "bool");
    SimConnect_AddToDataDefinition(simConnectHandle, DEFINITION_ENGINE, ("RECIP ENG FUEL FLOW:" + to_string(engine_index)).c_str(), "kilogram per second");
    SimConnect_AddToDataDefinition(simConnectHandle, DEFINITION_ENGINE, ("RECIP ENG CARBURETOR TEMPERATURE:" + to_string(engine_index)).c_str(), "celsius");
    SimConnect_AddToDataDefinition(simConnectHandle, DEFINITION_ENGINE, ("RECIP ENG MIXTURE RATIO:" + to_string(engine_index)).c_str(), "ratio");
    SimConnect_AddToDataDefinition(simConnectHandle, DEFINITION_ENGINE, ("ENG ON FIRE:" + to_string(engine_index)).c_str(), "bool");
    SimConnect_AddToDataDefinition(simConnectHandle, DEFINITION_ENGINE, ("PROP RPM:" + to_string(engine_index)).c_str(), "rpm");
}
Ideally, the main variables I'd like to set would be a combination of mixture ratio, manifold pressure, rpm, torque and bhp. Everything else doesn't matter as much.
DEFINITION_ENGINE = this should be specific name at each Avars
 

cheangjc

Resource contributor
#13
If you have a totally custom engine model, why are you trying to overwrite the default values? Just make your gauges show the custom model and only "use" the FDE engine model for "thrust". (i.e N1/rpm (indicator of thrust) -> convert to your other values; EGT and etc)
 

Heretic

Resource contributor
#14
Excuse my ignorance, but what would be the order of the processing chain, and why would it be important to stick to it?
I'm not familiar with pistons, so I don't know.

Probably throttle/prop/mixture lever values on one side and thrust, CHT and fuel flow on the other.
 
#16
All kidding aside, I am with CheangJC on this. Create fictional data, L:vars, to make your own custom readouts. So fast, and people will never know. I remember having to 'adjust' things like turbine N1 RPM data on a PW P67A because redoing the parameters to make the engine idle right were ASTRONOMICAL! And adjusting the output readout only took minutes. ;)
 
#17
This is interesting, it looks to me as if you guys never tried to overwrite the major engine parameters for piston engines yet, hu? Overwriting N2 doesn't really help me when I am dealing with this thing: :rotfl:


I currently gravitate towards setting up a PID or PD controller for the throttle axis with the goal of producing a set manifold pressure, depending on the calculations I do in the background. It's not the solution I wanted, but if the sim doesn't let me manipulate the variables directly it's probably the best way to deal with this problem...

I already follow your suggestion of creating LVars for all readouts. Essentially all of my instruments get their data through an LVar that's been provided by my DLL.

Bill, it is conceivable to create an anti-gravity drive for you Hanebu by freezing the craft's position and then manipulating it using simConnect. Would be a cool experiment ;)
 

rcbarend

Resource contributor
#18
Bill, it is conceivable to create an anti-gravity drive for you Hanebu by freezing the craft's position and then manipulating it using simConnect. Would be a cool experiment
In fact, I allready made that based on my VTOL stuff …….LoL

But to answer your question in an above post "" In that case, what's the purpose of making those variables settable in the first place? ""

As Doug explained above:
""Setting data like manifold pressure does not stop the sim from calculating its own value and updating the variable with that value. ""
So the result of overwriting an Avar strongly depends on how the sim calculates that var, and how it calculates the new value itself: instanteneously (based on other variables), or gradually (based on the previous value, which you commanded).
In other words: how hard the FDE "fights" your manipulation of an Avar.

To illustrate this, I'll give you an example from my VTOL implementations.
Suppose I want to make an object perfectly "hover" at a specific altitude with zero airspeed.
So the FDE, of course, will try to make the object drop like a rock.

What doesn't work good:
Constantly overwrite the Avar "PLANE ALTITUDE" with the desired value.
This will result in a pretty "jumpy" altitude and view.

What does work perfectly:
Constantly overwrite "VELOCITY BODY Y" with a value calculated from the difference between the (saved) intended value and actual value of PLANE ALTITUDE as calculated by the FDE.

Hope that this example makes it clear, why overwriting an Avar (even if it's settable) isn't always meaningfull or gives the intended result.

Rob
 

JB3DG

Resource contributor
#19
@Vitus I tried overwriting manifold pressure for the Milviz FG-1D in order to properly simulate the supercharger it has (and allow for the different blower settings that the pilot would manually apply) and the result was...iffy to say the least. I got around it however, by putting a turbo charger in the aircraft cfg file that had a critical altitude of 100 000ft. I then intercepted throttle inputs from the throttle events (which were masked from the sim) and redirected them into a formula supplied by our FDE guy and used that to set the sim throttle simvar, which delivered the desired MP. We faked the values on the gauge indicator so that I could set a lower actual MP (and thus power setting) if the user tried to set the higher blowers in the supercharger below the proper altitudes, thus simulating the loss of power in driving the supercharger. So yes, some sim vars get iffy if you try to set them, but there are ways around them. I also did an auto-mixture by intercepting the mixture lever inputs like the throttle and controlling the sim mixture lever using my formulae.
 

Roy Holmes

Resource contributor
#20
If you need a good overview of the propulsion flow used in the sim, I recommend aircraft_sim_tech_zyskowski.pdf. Basically the theory follows the Otto cycle and calculates the Brake HP of each cylinder. Total BHP is that times the number of cylinders. The flow then goes on to develop what is displayed on engine instruments, all of these parameters can be set externally.
I think the calculations used in the Otto cycle can probably only be altered by changing the inputs. So, manifold pressure would be derived from several inputs like ambient atmospheric pressure throttle position, charger boost etc. You could try setting those to see what that does.
Roy
 
Top