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/DecoderInterface.h" 00045 #include "inc/fuelAndIgnitionCalcs.h" 00046 00047 00064 void calculateFuelAndIgnition(){ 00065 /*&&&&&&&&&&&&& Perform the basic calculations one step at a time to get a final pulsewidth &&&&&&&&&&&&*/ 00066 00067 if(TRUE /* Genuine method */){ 00068 unsigned short airInletTemp = CoreVars->IAT; /* All except MAF use this. */ 00069 /* Determine the type of air flow data */ 00070 if(TRUE /* SpeedDensity */){ 00071 /* This won't overflow until 512kPa or about 60psi of boost with 128% VE. */ 00072 DerivedVars->AirFlow = ((unsigned long)CoreVars->MAP * DerivedVars->VEMain) / oneHundredPercentVE; 00073 /* Result is 450 - 65535 always. */ 00074 }else if(FALSE /*AlphaN*/){ 00075 DerivedVars->AirFlow = DerivedVars->VEMain; /* Not actually VE, but rather tuned air flow without density information */ 00076 }else if(FALSE /*MAF*/){ 00077 DerivedVars->AirFlow = CoreVars->MAF; /* Just fix temperature at appropriate level to provide correct Lambda */ 00079 airInletTemp = roomTemperature; // 293.15k is 20c * 100 to get value, so divide by 100 to get real number 00080 }else if(FALSE /*FixedAF*/){ /* Fixed air flow from config */ 00081 DerivedVars->AirFlow = fixedConfigs2.sensorPresets.presetAF; 00082 }else{ /* Default to no fuel delivery and error */ 00083 DerivedVars->AirFlow = 0; 00084 /* If anyone is listening, let them know something is wrong */ 00085 // sendError(AIRFLOW_NOT_CONFIGURED_CODE); // or maybe queue it? 00086 } 00087 00088 00089 /* This won't overflow until well past 125C inlet, 1.5 Lambda and fuel as dense as water */ 00090 DerivedVars->densityAndFuel = (((unsigned long)((unsigned long)airInletTemp * DerivedVars->Lambda) / stoichiometricLambda) * fixedConfigs1.engineSettings.densityOfFuelAtSTP) / densityOfFuelTotalDivisor; 00091 /* Result is 7500 - 60000 always. */ 00092 00093 /* Divisors for air inlet temp and pressure : 00094 * #define airInletTempDivisor 100 00095 * #define airPressureDivisor 100 00096 * cancel each other out! all others are used. */ 00097 00098 00099 DerivedVars->BasePW = (bootFuelConst * DerivedVars->AirFlow) / DerivedVars->densityAndFuel; 00100 }else if(FALSE /*configured*/){ /* Fixed PW from config */ 00101 DerivedVars->BasePW = fixedConfigs2.sensorPresets.presetBPW; 00102 }else{ /* Default to no fuel delivery and error */ 00103 DerivedVars->BasePW = 0; 00104 /* If anyone is listening, let them know something is wrong */ 00105 // sendError(BPW_NOT_CONFIGURED_CODE); // or maybe queue it? 00106 } 00107 00108 /*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ 00109 00110 00111 00112 00113 /*&&&&&&&&&&&&&&&&&&&&&&&&&&&& Apply All Corrections PCFC, ETE, IDT, TFC etc &&&&&&&&&&&&&&&&&&&&&&&&&&&*/ 00114 00115 /* Apply the corrections after calculating */ 00116 DerivedVars->EffectivePW = safeTrim(DerivedVars->BasePW, DerivedVars->TFCTotal); 00117 DerivedVars->EffectivePW = safeScale(DerivedVars->EffectivePW, DerivedVars->ETE); 00118 00119 00120 unsigned char channel; // the declaration of this variable is used in multiple loops below. 00121 00122 /* "Calculate" the individual fuel pulse widths */ 00123 for(channel = 0; channel < INJECTION_CHANNELS; channel++){ 00124 /* Add or subtract the per cylinder fuel trims */ 00125 unsigned short channelPW; 00126 channelPW = safeScale(DerivedVars->EffectivePW, TablesB.SmallTablesB.perCylinderFuelTrims[channel]); 00127 00128 /* Add on the IDT to get the final value and put it into the array */ 00129 injectorMainPulseWidthsMath[channel] = safeAdd(channelPW, DerivedVars->IDT); 00130 } 00131 00132 /* Reference PW for comparisons etc */ 00133 unsigned short refPW = safeAdd(DerivedVars->EffectivePW, DerivedVars->IDT); 00134 DerivedVars->RefPW = refPW; 00135 /*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ 00136 00137 00138 00139 00140 /*&&&&&&&&&&&&&&&&& Based on IDT schedule PW start such that Fuel is correctly timed &&&&&&&&&&&&&&&&&&&*/ 00141 00142 for(channel = 0;channel < INJECTION_CHANNELS;channel++){ 00143 //injectorMainAdvances[channel] = IDT blah blah. 00144 } 00145 00146 /* This will involve using RPM, injector firing angle and IDT to schedule the events correctly */ 00147 00150 /*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ 00151 00152 00153 00154 00155 /*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& Calculate Dwell and Ignition angle &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ 00156 /*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ 00157 00158 00159 00160 00161 /*&&&&&&&&&&&&&&& Based on Dwell and Ignition angle schedule the start and end of dwell &&&&&&&&&&&&&&&&*/ 00162 /*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ 00163 00164 00165 00166 00167 /*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& TEMPORARY (and old) &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ 00168 00169 /* "Calculate" the nominal total pulse width before per channel corrections */ 00170 masterPulseWidth = refPW;//(ADCArrays->EGO << 6) + (ADCArrays->MAP >> 4); 00171 00172 /* "Calculate" the individual fuel pulse widths */ 00173 for(channel = 0; channel < INJECTION_CHANNELS; channel++){ 00174 injectorMainPulseWidthsMath[channel] = masterPulseWidth; 00175 } 00176 00178 00179 /* Set the staged status on or off (for now based on changeable settings) */ 00180 if(fixedConfigs1.coreSettingsA & STAGED_ON){ 00181 coreStatusA |= STAGED_REQUIRED; 00183 }else{ 00184 coreStatusA &= STAGED_NOT_REQUIRED; 00185 } 00186 00187 // temporary ign tests 00188 unsigned short intendedAdvance = ADCArrays->MAT << 6; 00189 unsigned short intendedDwell = intendedAdvance >> 1; 00190 00191 short c; 00192 for(c=0;c<IGNITION_CHANNELS;c++){ 00193 ignitionAdvances[IGNITION_CHANNELS] = intendedAdvance; 00194 } 00195 *currentDwellMath = intendedDwell; 00196 00197 // unsigned short minPeriod = ignitionMinimumDwell << 1; 00198 // if(intendedDwell < ignitionMinimumDwell){ 00199 // dwellLength = ignitionMinimumDwell; 00200 // }else{ 00201 // dwellLength = intendedDwell; 00202 // } 00203 // if(intendedPeriod < minPeriod){ 00204 // dwellPeriod = minPeriod; 00205 // }else{ 00206 // dwellPeriod = intendedPeriod; 00207 // } 00208 // PITLD0 = dwellPeriod; 00209 00211 // just use one for all for now... 00212 totalAngleAfterReferenceInjection = (ADCArrays->TPS << 6); 00213 00218 /*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& TEMPORARY END &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ 00219 }