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