diff --git a/sensors.h b/sensors.h index 731c8527..908fff51 100644 --- a/sensors.h +++ b/sensors.h @@ -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 diff --git a/sensors.ino b/sensors.ino index 5578ac29..e6dba196 100644 --- a/sensors.ino +++ b/sensors.ino @@ -7,9 +7,12 @@ A full copy of the license may be found in the projects root directory void instanteneousMAPReading() { //Instantaneous MAP readings - tempReading = analogRead(pinMAP); - tempReading = analogRead(pinMAP); - + #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. { - tempReading = analogRead(pinMAP); - tempReading = analogRead(pinMAP); + #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. { - tempReading = analogRead(pinMAP); - tempReading = analogRead(pinMAP); + #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; - analogRead(pinTPS); - byte tempTPS = fastMap1023toX(analogRead(pinTPS), 255); //Get the current raw TPS ADC value and map it into a byte + #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() { - tempReading = analogRead(pinCLT); - tempReading = fastMap1023toX(analogRead(pinCLT), 511); //Get the current raw CLT value + #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() { - tempReading = analogRead(pinIAT); - tempReading = fastMap1023toX(analogRead(pinIAT), 511); //Get the current raw IAT value + #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() { - tempReading = analogRead(pinO2); - tempReading = fastMap1023toX(analogRead(pinO2), 511); //Get the current O2 value. + #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() { - tempReading = analogRead(pinBat); - tempReading = fastMap1023toX(analogRead(pinBat), 245); //Get the current raw Battery value. Permissible values are from 0v to 24.5v (245) + #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); } diff --git a/speeduino.ino b/speeduino.ino index 104a7222..a716f3d9 100644 --- a/speeduino.ino +++ b/speeduino.ino @@ -485,15 +485,24 @@ void setup() currentLoopTime = micros(); -#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) || defined(__AVR_ATmega2561__) //AVR chips use the ISR for this - //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 - //Can be disabled by removing the #include "fastAnalog.h" above - #ifdef sbi - sbi(ADCSRA,ADPS2); - cbi(ADCSRA,ADPS1); - cbi(ADCSRA,ADPS0); +#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 + //Can be disabled by removing the #include "fastAnalog.h" above + #ifdef sbi + sbi(ADCSRA,ADPS2); + cbi(ADCSRA,ADPS1); + cbi(ADCSRA,ADPS0); + #endif #endif #endif @@ -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 /*