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