From 64719b3da1cc6f5ae067479af3c1c1ed77d952e5 Mon Sep 17 00:00:00 2001 From: curt Date: Wed, 6 Sep 2000 15:45:43 +0000 Subject: [PATCH] Initial revision. --- src/FDM/ps-10520c.cxx | 529 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 529 insertions(+) create mode 100644 src/FDM/ps-10520c.cxx diff --git a/src/FDM/ps-10520c.cxx b/src/FDM/ps-10520c.cxx new file mode 100644 index 000000000..78ffb24a9 --- /dev/null +++ b/src/FDM/ps-10520c.cxx @@ -0,0 +1,529 @@ +// Module: 10520c.c +// Author: Phil Schubert +// Date started: 12/03/99 +// Purpose: Models a Continental IO-520-M Engine +// Called by: FGSimExec +// +// Copyright (C) 1999 Philip L. Schubert (philip@zedley.com) +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 2 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA +// 02111-1307, USA. +// +// Further information about the GNU General Public License can also +// be found on the world wide web at http://www.gnu.org. +// +// FUNCTIONAL DESCRIPTION +// ------------------------------------------------------------------------ +// Models a Continental IO-520-M engine. This engine is used in Cessna +// 210, 310, Beechcraft Bonaza and Baron C55. The equations used below +// were determined by a first and second order curve fits using Excel. +// The data is from the Cessna Aircraft Corporations Engine and Flight +// Computer for C310. Part Number D3500-13 +// +// ARGUMENTS +// ------------------------------------------------------------------------ +// +// +// HISTORY +// ------------------------------------------------------------------------ +// 12/03/99 PLS Created +// 07/03/99 PLS Added Calculation of Density, and Prop_Torque +// 07/03/99 PLS Restructered Variables to allow easier implementation +// of Classes +// 15/03/99 PLS Added Oil Pressure +// 19/8/2000 PLS Updated E-mail address - This version compiles +// 19/8/2000 PLS Set Max Prop blade angle to prevent prop exeeding 90 +// ------------------------------------------------------------------------ +// INCLUDES +// ------------------------------------------------------------------------ + +#include +// #include +#include +// #include "10520c.h" + +// ------------------------------------------------------------------------ +// CODE +// ------------------------------------------------------------------------ + +// prototype definitions +// These should be in a header file 10520c.h + +float Density (float x); +void ShowRho (float x); + +float IAS_to_FPS (float x); +void ShowFPS(float x); + +float Get_Throttle (float x); +void Show_Throttle (float x); + +float Manifold_Pressure (float x, float z); +void Show_Manifold_Pressure (float x); + +float CHT (float Fuel_Flow, float Mixture, float IAS); +void Show_CHT (float x); + +float Oil_Temp (float x, float y); +void Show_Oil_Temp (float x); + +float Oil_Press (float Oil_Temp, float Engine_RPM); +void Show_Oil_Press (float x); + +int main() + +{ + // Declare local variables + int num = 0; // Not used. Counting variables + int num2 = 100; // Not used. + float ManXRPM = 0; + float Vo = 0; + float V1 = 0; + + + // Set up the new variables + float Blade_Station = 30; + float Rho = 0.002378; + float FGProp_Area = 1.405/3; + float PI = 3.1428571; + + // Input Variables + float IAS = 0; + cout << "Enter IAS "; + // cin >> IAS; + IAS = 85; + cout << endl; + + + // 0 = Closed, 100 = Fully Open + float FGEng1_Throttle_Lever_Pos = 75; + // 0 = Full Course 100 = Full Fine + float FGEng1_Propeller_Lever_Pos = 75; + // 0 = Idle Cut Off 100 = Full Rich + float FGEng1_Mixture_Lever_Pos = 100; + + // Environmental Variables + + // Temp Variation from ISA (Deg F) + float FG_ISA_VAR = 0; + // Pressure Altitude 1000's of Feet + float FG_Pressure_Ht = 0; + + // Parameters that alter the operation of the engine. + // Yes = 1. Is there Fuel Available. Calculated elsewhere + int FGEng1_Fuel_Available = 1; + // Off = 0. Reduces power by 3 % for same throttle setting + int FGEng1_Alternate_Air_Pos =0; + // 1 = On. Reduces power by 5 % for same power lever settings + int FGEng1_Magneto_Left = 1; + // 1 = On. Ditto, Both of the above though do not alter fuel flow + int FGEng1_Magneto_Right = 1; + + // There needs to be a section in here to trap silly values, like + // 0, otherwise they will crash the calculations + + // Engine Specific Variables used by this program that have limits. + // Will be set in a parameter file to be read in to create + // and instance for each engine. + float FGEng_Max_Manifold_Pressure = 29.50; + float FGEng_Max_RPM = 2700; + float FGEng_Min_RPM = 1000; + float FGEng_Max_Fuel_Flow = 130; + float FGEng_Mag_Derate_Percent = 5; + float FGEng_MaxHP = 285; + float FGEng_Gear_Ratio = 1; + + // Initialise Engine Variables used by this instance + float FGEng1_Percentage_Power = 0; + float FGEng1_Manifold_Pressure = 29.00; // Inches + float FGEng1_RPM = 500; + float FGEng1_Fuel_Flow = 0; // lbs/hour + float FGEng1_Torque = 0; + float FGEng1_CHT = 370; + float FGEng1_Mixture = 14; + float FGEng1_Oil_Pressure = 0; // PSI + float FGEng1_Oil_Temp = 85; // Deg C + float FGEng1_HP = 0; + float FGEng1_RPS = 0; + float Torque_Imbalance = 0; + float FGEng1_Desired_RPM = 0; + + // Initialise Propellor Variables used by this instance + float FGProp1_Angular_V = 0; + float FGProp1_Coef_Drag = 0.6; + float FGProp1_Torque = 0; + float FGProp1_Thrust = 0; + float FGProp1_RPS = 0; + float FGProp1_Coef_Lift = 0.1; + float Alpha1 = 13.5; + float FGProp1_Blade_Angle = 13.5; + float FGProp_Fine_Pitch_Stop = 13.5; + float FGProp_Course_Pitch_Stop = 55; + + // cout << "Enter Blade Angle "; + // cin >> FGProp1_Blade_Angle; + // cout << endl; + + cout << " Number of Iterations "; + // cin >> num2; + num2 = 100; + cout << endl; + + cout << " Throttle % "; + // cin >> FGEng1_Throttle_Lever_Pos; + FGEng1_Throttle_Lever_Pos = 50; + cout << endl; + + cout << " Prop % "; + // cin >> FGEng1_Propeller_Lever_Pos; + FGEng1_Propeller_Lever_Pos = 100; + cout << endl; + + //================================================================== + // Engine & Environmental Inputs from elsewhere + + // Calculate Air Density (Rho) - In FG this is calculated in + // FG_Atomoshere.cxx + + Rho = Density(FG_Pressure_Ht); // In FG FG_Pressure_Ht is "h" + ShowRho(Rho); + + + // Calculate Manifold Pressure (Engine 1) as set by throttle opening + + FGEng1_Manifold_Pressure = Manifold_Pressure(FGEng1_Throttle_Lever_Pos, + FGEng1_Manifold_Pressure ); + Show_Manifold_Pressure(FGEng1_Manifold_Pressure); + + // Calculate Desired RPM as set by Prop Lever Position. + // Actual engine RPM may be different + // The governed max RPM at 100% Prop Lever Position = FGEng_MaxRPM + // The governed minimum RPM at 0% Prop Lever Position = FGEng_Min_RPM + // The actual minimum RPM of the engine can be < FGEng_Min_RPM if there is insufficient + // engine torque to counter act the propeller torque at FGProp_Fine_Pitch_Stop + + FGEng1_RPM = (FGEng1_Propeller_Lever_Pos * (FGEng_Max_RPM - FGEng_Min_RPM) /100) + + FGEng_Min_RPM ; + + // * ((FGEng_Max_RPM + FGEng_Min_RPM) / 100); + + if (FGEng1_RPM >= 2700) { + FGEng1_RPM = 2700; + } + FGEng1_Desired_RPM = FGEng1_RPM; + + cout << "Desired RPM = " << FGEng1_Desired_RPM << endl; + + //================================================================== + // Engine Power & Torque Calculations + + // Loop until stable - required for testing only + for (num = 1; num < num2; num++) { + cout << endl << "====================" << endl; + cout << "MP Inches = " << FGEng1_Manifold_Pressure << "\t"; + cout << FGEng1_RPM << " RPM" << "\t"; + + // For a givem Manifold Pressure and RPM calculate the % Power + // Multiply Manifold Pressure by RPM + ManXRPM = FGEng1_Manifold_Pressure * FGEng1_RPM; + cout << ManXRPM << endl; + + // Calculate % Power + FGEng1_Percentage_Power = (+ 7E-09 * ManXRPM * ManXRPM) + + ( + 7E-04 * ManXRPM) - 0.1218; + cout << "percent power = " << FGEng1_Percentage_Power << "%" << "\t"; + + // Adjust for Temperature - Temperature above Standard decrease + // power % by 7/120 per degree F increase, and incease power for + // temps below at the same ratio + FGEng1_Percentage_Power = FGEng1_Percentage_Power - (FG_ISA_VAR * 7 /120); + cout << " adjusted T = " << FGEng1_Percentage_Power << "%" << "\t"; + + // Adjust for Altitude. In this version a linear variation is + // used. Decrease 1% for each 1000' increase in Altitde + FGEng1_Percentage_Power = FGEng1_Percentage_Power + + (FG_Pressure_Ht * 12/10000); + cout << " adjusted A = " << FGEng1_Percentage_Power << "%" << "\t"; + + // Now Calculate Fuel Flow based on % Power Best Power Mixture + FGEng1_Fuel_Flow = FGEng1_Percentage_Power + * FGEng_Max_Fuel_Flow / 100; + // cout << FGEng1_Fuel_Flow << " lbs/hr"<< endl; + + // Now Derate engine for the effects of Bad/Switched off magnetos + if (FGEng1_Magneto_Left == 0 && FGEng1_Magneto_Right == 0) { + // cout << "Both OFF\n"; + FGEng1_Percentage_Power = 0; + } else if (FGEng1_Magneto_Left && FGEng1_Magneto_Right) { + // cout << "Both On "; + } else if (FGEng1_Magneto_Left == 0 || FGEng1_Magneto_Right== 0) { + // cout << "1 Magneto Failed "; + + FGEng1_Percentage_Power = FGEng1_Percentage_Power * + ((100 - FGEng_Mag_Derate_Percent)/100); + // cout << FGEng1_Percentage_Power << "%" << "\t"; + } + + // Calculate Engine Horsepower + + FGEng1_HP = FGEng1_Percentage_Power * FGEng_MaxHP/100; + + // Calculate Engine Torque + + FGEng1_Torque = FGEng1_HP * 5252 / FGEng1_RPM; + cout << FGEng1_Torque << "Ft/lbs" << "\t"; + + // Calculate Cylinder Head Temperature + FGEng1_CHT = CHT (FGEng1_Fuel_Flow, FGEng1_Mixture, IAS); + // Show_CHT (FGEng1_CHT); + + // Calculate Oil Pressure + FGEng1_Oil_Pressure = Oil_Press (FGEng1_Oil_Temp, FGEng1_RPM); + // Show_Oil_Press(FGEng1_Oil_Pressure); + + + //============================================================== + + // Now do the Propellor Calculations + + // Revs per second + FGProp1_RPS = FGEng1_RPM * FGEng_Gear_Ratio/60; + // cout << FGProp1_RPS << " RPS" << endl; + + //Radial Flow Vector (V2) Ft/sec at Ref Blade Station (usually 30") + FGProp1_Angular_V = FGProp1_RPS * 2 * PI * (Blade_Station / 12); + cout << "Angular Velocity " << FGProp1_Angular_V << endl; + + // Axial Flow Vector (Vo) Ft/sec + // Some further work required here to allow for inflow at low speeds + // Vo = (IAS + 20) * 1.688888; + Vo = IAS_to_FPS(IAS + 20); + // ShowFPS ( Vo ); + + // cout << Vo << "Axial Velocity" << endl; + + // Relative Velocity (V1) + V1 = sqrt((FGProp1_Angular_V * FGProp1_Angular_V) + + (Vo * Vo)); + cout << "Relative Velocity " << V1 << endl; + + if ( FGProp1_Blade_Angle >= FGProp_Course_Pitch_Stop ) { + FGProp1_Blade_Angle = FGProp_Course_Pitch_Stop; + } + + cout << FGProp1_Blade_Angle << " Prop Blade Angle" << endl; + + // Blade Angle of Attack (Alpha1) + + Alpha1 = FGProp1_Blade_Angle -(atan(Vo / FGProp1_Angular_V) * (180/PI)); + // cout << Alpha1 << " Alpha1" << endl; + + cout << " Alpha1 = " << Alpha1 + << " Blade angle = " << FGProp1_Blade_Angle + << " Vo = " << Vo + << " FGProp1_Angular_V = " << FGProp1_Angular_V << endl; + + // Calculate Coefficient of Drag at Alpha1 + FGProp1_Coef_Drag = (0.0005 * (Alpha1 * Alpha1)) + (0.0003 * Alpha1) + + 0.0094; + // cout << FGProp1_Coef_Drag << " Coef Drag" << endl; + + // Calculate Coefficient of Lift at Alpha1 + FGProp1_Coef_Lift = -(0.0026 * (Alpha1 * Alpha1)) + (0.1027 * Alpha1) + + 0.2295; + // cout << FGProp1_Coef_Lift << " Coef Lift " << endl; + + // Covert Alplha1 to Radians + // Alpha1 = Alpha1 * PI / 180; + + // Calculate Prop Torque + FGProp1_Torque = (0.5 * Rho * (V1 * V1) * FGProp_Area + * ((FGProp1_Coef_Lift * sin(Alpha1 * PI / 180)) + + (FGProp1_Coef_Drag * cos(Alpha1 * PI / 180)))) + * (Blade_Station/12); + cout << "Prop Torque = " << FGProp1_Torque << endl; + + // Calculate Prop Thrust + FGProp1_Thrust = 0.5 * Rho * (V1 * V1) * FGProp_Area + * ((FGProp1_Coef_Lift * cos(Alpha1 * PI / 180)) + - (FGProp1_Coef_Drag * sin(Alpha1 * PI / 180))); + cout << " Prop Thrust = " << FGProp1_Thrust << endl; + + // End of Propeller Calculations + //============================================================== + + + + Torque_Imbalance = FGProp1_Torque - FGEng1_Torque; + // cout << Torque_Imbalance << endl; + + if (Torque_Imbalance > 20) { + FGEng1_RPM -= 14.5; + // FGProp1_RPM -= 25; + FGProp1_Blade_Angle -= 0.75; + } + + if (FGProp1_Blade_Angle < FGProp_Fine_Pitch_Stop) { + FGProp1_Blade_Angle = FGProp_Fine_Pitch_Stop; + } + if (Torque_Imbalance < -20) { + FGEng1_RPM += 14.5; + // FGProp1_RPM += 25; + FGProp1_Blade_Angle += 0.75; + } + + if (FGEng1_RPM >= 2700) { + FGEng1_RPM = 2700; + } + + + // cout << FGEng1_RPM << " Blade_Angle " << FGProp1_Blade_Angle << endl << endl; + + } + + + return (0); +} + + + + +// Functions + +// Calculate Air Density - Rho +float Density ( float x ) +{ + float y ; + y = ((9E-08 * x * x) - (7E-08 * x) + 0.0024); + return(y); +} + +// Show Air Density Calculations +void ShowRho (float x) +{ + cout << "Rho = "; + cout << x << endl; +} + + + + + +// Calculate Speed in FPS given Knots CAS +float IAS_to_FPS (float x) +{ + float y; + y = x * 1.68888888; + return (y); +} + +// Show Feet per Second +void ShowFPS (float x) +{ + cout << "Feet/sec = "; + cout << x << endl; +} + + + +// Calculate Manifold Pressure based on Throttle lever Position + +float Manifold_Pressure ( float x, float z) +{ + float y; + // if ( x < = 0 ) + // { + // x = 0.00001; + // } + y = x * z / 100; + return (y); +} + +// Show Manifold Pressure +void Show_Manifold_Pressure (float x) +{ + cout << "Manifold Pressure = "; + cout << x << endl; +} + +// Calculate Oil Temperature + +float Oil_Temp (float Fuel_Flow, float Mixture, float IAS) +{ + float Oil_Temp = 85; + + return (Oil_Temp); +} + +// Show Oil Temperature + +void Show_Oil_Temp (float x) +{ + cout << "Oil Temperature (F) = "; + cout << x << endl; +} + + +// Calculate Oil Pressure + +float Oil_Press (float Oil_Temp, float Engine_RPM) +{ + float Oil_Pressure = 0; //PSI + float Oil_Press_Relief_Valve = 60; //PSI + float Oil_Press_RPM_Max = 1800; + float Design_Oil_Temp = 85; //Celsius + float Oil_Viscosity_Index = 0.25; // PSI/Deg C + float Temp_Deviation = 0; // Deg C + + Oil_Pressure = (Oil_Press_Relief_Valve / Oil_Press_RPM_Max) * Engine_RPM; + + // Pressure relief valve opens at Oil_Press_Relief_Valve PSI setting + if (Oil_Pressure >= Oil_Press_Relief_Valve) + { + Oil_Pressure = Oil_Press_Relief_Valve; + } + + // Now adjust pressure according to Temp which affects the viscosity + + Oil_Pressure += (Design_Oil_Temp - Oil_Temp) * Oil_Viscosity_Index; + + return (Oil_Pressure); +} + +// Show Oil Pressure +void Show_Oil_Press (float x) +{ + cout << "Oil Pressure (PSI) = "; + cout << x << endl; +} + + + +// Calculate Cylinder Head Temperature + +float CHT (float Fuel_Flow, float Mixture, float IAS) +{ + float CHT = 350; + + return (CHT); +} + +// Show Cyl Head Temperature + +void Show_CHT (float x) +{ + cout << "CHT (F) = "; + cout << x << endl; +}