00001 /* FreeEMS - the open source engine management system 00002 * 00003 * Copyright 2008, 2009, 2010 Fred Cooke 00004 * 00005 * This file is part of the FreeEMS project. 00006 * 00007 * FreeEMS software is free software: you can redistribute it and/or modify 00008 * it under the terms of the GNU General Public License as published by 00009 * the Free Software Foundation, either version 3 of the License, or 00010 * (at your option) any later version. 00011 * 00012 * FreeEMS software is distributed in the hope that it will be useful, 00013 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00015 * GNU General Public License for more details. 00016 * 00017 * You should have received a copy of the GNU General Public License 00018 * along with any FreeEMS software. If not, see http://www.gnu.org/licenses/ 00019 * 00020 * We ask that if you make any changes to this file you email them upstream to 00021 * us at admin(at)diyefi(dot)org or, even better, fork the code on github.com! 00022 * 00023 * Thank you for choosing FreeEMS to run your engine! 00024 */ 00025 00026 00039 #define FUELANDIGNITIONCALCS_C 00040 #include "inc/freeEMS.h" 00041 #include "inc/utils.h" 00042 #include "inc/commsCore.h" 00043 #include "inc/tableLookup.h" 00044 #include "inc/fuelAndIgnitionCalcs.h" 00045 00046 00063 void calculateFuelAndIgnition(){ 00064 /*&&&&&&&&&&&&& Perform the basic calculations one step at a time to get a final pulsewidth &&&&&&&&&&&&*/ 00065 00066 if(TRUE /* Genuine method */){ 00067 unsigned short airInletTemp = CoreVars->IAT; /* All except MAF use this. */ 00068 /* Determine the type of air flow data */ 00069 if(TRUE /* SpeedDensity */){ 00070 /* This won't overflow until 512kPa or about 60psi of boost with 128% VE. */ 00071 DerivedVars->AirFlow = ((unsigned long)CoreVars->MAP * DerivedVars->VEMain) / oneHundredPercentVE; 00072 /* Result is 450 - 65535 always. */ 00073 }else if(FALSE /*AlphaN*/){ 00074 DerivedVars->AirFlow = DerivedVars->VEMain; /* Not actually VE, but rather tuned air flow without density information */ 00075 }else if(FALSE /*MAF*/){ 00076 DerivedVars->AirFlow = CoreVars->MAF; /* Just fix temperature at appropriate level to provide correct Lambda */ 00078 airInletTemp = roomTemperature; // 293.15k is 20c * 100 to get value, so divide by 100 to get real number 00079 }else if(FALSE /*FixedAF*/){ /* Fixed air flow from config */ 00080 DerivedVars->AirFlow = fixedConfigs2.sensorPresets.presetAF; 00081 }else{ /* Default to no fuel delivery and error */ 00082 DerivedVars->AirFlow = 0; 00083 /* If anyone is listening, let them know something is wrong */ 00084 // sendError(AIRFLOW_NOT_CONFIGURED_CODE); // or maybe queue it? 00085 } 00086 00087 00088 /* This won't overflow until well past 125C inlet, 1.5 Lambda and fuel as dense as water */ 00089 DerivedVars->densityAndFuel = (((unsigned long)((unsigned long)airInletTemp * DerivedVars->Lambda) / stoichiometricLambda) * fixedConfigs1.engineSettings.densityOfFuelAtSTP) / densityOfFuelTotalDivisor; 00090 /* Result is 7500 - 60000 always. */ 00091 00092 /* Divisors for air inlet temp and pressure : 00093 * #define airInletTempDivisor 100 00094 * #define airPressureDivisor 100 00095 * cancel each other out! all others are used. */ 00096 00097 00098 DerivedVars->BasePW = (bootFuelConst * DerivedVars->AirFlow) / DerivedVars->densityAndFuel; 00099 }else if(FALSE /*configured*/){ /* Fixed PW from config */ 00100 DerivedVars->BasePW = fixedConfigs2.sensorPresets.presetBPW; 00101 }else{ /* Default to no fuel delivery and error */ 00102 DerivedVars->BasePW = 0; 00103 /* If anyone is listening, let them know something is wrong */ 00104 // sendError(BPW_NOT_CONFIGURED_CODE); // or maybe queue it? 00105 } 00106 00107 /*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ 00108 00109 00110 00111 00112 /*&&&&&&&&&&&&&&&&&&&&&&&&&&&& Apply All Corrections PCFC, ETE, IDT, TFC etc &&&&&&&&&&&&&&&&&&&&&&&&&&&*/ 00113 00114 /* Apply the corrections after calculating */ 00115 DerivedVars->FinalPW = safeTrim(DerivedVars->BasePW, DerivedVars->TFCTotal); 00116 DerivedVars->FinalPW = safeScale(DerivedVars->FinalPW, DerivedVars->ETE); 00117 00118 00119 unsigned char channel; // the declaration of this variable is used in multiple loops below. 00120 00121 /* "Calculate" the individual fuel pulse widths */ 00122 for(channel = 0; channel < INJECTION_CHANNELS; channel++){ 00123 /* Add or subtract the per cylinder fuel trims */ 00124 unsigned short channelPW; 00125 channelPW = safeScale(DerivedVars->FinalPW, TablesB.SmallTablesB.perCylinderFuelTrims[channel]); 00126 00127 /* Add on the IDT to get the final value and put it into the array */ 00128 injectorMainPulseWidthsMath[channel] = safeAdd(channelPW, DerivedVars->IDT); 00129 } 00130 00131 /* Reference PW for comparisons etc */ 00132 unsigned short refPW = safeAdd(DerivedVars->FinalPW, DerivedVars->IDT); 00133 DerivedVars->RefPW = refPW; 00134 /*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ 00135 00136 00137 00138 00139 /*&&&&&&&&&&&&&&&&& Based on IDT schedule PW start such that Fuel is correctly timed &&&&&&&&&&&&&&&&&&&*/ 00140 00141 for(channel = 0;channel < INJECTION_CHANNELS;channel++){ 00142 //injectorMainAdvances[channel] = IDT blah blah. 00143 } 00144 00145 /* This will involve using RPM, injector firing angle and IDT to schedule the events correctly */ 00146 00149 /*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ 00150 00151 00152 00153 00154 /*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& Calculate Dwell and Ignition angle &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ 00155 /*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ 00156 00157 00158 00159 00160 /*&&&&&&&&&&&&&&& Based on Dwell and Ignition angle schedule the start and end of dwell &&&&&&&&&&&&&&&&*/ 00161 /*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ 00162 00163 00164 00165 00166 /*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& TEMPORARY (and old) &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ 00167 00168 /* "Calculate" the nominal total pulse width before per channel corrections */ 00169 masterPulseWidth = refPW;//(ADCArrays->EGO << 6) + (ADCArrays->MAP >> 4); 00170 00171 /* "Calculate" the individual fuel pulse widths */ 00172 for(channel = 0; channel < INJECTION_CHANNELS; channel++){ 00173 injectorMainPulseWidthsMath[channel] = masterPulseWidth; 00174 } 00175 00177 00178 /* Set the staged status on or off (for now based on changeable settings) */ 00179 if(fixedConfigs1.coreSettingsA & STAGED_ON){ 00180 coreStatusA |= STAGED_REQUIRED; 00182 }else{ 00183 coreStatusA &= STAGED_NOT_REQUIRED; 00184 } 00185 00186 // temporary ign tests 00187 unsigned short intendedAdvance = ADCArrays->MAT << 6; 00188 unsigned short intendedDwell = intendedAdvance >> 1; 00189 00190 short c; 00191 for(c=0;c<IGNITION_CHANNELS;c++){ 00192 ignitionAdvances[IGNITION_CHANNELS] = intendedAdvance; 00193 } 00194 *currentDwellMath = intendedDwell; 00195 00196 // unsigned short minPeriod = ignitionMinimumDwell << 1; 00197 // if(intendedDwell < ignitionMinimumDwell){ 00198 // dwellLength = ignitionMinimumDwell; 00199 // }else{ 00200 // dwellLength = intendedDwell; 00201 // } 00202 // if(intendedPeriod < minPeriod){ 00203 // dwellPeriod = minPeriod; 00204 // }else{ 00205 // dwellPeriod = intendedPeriod; 00206 // } 00207 // PITLD0 = dwellPeriod; 00208 00210 // just use one for all for now... 00211 totalAngleAfterReferenceInjection = (ADCArrays->TPS << 6); 00212 00217 /*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& TEMPORARY END &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ 00218 }