+/*
+ // Hack for testing - should output every 5 seconds
+ static int count1 = 0;
+ if(count1 == 0) {
+// cout << "P_atmos = " << p_amb << " T_atmos = " << T_amb << '\n';
+// cout << "Manifold pressure = " << Manifold_Pressure << " True_Manifold_Pressure = " << True_Manifold_Pressure << '\n';
+// cout << "p_amb_sea_level = " << p_amb_sea_level << '\n';
+// cout << "equivalence_ratio = " << equivalence_ratio << '\n';
+// cout << "combustion_efficiency = " << combustion_efficiency << '\n';
+// cout << "AFR = " << 14.7 / equivalence_ratio << '\n';
+// cout << "Mixture lever = " << Mixture_Lever_Pos << '\n';
+// cout << "n = " << RPM << " rpm\n";
+// cout << "T_amb = " << T_amb << '\n';
+// cout << "running = " << running << '\n';
+ cout << "fuel = " << fgGetFloat("/consumables/fuel/tank[0]/level-gal_us") << '\n';
+// cout << "Percentage_Power = " << Percentage_Power << '\n';
+// cout << "current_oil_temp = " << current_oil_temp << '\n';
+ cout << "EGT = " << EGT << '\n';
+ }
+ count1++;
+ if(count1 == 100)
+ count1 = 0;
+*/
+
+ // Check parameters that may alter the operating state of the engine.
+ // (spark, fuel, starter motor etc)
+
+ // Check for spark
+ bool Magneto_Left = false;
+ bool Magneto_Right = false;
+ // Magneto positions:
+ // 0 -> off
+ // 1 -> left only
+ // 2 -> right only
+ // 3 -> both
+ if(mag_pos != 0) {
+ spark = true;
+ } else {
+ spark = false;
+ } // neglects battery voltage, master on switch, etc for now.
+ if((mag_pos == 1) || (mag_pos > 2))
+ Magneto_Left = true;
+ if(mag_pos > 1)
+ Magneto_Right = true;
+
+ // crude check for fuel
+ if((fgGetFloat("/consumables/fuel/tank[0]/level-gal_us") > 0) || (fgGetFloat("/consumables/fuel/tank[1]/level-gal_us") > 0)) {
+ fuel = true;
+ } else {
+ fuel = false;
+ } // Need to make this better, eg position of fuel selector switch.
+
+ // Check if we are turning the starter motor
+ if(cranking != starter) {
+ // This check saves .../cranking from getting updated every loop - they only update when changed.
+ cranking = starter;
+ crank_counter = 0;
+ }
+ // Note that although /engines/engine[0]/starter and /engines/engine[0]/cranking might appear to be duplication it is
+ // not since the starter may be engaged with the battery voltage too low for cranking to occur (or perhaps the master
+ // switch just left off) and the sound manager will read .../cranking to determine wether to play a cranking sound.
+ // For now though none of that is implemented so cranking can be set equal to .../starter without further checks.
+
+// int Alternate_Air_Pos =0; // Off = 0. Reduces power by 3 % for same throttle setting
+ // DCL - don't know what this Alternate_Air_Pos is - this is a leftover from the Schubert code.
+
+ //Check mode of engine operation
+ if(cranking) {
+ crank_counter++;
+ if(RPM <= 480) {
+ RPM += 100;
+ if(RPM > 480)
+ RPM = 480;
+ } else {
+ // consider making a horrible noise if the starter is engaged with the engine running
+ }
+ }
+ if((!running) && (spark) && (fuel) && (crank_counter > 120)) {
+ // start the engine if revs high enough
+ if(RPM > 450) {
+ // For now just instantaneously start but later we should maybe crank for a bit
+ running = true;
+// RPM = 600;
+ }
+ }
+ if( (running) && ((!spark)||(!fuel)) ) {
+ // Cut the engine
+ // note that we only cut the power - the engine may continue to spin if the prop is in a moving airstream
+ running = false;
+ }
+
+ // Now we've ascertained whether the engine is running or not we can start to do the engine calculations 'proper'
+
+ // Calculate Sea Level Manifold Pressure
+ Manifold_Pressure = Calc_Manifold_Pressure( Throttle_Lever_Pos, Max_Manifold_Pressure, Min_Manifold_Pressure );
+ // cout << "manifold pressure = " << Manifold_Pressure << endl;
+
+ //Then find the actual manifold pressure (the calculated one is the sea level pressure)
+ True_Manifold_Pressure = Manifold_Pressure * p_amb / p_amb_sea_level;
+
+ //Do the fuel flow calculations
+ Calc_Fuel_Flow_Gals_Hr();
+
+ //Calculate engine power
+ Calc_Percentage_Power(Magneto_Left, Magneto_Right);
+ HP = Percentage_Power * MaxHP / 100.0;
+ Power_SI = HP * CONVERT_HP_TO_WATTS;
+
+ // FMEP calculation. For now we will just use this during motored operation.
+ // Eventually we will calculate IMEP and use the FMEP all the time to give BMEP (maybe!)
+ if(!running) {
+ // This FMEP data is from the Patton paper, assumes fully warm conditions.
+ FMEP = 1e-12*pow(RPM,4) - 1e-8*pow(RPM,3) + 5e-5*pow(RPM,2) - 0.0722*RPM + 154.85;
+ // Gives FMEP in kPa - now convert to Pa
+ FMEP *= 1000;
+ } else {
+ FMEP = 0.0;
+ }
+ // Is this total FMEP or friction FMEP ???
+
+ Torque_FMEP = (FMEP * displacement_SI) / (2.0 * LS_PI * n_R);
+
+ // Calculate Engine Torque. Check for div by zero since percentage power correlation does not guarantee zero power at zero rpm.
+ // However this is problematical since there is a resistance to movement even at rest
+ // Ie this is a dynamics equation not a statics one. This can be solved by going over to MEP based torque calculations.
+ if(RPM == 0) {
+ Torque_SI = 0 - Torque_FMEP;
+ }
+ else {
+ Torque_SI = ((Power_SI * 60.0) / (2.0 * LS_PI * RPM)) - Torque_FMEP; //Torque = power / angular velocity
+ // cout << Torque << " Nm\n";
+ }
+
+ //Calculate Exhaust gas temperature
+ if(running)
+ Calc_EGT();
+ else
+ EGT = 298.0;
+
+ // Calculate Cylinder Head Temperature
+ Calc_CHT();
+
+ // Calculate oil temperature
+ current_oil_temp = Calc_Oil_Temp(current_oil_temp);
+
+ // Calculate Oil Pressure
+ Oil_Pressure = Calc_Oil_Press( Oil_Temp, RPM );
+
+ // Now do the Propeller Calculations
+ Do_Prop_Calcs();
+
+// Now do the engine - prop torque balance to calculate final RPM
+
+ //Calculate new RPM from torque balance and inertia.
+ Torque_Imbalance = Torque_SI - prop_torque; //This gives a +ve value when the engine torque exeeds the prop torque
+ // (Engine torque is +ve when it acts in the direction of engine revolution, prop torque is +ve when it opposes the direction of engine revolution)
+
+ angular_acceleration = Torque_Imbalance / (engine_inertia + prop_inertia);
+ angular_velocity_SI += (angular_acceleration * time_step);
+ // Don't let the engine go into reverse
+ if(angular_velocity_SI < 0)
+ angular_velocity_SI = 0;
+ RPM = (angular_velocity_SI * 60) / (2.0 * LS_PI);
+
+ // And finally a last check on the engine state after doing the torque balance with the prop - have we stalled?
+ if(running) {
+ //Check if we have stalled the engine
+ if (RPM == 0) {
+ running = false;
+ } else if((RPM <= 480) && (cranking)) {
+ //Make sure the engine noise dosn't play if the engine won't start due to eg mixture lever pulled out.
+ running = false;
+ EGT = 298.0;
+ }
+ }
+
+ // And finally, do any unit conversions from internal units to output units
+ EGT_degF = (EGT * 1.8) - 459.67;
+ CHT_degF = (CHT * 1.8) - 459.67;