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 COREVARSGENERATOR_C 00040 #include "inc/freeEMS.h" 00041 #include "inc/commsCore.h" 00042 #include "inc/coreVarsGenerator.h" 00043 #include "inc/DecoderInterface.h" 00044 00045 00059 void generateCoreVars(){ 00060 /*&&&&&&&& Calculate and obtain the basic variables with which we will perform the calculations &&&&&&&&*/ 00061 00062 00063 /* Pre calculate things used in multiple places */ 00064 00065 /* Bound the TPS ADC reading and shift it to start at zero */ 00066 unsigned short unboundedTPSADC = ADCArrays->TPS; 00067 if(unboundedTPSADC > fixedConfigs2.sensorRanges.TPSMaximumADC){ 00068 boundedTPSADC = TPSADCRange; 00069 }else if(unboundedTPSADC > fixedConfigs2.sensorRanges.TPSMinimumADC){ // force secondary config to be used... TODO remove this 00070 boundedTPSADC = unboundedTPSADC - fixedConfigs2.sensorRanges.TPSMinimumADC; 00071 }else{ 00072 boundedTPSADC = 0; 00073 } 00074 00075 00076 /* Get BRV from ADC using transfer variables (all installations need this) */ 00077 unsigned short localBRV; 00078 if(TRUE){ /* If BRV connected */ 00079 localBRV = (((unsigned long)ADCArrays->BRV * fixedConfigs2.sensorRanges.BRVRange) / ADC_DIVISIONS) + fixedConfigs2.sensorRanges.BRVMinimum; 00080 }else if(FALSE){ /* Configured to be fixed value */ 00081 /* Get the preferred BRV figure from configuration settings */ 00082 localBRV = fixedConfigs2.sensorPresets.presetBRV; 00083 }else{ /* Fail safe if config is broken */ 00084 /* Default to normal alternator charging voltage 14.4V */ 00085 localBRV = runningVoltage; 00086 /* If anyone is listening, let them know something is wrong */ 00087 sendErrorIfClear(BRV_NOT_CONFIGURED_CODE); 00088 } 00089 00090 00091 unsigned short localCHT; 00092 /* Get CHT from ADC using the transfer table (all installations need this) */ 00093 if(TRUE){ /* If CHT connected */ 00094 localCHT = CHTTransferTable[ADCArrays->CHT]; 00095 }else if(FALSE){ /* Configured to be read From ADC as dashpot */ 00096 /* Transfer the ADC reading to an engine temperature in a reasonable way */ 00097 localCHT = (ADCArrays->CHT * 10) + freezingPoint; /* 0 ADC = 0C = 273.15K = 27315, 1023 ADC = 102.3C = 375.45K = 37545 */ 00098 }else if(FALSE){ /* Configured to be fixed value */ 00099 /* Get the preferred CHT figure from configuration settings */ 00100 localCHT = fixedConfigs2.sensorPresets.presetCHT; 00101 }else{ /* Fail safe if config is broken */ 00102 /* Default to normal running temperature of 85C/358K */ 00103 localCHT = runningTemperature; 00104 /* If anyone is listening, let them know something is wrong */ 00105 sendErrorIfClear(CHT_NOT_CONFIGURED_CODE); 00106 } 00107 00108 00109 unsigned short localIAT; 00110 /* Get IAT from ADC using the transfer table (all installations need this) */ 00111 if(TRUE){ /* If IAT connected */ /* using false here causes iat to default to room temp, useful with heatsoaked OEM sensors like the Volvo's... */ 00112 localIAT = IATTransferTable[ADCArrays->IAT]; 00113 }else if(FALSE){ /* Configured to be read From ADC as dashpot */ 00114 /* Transfer the ADC reading to an air temperature in a reasonable way */ 00115 localIAT = (ADCArrays->IAT * 10) + 27315; /* 0 ADC = 0C = 273.15K = 27315, 1023 ADC = 102.3C = 375.45K = 37545 */ 00116 }else if(FALSE){ /* Configured to be fixed value */ 00117 /* Get the preferred IAT figure from configuration settings */ 00118 localIAT = fixedConfigs2.sensorPresets.presetIAT; 00119 }else{ /* Fail safe if config is broken */ 00120 /* Default to normal air temperature of 20C/293K */ 00121 localIAT = roomTemperature; 00122 /* If anyone is listening, let them know something is wrong */ 00123 sendErrorIfClear(IAT_NOT_CONFIGURED_CODE); 00124 } 00125 00126 00127 unsigned short localMAT; 00128 /* Determine the MAT reading for future calculations */ 00129 if(TRUE){ /* If MAT sensor is connected */ 00130 /* Get MAT from ADC using same transfer table as IAT (too much space to waste on having two) */ 00131 localMAT = IATTransferTable[ADCArrays->MAT]; 00132 }else if(FALSE){ /* Configured to be fixed value */ 00133 /* Get the preferred MAT figure from configuration settings */ 00134 localMAT = fixedConfigs2.sensorPresets.presetMAT; 00135 }else{ /* Fail safe if config is broken */ 00136 /* If not, default to same value as IAT */ 00137 localMAT = localIAT; 00138 /* If anyone is listening, let them know something is wrong */ 00139 sendErrorIfClear(MAT_NOT_CONFIGURED_CODE); 00140 } 00141 00142 00143 unsigned short localMAP; 00144 unsigned short localIAP; 00145 /* Determine the MAP pressure to use for future calculations */ 00146 if(TRUE){ /* If MAP sensor is connected */ 00147 /* get MAP from ADC using transfer variables */ 00148 localMAP = (((unsigned long)ADCArrays->MAP * fixedConfigs2.sensorRanges.MAPRange) / ADC_DIVISIONS) + fixedConfigs2.sensorRanges.MAPMinimum; 00149 if(TRUE){ /* If Intercooler boost sensor connected */ 00150 /* Get IAP from ADC using the same transfer variables as they both need to read the same range */ 00151 localIAP = (((unsigned long)ADCArrays->IAP * fixedConfigs2.sensorRanges.MAPRange) / ADC_DIVISIONS) + fixedConfigs2.sensorRanges.MAPMinimum; 00152 } 00153 }else if(FALSE){ /* Configured for MAP to imitate TPS signal */ 00154 /* Get MAP from TPS via conversion */ 00155 localMAP = (((unsigned long)boundedTPSADC * TPSMAPRange) / TPSADCRange) + fixedConfigs2.sensorRanges.TPSClosedMAP; 00156 }else if(FALSE){ /* Configured for dash potentiometer on ADC */ 00157 /* Get MAP from ADC via conversion to internal kPa figure where 1023ADC = 655kPa */ 00158 localMAP = ADCArrays->MAP << 6; 00159 if(TRUE){ /* If Intercooler boost sensor enabled */ 00160 /* Get IAP from ADC via conversion to internal kPa figure where 1023ADC = 655kPa */ 00161 localIAP = ADCArrays->IAP << 6; 00162 } 00163 }else if(FALSE){ /* Configured for fixed MAP from config */ 00164 /* Get the preferred MAP figure from configuration settings */ 00165 localMAP = fixedConfigs2.sensorPresets.presetMAP; 00166 }else{ /* Fail safe if config is broken */ 00167 /* Default to zero to nulify all other calcs and effectively cut fuel */ 00168 localMAP = 0; 00169 /* If anyone is listening, let them know something is wrong */ 00170 sendErrorIfClear(MAP_NOT_CONFIGURED_CODE); // or maybe queue it? 00171 } 00172 00173 00174 /* Determine MAF variable if required */ 00175 unsigned short localMAF = 0; // Default to zero as it is not required for anything except main PW calcs optionally 00176 if(TRUE){ 00177 localMAF = MAFTransferTable[ADCArrays->MAF]; 00178 } 00179 00180 unsigned short localAAP; 00181 /* Determine the Atmospheric pressure to use for future calculations */ 00182 if(TRUE){ /* Configured for second sensor to read AAP */ 00183 /* get AAP from ADC using separate vars to allow 115kPa sensor etc to be used */ 00184 localAAP = (((unsigned long)ADCArrays->AAP * fixedConfigs2.sensorRanges.AAPRange) / ADC_DIVISIONS) + fixedConfigs2.sensorRanges.AAPMinimum; 00185 }else if(FALSE){ /* Configured for dash potentiometer on ADC */ 00186 /* Get AAP from ADC via conversion to internal kPa figure where 1023ADC = 102.3kPa */ 00187 localAAP = ADCArrays->AAP * 10; 00188 }else if(FALSE){ /* Configured for fixed AAP reading from pre start */ 00189 /* Get the AAP reading as saved during startup */ 00190 localAAP = bootTimeAAP; /* This is populated pre start up */ 00191 }else if(FALSE){ /* Configured for fixed AAP from config */ 00192 /* Get the preferred AAP figure from configuration settings */ 00193 localAAP = fixedConfigs2.sensorPresets.presetAAP; 00194 }else{ /* Fail safe if config is broken */ 00195 /* Default to sea level */ 00196 localAAP = seaLevelKPa; /* 100kPa */ 00197 /* If anyone is listening, let them know something is wrong */ 00198 sendErrorIfClear(AAP_NOT_CONFIGURED_CODE); // or maybe queue it? 00199 } 00200 00201 00202 unsigned short localEGO; 00203 /* Get main Lambda reading */ 00204 if(TRUE){ /* If WBO2-1 is connected */ 00205 /* Get EGO from ADCs using transfer variables */ 00206 localEGO = (((unsigned long)ADCArrays->EGO * fixedConfigs2.sensorRanges.EGORange) / ADC_DIVISIONS) + fixedConfigs2.sensorRanges.EGOMinimum; 00207 }else if(FALSE){ /* Configured for fixed EGO from config */ 00208 /* Get the preferred EGO figure from configuration settings */ 00209 localEGO = fixedConfigs2.sensorPresets.presetEGO; 00210 }else{ /* Default value if not connected incase other things are misconfigured */ 00211 /* Default to stoichiometric */ 00212 localEGO = stoichiometricLambda; /* EGO / 32768 = Lambda */ 00213 /* If anyone is listening, let them know something is wrong */ 00214 sendErrorIfClear(EGO_NOT_CONFIGURED_CODE); // or maybe queue it? 00215 } 00216 00217 00218 unsigned short localEGO2; 00219 /* Get second Lambda reading */ 00220 if(TRUE){ /* If WBO2-2 is connected */ 00221 /* Get EGO2 from ADCs using same transfer variables as EGO */ 00222 localEGO2 = (((unsigned long)ADCArrays->EGO2 * fixedConfigs2.sensorRanges.EGORange) / ADC_DIVISIONS) + fixedConfigs2.sensorRanges.EGOMinimum; 00223 }else if(FALSE){ /* Configured for fixed EGO2 from config */ 00224 /* Get the preferred EGO2 figure from configuration settings */ 00225 localEGO2 = fixedConfigs2.sensorPresets.presetEGO2; 00226 }else{ /* Default value if not connected incase other things are misconfigured */ 00227 /* Default to stoichiometric */ 00228 localEGO2 = stoichiometricLambda; 00229 /* If anyone is listening, let them know something is wrong */ 00230 sendErrorIfClear(EGO2_NOT_CONFIGURED_CODE); // or maybe queue it? 00231 } 00232 00233 00234 unsigned short localTPS; 00235 /* Get TPS percentage */ 00236 if(TRUE){ /* If TPS is connected */ 00237 /* Get TPS from ADC no need to add TPS min as we know it is zero by definition */ 00238 localTPS = ((unsigned long)boundedTPSADC * TPS_RANGE_MAX) / TPSADCRange; 00239 }else if(FALSE){ /* Configured for TPS to imitate MAP signal */ 00240 /* Get TPS from MAP via conversion */ 00241 /* Box MAP signal down */ 00242 if(localTPS > fixedConfigs2.sensorRanges.TPSOpenMAP){ /* Greater than ~95kPa */ 00243 localTPS = TPS_RANGE_MAX; /* 64000/640 = 100% */ 00244 }else if(localTPS < fixedConfigs2.sensorRanges.TPSClosedMAP){ /* Less than ~30kPa */ 00245 localTPS = 0; 00246 }else{ /* Scale MAP range to TPS range */ 00247 localTPS = localMAP - fixedConfigs2.sensorRanges.TPSClosedMAP; 00248 } 00249 // get TPS from MAP no need to add TPS min as we know it is zero by definition 00250 localTPS = ((unsigned long)localTPS * TPS_RANGE_MAX) / (fixedConfigs2.sensorRanges.TPSOpenMAP - fixedConfigs2.sensorRanges.TPSClosedMAP); 00251 }else if(FALSE){ /* Configured for dash potentiometer on ADC */ 00252 /* Get TPS from ADC as shown : 1023 ADC = 100%, 0 ADC = 0% */ 00253 localTPS = ((unsigned long)ADCArrays->TPS * TPS_RANGE_MAX) / ADC_DIVISIONS; 00254 }else if(FALSE){ /* Configured for fixed TPS from config */ 00255 /* Get the preferred TPS figure from configuration settings */ 00256 localTPS = fixedConfigs2.sensorPresets.presetTPS; 00257 }else{ /* Fail safe if config is broken */ 00258 /* Default to 50% to not trigger any WOT or CT conditions */ 00259 localTPS = halfThrottle; 00260 /* If anyone is listening, let them know something is wrong */ 00261 sendErrorIfClear(TPS_NOT_CONFIGURED_CODE); // or maybe queue it? 00262 } 00263 00264 00265 /* Get RPM by locking out ISRs for a second and grabbing the Tooth logging data */ 00266 //atomic start 00267 // copy rpm data 00268 //atomic end 00269 00270 // Calculate RPM and delta RPM and delta delta RPM from data recorded 00271 CoreVars->RPM = *RPM; // temporary!! 00272 unsigned short localDRPM = 0; 00273 unsigned short localDDRPM = 0; 00274 00275 00276 /*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ 00277 00278 00279 00280 00281 /*&&&&&&&&&&&&&&&&&&&&&&&&&&&& Average the variables as per the configuration &&&&&&&&&&&&&&&&&&&&&&&&&&*/ 00282 /* Strictly speaking only the primary variables need to be averaged. After that, the derived ones are */ 00283 /* already averaged in a way. However, there may be some advantage to some short term averaging on the */ 00284 /* derived ones also, so it is something to look into later. */ 00285 00287 00288 // newVal var word ' the value from the ADC 00289 // smoothed var word ' a nicely smoothed result 00290 // 00291 // if newval > smoothed then 00292 // smoothed = smoothed + (newval - smoothed)/alpha 00293 // else 00294 // smoothed = smoothed - (smoothed - newval)/alpha 00295 // endif 00296 00297 // from : http://www.tigoe.net/pcomp/code/category/code/arduinowiring/41 00298 00299 // for now just copy them in. 00300 CoreVars->IAT = localIAT; 00301 CoreVars->CHT = localCHT; 00302 CoreVars->TPS = localTPS; 00303 CoreVars->EGO = localEGO; 00304 CoreVars->BRV = localBRV; 00305 CoreVars->MAP = localMAP; 00306 CoreVars->AAP = localAAP; 00307 CoreVars->MAT = localMAT; 00308 00309 CoreVars->EGO2 = localEGO2; 00310 CoreVars->IAP = localIAP; 00311 CoreVars->MAF = localMAF; 00312 CoreVars->DRPM = localDRPM; 00313 CoreVars->DDRPM = localDDRPM; 00314 00315 // later... 00316 unsigned short i; 00317 for(i=0;i<CORE_VARS_LENGTH;i++){ // TODO 00318 /* Perform averaging on all primary variables as per the configuration array */ 00319 // get old value(s) 00320 // process new and old to produce result based on config array value */ 00321 // assign result to old value holder 00322 } // TODO 00323 00324 /*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ 00325 }