fuelAndIgnitionCalcs.c File Reference

Fuel and ignition calculations. More...

#include "inc/freeEMS.h"
#include "inc/commsCore.h"
#include "inc/tableLookup.h"
#include "inc/fuelAndIgnitionCalcs.h"

Include dependency graph for fuelAndIgnitionCalcs.c:

Go to the source code of this file.

Defines

#define FUELANDIGNITIONCALCS_C
#define oneHundredPercentPCFT   32768

Functions

void calculateFuelAndIgnition ()
 Fuel and ignition calculations.


Detailed Description

Fuel and ignition calculations.

This file contains all of the main fuel and ignition calculations based upon the variables that we have already determined in previous stages.

Author:
Fred Cooke

Definition in file fuelAndIgnitionCalcs.c.


Define Documentation

#define FUELANDIGNITIONCALCS_C

Definition at line 38 of file fuelAndIgnitionCalcs.c.

#define oneHundredPercentPCFT   32768


Function Documentation

void calculateFuelAndIgnition ( void   ) 

Fuel and ignition calculations.

Using a variety of primary algorithms calculate a base pulsewidth and then apply various corrections to it such as injector dead time, transient fuel correction, engine temperature enrichment and per cylinder trims. The fuel injection timing is also determined here.

Calculate the ignition timing and dwell here too. Several corrections are applied to these as well.

Todo:
TODO implement the all of the ignition stuff and finish off all of the fuel injection stuff.

TODO change the way configuration is done and make sure the most common options are after the first if().

TODO add actual configuration options to the fixed config blocks for these items.

Author:
Fred Cooke

Todo:
TODO figure out what the correct "temperature" is to make MAF work correctly!

Todo:
TODO check for overflow when TFC is positive and underflow when negative

Todo:
TODO check for overflow of ETE always

Todo:
TODO make injector channels come from config, not defines.

Todo:
TODO make injector channels come from config, not defines.

Todo:
TODO work needs to be done on scheduling before this can be completed.

Todo:
TODO x 6 main pulsewidths, x 6 staged pulsewidths, x 6 flags for staged channels if(coreSettingsA & STAGED_ON){}

Todo:
TODO determine the requirement for staged based on some sort of map and or complex load based configuration.

Todo:
TODO Calculate the fuel advances (six of)

Todo:
TODO Calculate the dwell period (one of)

Todo:
TODO Calculate the ignition advances (twelve of)

Definition at line 61 of file fuelAndIgnitionCalcs.c.

References ADCArrays, DerivedVar::AirFlow, DerivedVar::BasePW, bootFuelConst, fixedConfig1::coreSettingsA, coreStatusA, CoreVars, currentDwellMath, DerivedVar::densityAndFuel, engineSetting::densityOfFuelAtSTP, densityOfFuelTotalDivisor, DerivedVars, ADCArray::EGO, fixedConfig1::engineSettings, DerivedVar::ETE, FALSE, DerivedVar::FinalPW, fixedConfigs1, fixedConfigs2, CoreVar::IAT, DerivedVar::IDT, IGNITION_CHANNELS, ignitionAdvances, INJECTION_CHANNELS, injectorMainPulseWidthsMath, DerivedVar::Lambda, CoreVar::MAF, ADCArray::MAP, CoreVar::MAP, masterPulseWidth, ADCArray::MAT, oneHundredPercentPCFT, oneHundredPercentVE, sensorPreset::presetAF, sensorPreset::presetBPW, DerivedVar::RefPW, roomTemperature, fixedConfig2::sensorPresets, SHORTMAX, STAGED_NOT_REQUIRED, STAGED_ON, STAGED_REQUIRED, stoichiometricLambda, DerivedVar::TFCTotal, totalAngleAfterReferenceInjection, ADCArray::TPS, TRUE, and DerivedVar::VEMain.

Referenced by main().

00061                                {
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 }


Generated on Mon Jan 26 00:16:59 2009 for FreeEMS by  doxygen 1.5.8