Tiny fix found while looking for mistakes that might have been causing Mike trouble...
[freeems-vanilla.git] / src / coreVarsGenerator.c
blobb31732c4e368860d7bdaac79a939418d5da3a8ce
1 /* FreeEMS - the open source engine management system
3 * Copyright 2008-2012 Fred Cooke
5 * This file is part of the FreeEMS project.
7 * FreeEMS software is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation, either version 3 of the License, or
10 * (at your option) any later version.
12 * FreeEMS software is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with any FreeEMS software. If not, see http://www.gnu.org/licenses/
20 * We ask that if you make any changes to this file you email them upstream to
21 * us at admin(at)diyefi(dot)org or, even better, fork the code on github.com!
23 * Thank you for choosing FreeEMS to run your engine!
27 /** @file
29 * @ingroup measurementsAndCalculations
31 * @brief Generate and average the core variables.
33 * This file contains the function that transfers the raw ADC values to actual
34 * physical measurements and averages them.
36 * @author Fred Cooke
40 #define COREVARSGENERATOR_C
41 #include "inc/freeEMS.h"
42 #include "inc/commsCore.h"
43 #include "inc/coreVarsGenerator.h"
44 #include "inc/decoderInterface.h"
47 /** @brief Generate the core variables and average them.
49 * Each raw ADC value is converted to a usable measurement via a variety of
50 * methods chosen at runtime by configured settings. Once in their native units
51 * and therefore closer to maximal use of the available data range they are
52 * all averaged.
54 * @todo TODO incorporate averaging code, right now its a straight copy.
55 * @todo TODO change the way configuration is done and make sure the most common options are after the first if().
56 * @todo TODO add actual configuration options to the fixed config blocks for these items.
58 * @author Fred Cooke
60 void generateCoreVars(){
61 /*&&&&&&&& Calculate and obtain the basic variables with which we will perform the calculations &&&&&&&&*/
64 /* Pre calculate things used in multiple places */
66 /* Bound the TPS ADC reading and shift it to start at zero */
67 unsigned short unboundedTPSADC = ADCBuffers->TPS;
68 if(unboundedTPSADC > fixedConfigs2.sensorRanges.TPSMaximumADC){
69 boundedTPSADC = TPSADCRange;
70 }else if(unboundedTPSADC > fixedConfigs2.sensorRanges.TPSMinimumADC){ // force secondary config to be used... TODO remove this
71 boundedTPSADC = unboundedTPSADC - fixedConfigs2.sensorRanges.TPSMinimumADC;
72 }else{
73 boundedTPSADC = 0;
77 /* Get BRV from ADC using transfer variables (all installations need this) */
78 unsigned short localBRV;
79 if(TRUE){ /* If BRV connected */
80 /// @todo TODO WARNING: HACK!!! Remove ASAP!!! IE, As Soon As Preston (get's a new cpu on the TA card!)
81 #ifdef HOTEL
82 localBRV = (((unsigned long)ADCBuffers->MAT * fixedConfigs2.sensorRanges.BRVRange) / ADC_DIVISIONS) + fixedConfigs2.sensorRanges.BRVMinimum;
83 #else
84 localBRV = (((unsigned long)ADCBuffers->BRV * fixedConfigs2.sensorRanges.BRVRange) / ADC_DIVISIONS) + fixedConfigs2.sensorRanges.BRVMinimum;
85 #endif
86 }else if(FALSE){ /* Configured to be fixed value */
87 /* Get the preferred BRV figure from configuration settings */
88 localBRV = fixedConfigs2.sensorPresets.presetBRV;
89 }else{ /* Fail safe if config is broken */
90 /* Default to normal alternator charging voltage 14.4V */
91 localBRV = VOLTS(14.4);
92 /* If anyone is listening, let them know something is wrong */
93 sendErrorIfClear(BRV_NOT_CONFIGURED_CODE);
97 unsigned short localCHT;
98 /* Get CHT from ADC using the transfer table (all installations need this) */
99 if(TRUE){ /* If CHT connected */
100 localCHT = CHTTransferTable[ADCBuffers->CHT];
101 }else if(FALSE){ /* Configured to be read From ADC as dashpot */
102 /* Transfer the ADC reading to an engine temperature in a reasonable way */
103 localCHT = (ADCBuffers->CHT * 10) + DEGREES_C(0); /* 0 ADC = 0C = 273.15K = 27315, 1023 ADC = 102.3C = 375.45K = 37545 */
104 }else if(FALSE){ /* Configured to be fixed value */
105 /* Get the preferred CHT figure from configuration settings */
106 localCHT = fixedConfigs2.sensorPresets.presetCHT;
107 }else{ /* Fail safe if config is broken */
108 /* Default to normal running temperature of 85C/358K */
109 localCHT = DEGREES_C(85);
110 /* If anyone is listening, let them know something is wrong */
111 sendErrorIfClear(CHT_NOT_CONFIGURED_CODE);
115 unsigned short localIAT;
116 /* Get IAT from ADC using the transfer table (all installations need this) */
117 if(TRUE){ /* If IAT connected */ /* using false here causes iat to default to room temp, useful with heatsoaked OEM sensors like the Volvo's... */
118 localIAT = IATTransferTable[ADCBuffers->IAT];
119 }else if(FALSE){ /* Configured to be read From ADC as dashpot */
120 /* Transfer the ADC reading to an air temperature in a reasonable way */
121 localIAT = (ADCBuffers->IAT * 10) + 27315; /* 0 ADC = 0C = 273.15K = 27315, 1023 ADC = 102.3C = 375.45K = 37545 */
122 }else if(FALSE){ /* Configured to be fixed value */
123 /* Get the preferred IAT figure from configuration settings */
124 localIAT = fixedConfigs2.sensorPresets.presetIAT;
125 }else{ /* Fail safe if config is broken */
126 /* Default to room temperature (20C/293K) TODO poor choice, fix. */
127 localIAT = DEGREES_C(20);
128 /* If anyone is listening, let them know something is wrong */
129 sendErrorIfClear(IAT_NOT_CONFIGURED_CODE);
133 unsigned short localMAT;
134 /* Determine the MAT reading for future calculations */
135 if(TRUE){ /* If MAT sensor is connected */
136 /* Get MAT from ADC using same transfer table as IAT (too much space to waste on having two) */
137 localMAT = IATTransferTable[ADCBuffers->MAT];
138 }else if(FALSE){ /* Configured to be fixed value */
139 /* Get the preferred MAT figure from configuration settings */
140 localMAT = fixedConfigs2.sensorPresets.presetMAT;
141 }else{ /* Fail safe if config is broken */
142 /* If not, default to same value as IAT */
143 localMAT = localIAT;
144 /* If anyone is listening, let them know something is wrong */
145 sendErrorIfClear(MAT_NOT_CONFIGURED_CODE);
149 unsigned short localMAP;
150 unsigned short localIAP;
151 /* Determine the MAP pressure to use for future calculations */
152 if(TRUE){ /* If MAP sensor is connected */
153 /* get MAP from ADC using transfer variables */
154 localMAP = (((unsigned long)ADCBuffers->MAP * fixedConfigs2.sensorRanges.MAPRange) / ADC_DIVISIONS) + fixedConfigs2.sensorRanges.MAPMinimum;
155 if(TRUE){ /* If Intercooler boost sensor connected */
156 /* Get IAP from ADC using the same transfer variables as they both need to read the same range */
157 localIAP = (((unsigned long)ADCBuffers->IAP * fixedConfigs2.sensorRanges.MAPRange) / ADC_DIVISIONS) + fixedConfigs2.sensorRanges.MAPMinimum;
159 }else if(FALSE){ /* Configured for MAP to imitate TPS signal */
160 /* Get MAP from TPS via conversion */
161 localMAP = (((unsigned long)boundedTPSADC * TPSMAPRange) / TPSADCRange) + fixedConfigs2.sensorRanges.TPSClosedMAP;
162 }else if(FALSE){ /* Configured for dash potentiometer on ADC */
163 /* Get MAP from ADC via conversion to internal kPa figure where 1023ADC = 655kPa */
164 localMAP = ADCBuffers->MAP << 6;
165 if(TRUE){ /* If Intercooler boost sensor enabled */
166 /* Get IAP from ADC via conversion to internal kPa figure where 1023ADC = 655kPa */
167 localIAP = ADCBuffers->IAP << 6;
169 }else if(FALSE){ /* Configured for fixed MAP from config */
170 /* Get the preferred MAP figure from configuration settings */
171 localMAP = fixedConfigs2.sensorPresets.presetMAP;
172 }else{ /* Fail safe if config is broken */
173 /* Default to zero to nulify all other calcs and effectively cut fuel */
174 localMAP = 0;
175 /* If anyone is listening, let them know something is wrong */
176 sendErrorIfClear(MAP_NOT_CONFIGURED_CODE); // or maybe queue it?
180 /* Determine MAF variable if required */
181 unsigned short localMAF = 0; // Default to zero as it is not required for anything except main PW calcs optionally
182 if(TRUE){
183 localMAF = MAFTransferTable[ADCBuffers->MAF];
186 unsigned short localAAP;
187 /* Determine the Atmospheric pressure to use for future calculations */
188 if(TRUE){ /* Configured for second sensor to read AAP */
189 /* get AAP from ADC using separate vars to allow 115kPa sensor etc to be used */
190 localAAP = (((unsigned long)ADCBuffers->AAP * fixedConfigs2.sensorRanges.AAPRange) / ADC_DIVISIONS) + fixedConfigs2.sensorRanges.AAPMinimum;
191 }else if(FALSE){ /* Configured for dash potentiometer on ADC */
192 /* Get AAP from ADC via conversion to internal kPa figure where 1023ADC = 102.3kPa */
193 localAAP = ADCBuffers->AAP * 10;
194 }else if(FALSE){ /* Configured for fixed AAP from config */
195 /* Get the preferred AAP figure from configuration settings */
196 localAAP = fixedConfigs2.sensorPresets.presetAAP;
197 }else{ /* Fail safe if config is broken */
198 /* Default to sea level */
199 localAAP = KPA(100);
200 /* If anyone is listening, let them know something is wrong */
201 sendErrorIfClear(AAP_NOT_CONFIGURED_CODE); // or maybe queue it?
205 unsigned short localEGO;
206 /* Get main Lambda reading */
207 if(TRUE){ /* If WBO2-1 is connected */
208 /* Get EGO from ADCs using transfer variables */
209 localEGO = (((unsigned long)ADCBuffers->EGO * fixedConfigs2.sensorRanges.EGORange) / ADC_DIVISIONS) + fixedConfigs2.sensorRanges.EGOMinimum;
210 }else if(FALSE){ /* Configured for fixed EGO from config */
211 /* Get the preferred EGO figure from configuration settings */
212 localEGO = fixedConfigs2.sensorPresets.presetEGO;
213 }else{ /* Default value if not connected incase other things are misconfigured */
214 /* Default to stoichiometric */
215 localEGO = LAMBDA(1.0);
216 /* If anyone is listening, let them know something is wrong */
217 sendErrorIfClear(EGO_NOT_CONFIGURED_CODE); // or maybe queue it?
221 unsigned short localEGO2;
222 /* Get second Lambda reading */
223 if(TRUE){ /* If WBO2-2 is connected */
224 /* Get EGO2 from ADCs using same transfer variables as EGO */
225 localEGO2 = (((unsigned long)ADCBuffers->EGO2 * fixedConfigs2.sensorRanges.EGORange) / ADC_DIVISIONS) + fixedConfigs2.sensorRanges.EGOMinimum;
226 }else if(FALSE){ /* Configured for fixed EGO2 from config */
227 /* Get the preferred EGO2 figure from configuration settings */
228 localEGO2 = fixedConfigs2.sensorPresets.presetEGO2;
229 }else{ /* Default value if not connected incase other things are misconfigured */
230 /* Default to stoichiometric */
231 localEGO2 = LAMBDA(1.0);
232 /* If anyone is listening, let them know something is wrong */
233 sendErrorIfClear(EGO2_NOT_CONFIGURED_CODE); // or maybe queue it?
237 unsigned short localTPS;
238 /* Get TPS percentage */
239 if(TRUE){ /* If TPS is connected */
240 /* Get TPS from ADC no need to add TPS min as we know it is zero by definition */
241 localTPS = ((unsigned long)boundedTPSADC * PERCENT(100)) / TPSADCRange;
242 }else if(FALSE){ /* Configured for TPS to imitate MAP signal */
243 /* Get TPS from MAP via conversion */
244 /* Box MAP signal down */
245 if(localTPS > fixedConfigs2.sensorRanges.TPSOpenMAP){ /* Greater than ~95kPa */
246 localTPS = PERCENT(100);
247 }else if(localTPS < fixedConfigs2.sensorRanges.TPSClosedMAP){ /* Less than ~30kPa */
248 localTPS = 0;
249 }else{ /* Scale MAP range to TPS range */
250 localTPS = localMAP - fixedConfigs2.sensorRanges.TPSClosedMAP;
252 // get TPS from MAP no need to add TPS min as we know it is zero by definition
253 localTPS = ((unsigned long)localTPS * PERCENT(100)) / (fixedConfigs2.sensorRanges.TPSOpenMAP - fixedConfigs2.sensorRanges.TPSClosedMAP);
254 }else if(FALSE){ /* Configured for dash potentiometer on ADC */
255 /* Get TPS from ADC as shown : 1023 ADC = 100%, 0 ADC = 0% */
256 localTPS = ((unsigned long)ADCBuffers->TPS * PERCENT(100)) / ADC_DIVISIONS;
257 }else if(FALSE){ /* Configured for fixed TPS from config */
258 /* Get the preferred TPS figure from configuration settings */
259 localTPS = fixedConfigs2.sensorPresets.presetTPS;
260 }else{ /* Fail safe if config is broken */
261 /* Default to 50% to not trigger any WOT or CT conditions */
262 localTPS = PERCENT(50); // TODO YAGNI?
263 /* If anyone is listening, let them know something is wrong */
264 sendErrorIfClear(TPS_NOT_CONFIGURED_CODE); // or maybe queue it?
268 /* Get RPM by locking out ISRs for a second and grabbing the Tooth logging data */
269 //atomic start
270 // copy rpm data
271 //atomic end
273 // Calculate RPM and delta RPM and delta delta RPM from data recorded
274 if(*ticksPerDegree != 0){
275 CoreVars->RPM = (unsigned short)(degreeTicksPerMinute / *ticksPerDegree);
276 }else{
277 CoreVars->RPM = 0;
280 CoreVars->DRPM = *ticksPerDegree;
281 // unsigned short localDRPM = 0;
282 // unsigned short localDDRPM = 0;
285 /*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
290 /*&&&&&&&&&&&&&&&&&&&&&&&&&&&& Average the variables as per the configuration &&&&&&&&&&&&&&&&&&&&&&&&&&*/
291 /* Strictly speaking only the primary variables need to be averaged. After that, the derived ones are */
292 /* already averaged in a way. However, there may be some advantage to some short term averaging on the */
293 /* derived ones also, so it is something to look into later. */
295 /// @todo TODO average the generated values here
297 // newVal var word ' the value from the ADC
298 // smoothed var word ' a nicely smoothed result
300 // if newval > smoothed then
301 // smoothed = smoothed + (newval - smoothed)/alpha
302 // else
303 // smoothed = smoothed - (smoothed - newval)/alpha
304 // endif
306 // from : http://www.tigoe.net/pcomp/code/category/code/arduinowiring/41
308 // for now just copy them in.
309 CoreVars->IAT = localIAT;
310 CoreVars->CHT = localCHT;
311 CoreVars->TPS = localTPS;
312 CoreVars->EGO = localEGO;
313 CoreVars->BRV = localBRV;
314 CoreVars->MAP = localMAP;
315 CoreVars->AAP = localAAP;
316 CoreVars->MAT = localMAT;
318 CoreVars->EGO2 = localEGO2;
319 CoreVars->IAP = localIAP;
320 CoreVars->MAF = localMAF;
321 // CoreVars->DRPM = localDRPM;
322 // CoreVars->DDRPM = localDDRPM;
323 // CoreVars->DTPS = localDTPS;
325 // later...
326 unsigned short i;
327 for(i=0;i<sizeof(CoreVar);i++){ // TODO
328 /* Perform averaging on all primary variables as per the configuration array */
329 // get old value(s)
330 // process new and old to produce result based on config array value */
331 // assign result to old value holder
332 } // TODO
334 /*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/