2016-03-08 21:40:11 -08:00
/*
Speeduino - Simple engine management for the Arduino Mega 2560 platform
Copyright ( C ) Josh Stewart
A full copy of the license may be found in the projects root directory
*/
2017-01-17 22:37:55 -08:00
# include "sensors.h"
2016-06-10 05:38:05 -07:00
2016-11-17 17:57:11 -08:00
void initialiseADC ( )
{
# if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega1281__) || defined(__AVR_ATmega2560__) || defined(__AVR_ATmega2561__) //AVR chips use the ISR for this
# if defined(ANALOG_ISR)
//This sets the ADC (Analog to Digitial Converter) to run at 250KHz, greatly reducing analog read times (MAP/TPS)
//the code on ISR run each conversion every 25 ADC clock, conversion run about 100KHz effectively
//making a 6250 conversions/s on 16 channels and 12500 on 8 channels devices.
noInterrupts ( ) ; //Interrupts should be turned off when playing with any of these registers
2017-02-08 19:17:20 -08:00
2016-11-17 17:57:11 -08:00
ADCSRB = 0x00 ; //ADC Auto Trigger Source is in Free Running mode
ADMUX = 0x40 ; //Select AREF as reference, ADC Left Adjust Result, Starting at channel 0
//All of the below is the longhand version of: ADCSRA = 0xEE;
# define ADFR 5 //Why the HELL isn't this defined in the same place as everything else (wiring.h)?!?!
BIT_SET ( ADCSRA , ADFR ) ; //Set free running mode
BIT_SET ( ADCSRA , ADIE ) ; //Set ADC interrupt enabled
BIT_CLEAR ( ADCSRA , ADIF ) ; //Clear interrupt flag
2016-11-17 18:42:51 -08:00
// Set ADC clock to 125KHz (Prescaler = 128)
2016-11-17 17:57:11 -08:00
BIT_SET ( ADCSRA , ADPS2 ) ;
BIT_SET ( ADCSRA , ADPS1 ) ;
BIT_SET ( ADCSRA , ADPS0 ) ;
2017-02-08 19:17:20 -08:00
2016-11-17 17:57:11 -08:00
BIT_SET ( ADCSRA , ADEN ) ; //Enable ADC
2017-02-08 19:17:20 -08:00
2016-11-17 17:57:11 -08:00
interrupts ( ) ;
BIT_SET ( ADCSRA , ADSC ) ; //Start conversion
2017-02-08 19:17:20 -08:00
2016-11-17 17:57:11 -08:00
# else
2016-11-17 18:42:51 -08:00
//This sets the ADC (Analog to Digitial Converter) to run at 1Mhz, greatly reducing analog read times (MAP/TPS) when using the standard analogRead() function
2016-11-17 17:57:11 -08:00
//1Mhz is the fastest speed permitted by the CPU without affecting accuracy
2016-11-17 18:42:51 -08:00
//Please see chapter 11 of 'Practical Arduino' (http://books.google.com.au/books?id=HsTxON1L6D4C&printsec=frontcover#v=onepage&q&f=false) for more detail
2016-11-17 17:57:11 -08:00
BIT_SET ( ADCSRA , ADPS2 ) ;
BIT_CLEAR ( ADCSRA , ADPS1 ) ;
BIT_CLEAR ( ADCSRA , ADPS0 ) ;
# endif
2018-04-10 15:17:38 -07:00
# elif defined(ARDUINO_ARCH_STM32) //STM32GENERIC lib
analogReadResolution ( 10 ) ; //use 10bits for analog
2016-11-17 17:57:11 -08:00
# endif
2017-10-10 06:12:07 -07:00
MAPcurRev = 0 ;
MAPcount = 0 ;
MAPrunningValue = 0 ;
2016-11-17 17:57:11 -08:00
}
2017-11-07 03:05:23 -08:00
static inline void instanteneousMAPReading ( )
2016-03-08 21:40:11 -08:00
{
2017-07-02 18:52:27 -07:00
unsigned int tempReading ;
2016-03-08 21:40:11 -08:00
//Instantaneous MAP readings
2017-06-28 21:34:47 -07:00
# if defined(ANALOG_ISR_MAP)
2016-11-06 05:31:18 -08:00
tempReading = AnChannel [ pinMAP - A0 ] ;
# else
tempReading = analogRead ( pinMAP ) ;
tempReading = analogRead ( pinMAP ) ;
2017-02-08 19:17:20 -08:00
# endif
2016-03-08 21:40:11 -08:00
//Error checking
2017-06-28 21:34:47 -07:00
if ( ( tempReading > = VALID_MAP_MAX ) | | ( tempReading < = VALID_MAP_MIN ) ) { mapErrorCount + = 1 ; }
2017-02-11 17:43:18 -08:00
else { mapErrorCount = 0 ; }
2017-02-08 19:17:20 -08:00
2017-07-29 21:25:07 -07:00
//During startup a call is made here to get the baro reading. In this case, we can't apply the ADC filter
if ( initialisationComplete = = true ) { currentStatus . mapADC = ADC_FILTER ( tempReading , ADCFILTER_MAP , currentStatus . mapADC ) ; } //Very weak filter
else { currentStatus . mapADC = tempReading ; } //Baro reading (No filter)
2017-04-20 23:33:24 -07:00
2018-01-23 17:05:50 -08:00
currentStatus . MAP = fastMap10Bit ( currentStatus . mapADC , configPage2 . mapMin , configPage2 . mapMax ) ; //Get the current MAP value
2017-07-26 19:47:59 -07:00
if ( currentStatus . MAP < 0 ) { currentStatus . MAP = 0 ; } //Sanity check
2017-04-20 23:33:24 -07:00
2016-03-08 21:40:11 -08:00
}
2017-11-07 03:05:23 -08:00
static inline void readMAP ( )
2016-03-08 21:40:11 -08:00
{
2017-07-02 18:52:27 -07:00
unsigned int tempReading ;
2016-06-10 05:38:05 -07:00
//MAP Sampling system
2018-01-23 17:05:50 -08:00
switch ( configPage2 . mapSample )
2016-06-10 05:38:05 -07:00
{
case 0 :
//Instantaneous MAP readings
instanteneousMAPReading ( ) ;
break ;
2017-02-08 19:17:20 -08:00
2016-06-10 05:38:05 -07:00
case 1 :
//Average of a cycle
2017-02-08 19:17:20 -08:00
2017-06-28 21:34:47 -07:00
if ( ( currentStatus . RPM > 0 ) & & ( currentStatus . hasSync = = true ) ) //If the engine isn't running, fall back to instantaneous reads
2016-06-10 05:38:05 -07:00
{
2017-06-28 21:34:47 -07:00
if ( ( MAPcurRev = = currentStatus . startRevolutions ) | | ( MAPcurRev = = ( currentStatus . startRevolutions + 1 ) ) ) //2 revolutions are looked at for 4 stroke. 2 stroke not currently catered for.
2016-03-08 21:40:11 -08:00
{
2017-06-28 21:34:47 -07:00
# if defined(ANALOG_ISR_MAP)
tempReading = AnChannel [ pinMAP - A0 ] ;
# else
tempReading = analogRead ( pinMAP ) ;
tempReading = analogRead ( pinMAP ) ;
# endif
//Error check
if ( ( tempReading < VALID_MAP_MAX ) & & ( tempReading > VALID_MAP_MIN ) )
{
2017-08-20 18:50:50 -07:00
currentStatus . mapADC = ADC_FILTER ( tempReading , ADCFILTER_MAP , currentStatus . mapADC ) ;
MAPrunningValue + = currentStatus . mapADC ; //Add the current reading onto the total
2017-06-28 21:34:47 -07:00
MAPcount + + ;
}
else { mapErrorCount + = 1 ; }
2018-04-24 04:31:52 -07:00
//Repeat for EMAP if it's enabled
if ( configPage6 . useEMAP = = true )
{
tempReading = analogRead ( pinEMAP ) ;
tempReading = analogRead ( pinEMAP ) ;
//Error check
if ( ( tempReading < VALID_MAP_MAX ) & & ( tempReading > VALID_MAP_MIN ) )
{
currentStatus . EMAPADC = ADC_FILTER ( tempReading , ADCFILTER_MAP , currentStatus . EMAPADC ) ;
EMAPrunningValue + = currentStatus . EMAPADC ; //Add the current reading onto the total
}
else { mapErrorCount + = 1 ; }
}
2017-06-28 21:34:47 -07:00
}
else
{
//Reaching here means that the last cylce has completed and the MAP value should be calculated
//Sanity check
if ( ( MAPrunningValue ! = 0 ) & & ( MAPcount ! = 0 ) )
{
currentStatus . mapADC = ldiv ( MAPrunningValue , MAPcount ) . quot ;
2018-01-23 17:05:50 -08:00
currentStatus . MAP = fastMap10Bit ( currentStatus . mapADC , configPage2 . mapMin , configPage2 . mapMax ) ; //Get the current MAP value
2017-07-26 19:47:59 -07:00
if ( currentStatus . MAP < 0 ) { currentStatus . MAP = 0 ; } //Sanity check
2018-04-24 04:31:52 -07:00
//If EMAP is enabled, the process is identical to the above
if ( configPage6 . useEMAP = = true )
{
currentStatus . EMAPADC = ldiv ( EMAPrunningValue , MAPcount ) . quot ; //Note that the MAP count can be reused here as it will always be the same count.
currentStatus . EMAP = fastMap10Bit ( currentStatus . EMAPADC , configPage2 . EMAPMin , configPage2 . EMAPMax ) ;
if ( currentStatus . EMAP < 0 ) { currentStatus . EMAP = 0 ; } //Sanity check
}
2017-06-28 21:34:47 -07:00
}
else { instanteneousMAPReading ( ) ; }
2017-10-11 00:54:42 -07:00
MAPcurRev = currentStatus . startRevolutions ; //Reset the current rev count
MAPrunningValue = 0 ;
2018-04-24 04:31:52 -07:00
EMAPrunningValue = 0 ; //Can reset this even if EMAP not used
2017-10-11 00:54:42 -07:00
MAPcount = 0 ;
2016-03-08 21:40:11 -08:00
}
2016-06-10 05:38:05 -07:00
}
2017-06-28 21:34:47 -07:00
else { instanteneousMAPReading ( ) ; }
2016-06-10 05:38:05 -07:00
break ;
2017-02-08 19:17:20 -08:00
2016-06-10 05:38:05 -07:00
case 2 :
//Minimum reading in a cycle
2017-06-28 21:34:47 -07:00
if ( currentStatus . RPM > 0 ) //If the engine isn't running, fall back to instantaneous reads
2016-06-10 05:38:05 -07:00
{
2017-06-28 21:34:47 -07:00
if ( ( MAPcurRev = = currentStatus . startRevolutions ) | | ( MAPcurRev = = ( currentStatus . startRevolutions + 1 ) ) ) //2 revolutions are looked at for 4 stroke. 2 stroke not currently catered for.
2016-03-08 21:40:11 -08:00
{
2017-06-28 21:34:47 -07:00
# if defined(ANALOG_ISR_MAP)
tempReading = AnChannel [ pinMAP - A0 ] ;
# else
tempReading = analogRead ( pinMAP ) ;
tempReading = analogRead ( pinMAP ) ;
# endif
//Error check
if ( ( tempReading < VALID_MAP_MAX ) & & ( tempReading > VALID_MAP_MIN ) )
{
if ( ( unsigned long ) tempReading < MAPrunningValue ) { MAPrunningValue = ( unsigned long ) tempReading ; } //Check whether the current reading is lower than the running minimum
}
else { mapErrorCount + = 1 ; }
}
else
{
//Reaching here means that the last cylce has completed and the MAP value should be calculated
currentStatus . mapADC = MAPrunningValue ;
2018-01-23 17:05:50 -08:00
currentStatus . MAP = fastMap10Bit ( currentStatus . mapADC , configPage2 . mapMin , configPage2 . mapMax ) ; //Get the current MAP value
2017-07-26 19:47:59 -07:00
if ( currentStatus . MAP < 0 ) { currentStatus . MAP = 0 ; } //Sanity check
2017-06-28 21:34:47 -07:00
MAPcurRev = currentStatus . startRevolutions ; //Reset the current rev count
MAPrunningValue = 1023 ; //Reset the latest value so the next reading will always be lower
2016-03-08 21:40:11 -08:00
}
2016-06-10 05:38:05 -07:00
}
2017-06-28 21:34:47 -07:00
else { instanteneousMAPReading ( ) ; }
2016-06-10 05:38:05 -07:00
break ;
2017-06-28 21:34:47 -07:00
default :
//Instantaneous MAP readings (Just in case)
instanteneousMAPReading ( ) ;
break ;
2016-06-10 05:38:05 -07:00
}
2016-03-08 21:40:11 -08:00
}
2016-03-23 04:09:04 -07:00
void readTPS ( )
{
2016-06-10 05:38:05 -07:00
currentStatus . TPSlast = currentStatus . TPS ;
currentStatus . TPSlast_time = currentStatus . TPS_time ;
2017-02-08 19:17:20 -08:00
# if defined(ANALOG_ISR)
2016-11-06 05:31:18 -08:00
byte tempTPS = fastMap1023toX ( AnChannel [ pinTPS - A0 ] , 255 ) ; //Get the current raw TPS ADC value and map it into a byte
# else
analogRead ( pinTPS ) ;
byte tempTPS = fastMap1023toX ( analogRead ( pinTPS ) , 255 ) ; //Get the current raw TPS ADC value and map it into a byte
# endif
2016-06-10 05:38:05 -07:00
currentStatus . tpsADC = ADC_FILTER ( tempTPS , ADCFILTER_TPS , currentStatus . tpsADC ) ;
byte tempADC = currentStatus . tpsADC ; //The tempADC value is used in order to allow TunerStudio to recover and redo the TPS calibration if this somehow gets corrupted
2018-06-16 19:20:09 -07:00
if ( configPage2 . tpsMax > configPage2 . tpsMin )
{
//Check that the ADC values fall within the min and max ranges (Should always be the case, but noise can cause these to fluctuate outside the defined range).
if ( currentStatus . tpsADC < configPage2 . tpsMin ) { tempADC = configPage2 . tpsMin ; }
else if ( currentStatus . tpsADC > configPage2 . tpsMax ) { tempADC = configPage2 . tpsMax ; }
currentStatus . TPS = map ( tempADC , configPage2 . tpsMin , configPage2 . tpsMax , 0 , 100 ) ; //Take the raw TPS ADC value and convert it into a TPS% based on the calibrated values
}
else
{
//This case occurs when the TPS +5v and gnd are wired backwards, but the user wishes to retain this configuration.
//In such a case, tpsMin will be greater then tpsMax and hence checks and mapping needs to be reversed
tempADC = 255 - currentStatus . tpsADC ; //Reverse the ADC values
//All checks below are reversed from the standard case above
if ( tempADC > configPage2 . tpsMin ) { tempADC = configPage2 . tpsMin ; }
else if ( tempADC < configPage2 . tpsMax ) { tempADC = configPage2 . tpsMax ; }
currentStatus . TPS = map ( tempADC , configPage2 . tpsMax , configPage2 . tpsMin , 0 , 100 ) ;
}
2017-02-08 19:17:20 -08:00
currentStatus . TPS_time = currentLoopTime ;
2016-03-23 04:09:04 -07:00
}
void readCLT ( )
{
2017-07-02 18:52:27 -07:00
unsigned int tempReading ;
2017-02-08 19:17:20 -08:00
# if defined(ANALOG_ISR)
2016-11-06 05:31:18 -08:00
tempReading = fastMap1023toX ( AnChannel [ pinCLT - A0 ] , 511 ) ; //Get the current raw CLT value
# else
tempReading = analogRead ( pinCLT ) ;
tempReading = fastMap1023toX ( analogRead ( pinCLT ) , 511 ) ; //Get the current raw CLT value
# endif
2016-06-10 05:38:05 -07:00
currentStatus . cltADC = ADC_FILTER ( tempReading , ADCFILTER_CLT , currentStatus . cltADC ) ;
currentStatus . coolant = cltCalibrationTable [ currentStatus . cltADC ] - CALIBRATION_TEMPERATURE_OFFSET ; //Temperature calibration values are stored as positive bytes. We subtract 40 from them to allow for negative temperatures
2016-03-23 04:09:04 -07:00
}
void readIAT ( )
{
2017-07-02 18:52:27 -07:00
unsigned int tempReading ;
2017-02-08 19:17:20 -08:00
# if defined(ANALOG_ISR)
2016-11-06 05:31:18 -08:00
tempReading = fastMap1023toX ( AnChannel [ pinIAT - A0 ] , 511 ) ; //Get the current raw IAT value
# else
tempReading = analogRead ( pinIAT ) ;
tempReading = fastMap1023toX ( analogRead ( pinIAT ) , 511 ) ; //Get the current raw IAT value
# endif
2016-06-10 05:38:05 -07:00
currentStatus . iatADC = ADC_FILTER ( tempReading , ADCFILTER_IAT , currentStatus . iatADC ) ;
currentStatus . IAT = iatCalibrationTable [ currentStatus . iatADC ] - CALIBRATION_TEMPERATURE_OFFSET ;
2016-03-23 04:09:04 -07:00
}
2017-07-17 00:06:14 -07:00
void readBaro ( )
{
2018-01-23 17:05:50 -08:00
if ( configPage6 . useExtBaro ! = 0 )
2017-07-17 00:06:14 -07:00
{
int tempReading ;
// readings
# if defined(ANALOG_ISR_MAP)
tempReading = AnChannel [ pinBaro - A0 ] ;
# else
tempReading = analogRead ( pinBaro ) ;
tempReading = analogRead ( pinBaro ) ;
# endif
currentStatus . baroADC = ADC_FILTER ( tempReading , ADCFILTER_BARO , currentStatus . baroADC ) ; //Very weak filter
2018-01-23 17:05:50 -08:00
currentStatus . baro = fastMap10Bit ( currentStatus . baroADC , configPage2 . baroMin , configPage2 . baroMax ) ; //Get the current MAP value
2017-07-17 00:06:14 -07:00
}
}
2016-03-23 04:09:04 -07:00
void readO2 ( )
{
2017-07-02 18:52:27 -07:00
unsigned int tempReading ;
2017-02-08 19:17:20 -08:00
# if defined(ANALOG_ISR)
tempReading = fastMap1023toX ( AnChannel [ pinO2 - A0 ] , 511 ) ; //Get the current O2 value.
2016-11-06 05:31:18 -08:00
# else
tempReading = analogRead ( pinO2 ) ;
2017-02-08 19:17:20 -08:00
tempReading = fastMap1023toX ( analogRead ( pinO2 ) , 511 ) ; //Get the current O2 value.
2016-11-06 05:31:18 -08:00
# endif
2016-06-10 05:38:05 -07:00
currentStatus . O2ADC = ADC_FILTER ( tempReading , ADCFILTER_O2 , currentStatus . O2ADC ) ;
currentStatus . O2 = o2CalibrationTable [ currentStatus . O2ADC ] ;
2016-03-23 04:09:04 -07:00
}
2017-02-08 19:17:20 -08:00
2018-04-05 14:11:58 -07:00
void readO2_2 ( )
{
2017-06-28 21:34:47 -07:00
//Second O2 currently disabled as its not being used
//Get the current O2 value.
2018-04-05 14:11:58 -07:00
unsigned int tempReading ;
# if defined(ANALOG_ISR)
tempReading = fastMap1023toX ( AnChannel [ pinO2_2 - A0 ] , 511 ) ; //Get the current O2 value.
# else
tempReading = analogRead ( pinO2_2 ) ;
tempReading = fastMap1023toX ( analogRead ( pinO2_2 ) , 511 ) ; //Get the current O2 value.
# endif
2018-04-05 13:37:28 -07:00
currentStatus . O2_2ADC = ADC_FILTER ( tempReading , ADCFILTER_O2 , currentStatus . O2_2ADC ) ;
currentStatus . O2_2 = o2CalibrationTable [ currentStatus . O2_2ADC ] ;
2018-04-05 14:11:58 -07:00
}
2016-03-23 04:09:04 -07:00
void readBat ( )
{
2017-07-02 18:52:27 -07:00
unsigned int tempReading ;
2017-02-08 19:17:20 -08:00
# if defined(ANALOG_ISR)
2016-11-06 05:31:18 -08:00
tempReading = fastMap1023toX ( AnChannel [ pinBat - A0 ] , 245 ) ; //Get the current raw Battery value. Permissible values are from 0v to 24.5v (245)
# else
tempReading = analogRead ( pinBat ) ;
tempReading = fastMap1023toX ( analogRead ( pinBat ) , 245 ) ; //Get the current raw Battery value. Permissible values are from 0v to 24.5v (245)
# endif
2016-06-10 05:38:05 -07:00
currentStatus . battery10 = ADC_FILTER ( tempReading , ADCFILTER_BAT , currentStatus . battery10 ) ;
2016-03-23 04:09:04 -07:00
}
2016-06-24 01:02:53 -07:00
/*
* The interrupt function for reading the flex sensor frequency
* This value is incremented with every pulse and reset back to 0 once per second
*/
2016-10-25 07:04:37 -07:00
void flexPulse ( )
2016-06-24 01:02:53 -07:00
{
+ + flexCounter ;
}