ADC interrupt routine

Introducing ADC interrupt routine tor atmel devices
This commit is contained in:
VitorBoss 2016-11-06 11:31:18 -02:00
parent 0a6be57aa6
commit 0a1cadc504
3 changed files with 137 additions and 26 deletions

View File

@ -14,6 +14,15 @@
volatile byte flexCounter = 0;
#define ANALOG_ISR //Comment this line to disable the ADC interrupt routine
#if defined(ANALOG_ISR)
#if defined(__AVR_ATmega1281__) || defined(__AVR_ATmega2561__)
int AnChannel[7];
#else
int AnChannel[15];
#endif
#endif
/*
* Simple low pass IIR filter macro for the analog inputs
* This is effectively implementing the smooth filter from http://playground.arduino.cc/Main/Smooth
@ -27,4 +36,35 @@ void flexPulse();
unsigned int tempReading;
#if defined(ANALOG_ISR)
//Analog ISR interrupt routine
ISR(ADC_vect)
{
byte nChannel;
int result = ADCL | (ADCH << 8);
ADCSRA = 0x6E; // ADC disabled by clearing bit 7(ADEN)
nChannel = ADMUX & 0x07;
#if defined(__AVR_ATmega1281__) || defined(__AVR_ATmega2561__)
if (nChannel==7) { ADMUX = 0x40; }
#elif defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
if(ADCSRB & 0x08) { nChannel+=8; } //8 to 15
if(nChannel==15)
{
ADMUX = 0x40; //channel 0
ADCSRB = 0x00; //clear MUX5 bit
}
else if (nChannel==7) //channel 7
{
ADMUX = 0x40;
ADCSRB = 0x08; //Set MUX5 bit
}
#endif
else { ADMUX++; }
AnChannel[nChannel] = result;
ADCSRA = 0xEE; // ADC Interrupt Flag enabled
}
#endif
#endif // SENSORS_H

View File

@ -7,9 +7,12 @@ A full copy of the license may be found in the projects root directory
void instanteneousMAPReading()
{
//Instantaneous MAP readings
#if defined(ANALOG_ISR)
tempReading = AnChannel[pinMAP-A0];
#else
tempReading = analogRead(pinMAP);
tempReading = analogRead(pinMAP);
#endif
//Error checking
if(tempReading >= VALID_MAP_MAX || tempReading <= VALID_MAP_MIN) { mapErrorCount += 1; }
else { currentStatus.mapADC = tempReading; mapErrorCount = 0; }
@ -34,8 +37,12 @@ void readMAP()
if( (MAPcurRev == startRevolutions) || (MAPcurRev == startRevolutions+1) ) //2 revolutions are looked at for 4 stroke. 2 stroke not currently catered for.
{
#if defined(ANALOG_ISR)
tempReading = AnChannel[pinMAP-A0];
#else
tempReading = analogRead(pinMAP);
tempReading = analogRead(pinMAP);
#endif
//Error check
if(tempReading < VALID_MAP_MAX && tempReading > VALID_MAP_MIN)
@ -62,8 +69,12 @@ void readMAP()
if( (MAPcurRev == startRevolutions) || (MAPcurRev == startRevolutions+1) ) //2 revolutions are looked at for 4 stroke. 2 stroke not currently catered for.
{
#if defined(ANALOG_ISR)
tempReading = AnChannel[pinMAP-A0];
#else
tempReading = analogRead(pinMAP);
tempReading = analogRead(pinMAP);
#endif
//Error check
if(tempReading < VALID_MAP_MAX && tempReading > VALID_MAP_MIN)
{
@ -87,8 +98,12 @@ void readTPS()
{
currentStatus.TPSlast = currentStatus.TPS;
currentStatus.TPSlast_time = currentStatus.TPS_time;
#if defined(ANALOG_ISR)
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
currentStatus.tpsADC = ADC_FILTER(tempTPS, ADCFILTER_TPS, currentStatus.tpsADC);
//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).
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
@ -100,24 +115,36 @@ void readTPS()
void readCLT()
{
#if defined(ANALOG_ISR)
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
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
}
void readIAT()
{
#if defined(ANALOG_ISR)
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
currentStatus.iatADC = ADC_FILTER(tempReading, ADCFILTER_IAT, currentStatus.iatADC);
currentStatus.IAT = iatCalibrationTable[currentStatus.iatADC] - CALIBRATION_TEMPERATURE_OFFSET;
}
void readO2()
{
#if defined(ANALOG_ISR)
tempReading = fastMap1023toX(AnChannel[pinO2-A0], 511); //Get the current O2 value.
#else
tempReading = analogRead(pinO2);
tempReading = fastMap1023toX(analogRead(pinO2), 511); //Get the current O2 value.
#endif
currentStatus.O2ADC = ADC_FILTER(tempReading, ADCFILTER_O2, currentStatus.O2ADC);
currentStatus.O2 = o2CalibrationTable[currentStatus.O2ADC];
}
@ -130,8 +157,12 @@ void readO2()
void readBat()
{
#if defined(ANALOG_ISR)
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
currentStatus.battery10 = ADC_FILTER(tempReading, ADCFILTER_BAT, currentStatus.battery10);
}

View File

@ -485,7 +485,15 @@ void setup()
currentLoopTime = micros();
#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) || defined(__AVR_ATmega2561__) //AVR chips use the ISR for this
#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega1281__) || defined(__AVR_ATmega2560__) || defined(__AVR_ATmega2561__) //AVR chips use the ISR for this
#if defined(ANALOG_ISR) //ADC interrupt routine
//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.
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
ADCSRA = 0xEE; // ADC Interrupt Flag enabled and prescaler selected to 250KHz
#else
//This sets the ADC (Analog to Digitial Converter) to run at 1Mhz, greatly reducing analog read times (MAP/TPS)
//1Mhz is the fastest speed permitted by the CPU without affecting accuracy
//Please see chapter 11 of 'Practical Arduino' (http://books.google.com.au/books?id=HsTxON1L6D4C&printsec=frontcover#v=onepage&q&f=false) for more details
@ -496,6 +504,7 @@ void setup()
cbi(ADCSRA,ADPS0);
#endif
#endif
#endif
mainLoopCount = 0;
@ -1450,6 +1459,37 @@ void loop()
//************************************************************************************************
//Interrupts
#if defined(ANALOG_H)
//Analog ISR interrupt routine
ISR(ADC_vect)
{
byte nChannel;
int result = ADCL | (ADCH << 8);
ADCSRA = 0x6E; // ADC Auto Trigger disabled by clearing bit 7(ADEN)
nChannel = ADMUX & 0x07;
#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
if(ADCSRB & 0x08) { nChannel+=8; } //8 to 15
if(nChannel==15)
{
ADMUX = 0x40; //channel 0
ADCSRB = 0x00; //clear MUX5 bit
}
else if (nChannel==7) //channel 7
{
ADMUX = 0x40;
ADCSRB = 0x08; //Set MUX5 bit
}
#elif defined(__AVR_ATmega1281__) || defined(__AVR_ATmega2561__)
if (nChannel==7) { ADMUX = 0x40; }
#endif
else { ADMUX++; }
AnChannel[nChannel] = result;
ADCSRA = 0xEE; // ADC Interrupt Flag enabled
}
#endif
//These functions simply trigger the injector/coil driver off or on.
//NOTE: squirt status is changed as per http://www.msextra.com/doc/ms1extra/COM_RS232.htm#Acmd
/*