Bob Anderson
/
AnalogInAnalyzer
Diff: main.cpp
- Revision:
- 1:ecca38babc13
- Parent:
- 0:7c70badd2847
- Child:
- 2:e1781d02ec0d
--- a/main.cpp Wed Feb 16 23:20:42 2011 +0000 +++ b/main.cpp Fri Feb 18 00:43:05 2011 +0000 @@ -10,7 +10,14 @@ by a "vote" taken from three successive readings. 3) Introduces a "glitch" suppression method that appears - to be effective. + to be effective. I consider a glitch to have occurred + when two consecutive reading differ in value by more than + 3 sigma (approximately 10 for the noise distributions + exhibited by the internal ADC). + + 4) Provides for side-by-side comparison of an external ADC + (MCP3304 or MCP3208) running at about 20,000 sps (because + I'm running the part at 3.3v). With a 100nf capacitor from the analog pin to ground and a reasonably low impedance source ( < 5K ) and glitch suppression @@ -20,25 +27,39 @@ cleanest of inputs. This program will help you determine for yourself whether that statement is true. Play with it. +The comparison of the internal ADC with the external ADC show that the +external ADC is well behaved in circumstances that wipe out the internal ADC +which is apparently quite sensitive to noise, whereas the external ADC is quite +tolerant of noise. The external ADC produces very narrow "distributions". + */ #include "mbed.h" -#include "Serial.h" -#include "AnalogIn.h" Serial pc( USBTX, USBRX ); AnalogIn ain( p20 ); +DigitalOut mpc3304Select(p8); +DigitalOut led4(LED4); + +SPI spi(p5,p6,p7); // spi(mosi,miso,sck) + #define NUM_SAMPLES 1000000 #define HGRAM_MAX_INDEX 60 -int histoGram[ HGRAM_MAX_INDEX + 1 ]; + +int histoGramA[ HGRAM_MAX_INDEX + 1 ]; // histogram array for internal ADC +int histoGramB[ HGRAM_MAX_INDEX + 1 ]; // histogram array for (possible) external ADC int glitchCount = 0; bool glitchSuppressionWanted = false; +bool useExternalADC = false; -void setADCclockToMaxConversionRate(void); -int glitchSuppressedAnalogIn( void ); +void setADCclockToMaxConversionRate( void ); +int glitchSuppressedAnalogIn( bool ); +int readExternalADC( void ); +void displayMenu( void ); +int getCenterValue( bool externalADC ); int max( int a, int b ) { if ( a > b ) return a; @@ -55,20 +76,33 @@ return (a <= max(b,c)) && (a >= min(b,c)); } +// The MPC3304 chip select line is inverted: low == selected +#define EXT_ADC_OFF 1 +#define EXT_ADC_ON 0 + + + int main() { int referenceValue; int delta; int newValue; + led4 = 0; // This led shows progress during data acquisition. + + mpc3304Select = EXT_ADC_OFF; // deselect + + spi.format( 8, 0 ); + spi.frequency( 500000 ); + // Speedup the AnalogIn conversion rate by readjusting // the ADC clock to 12 MHz (assuming SystemCoreClock = 96MHz) setADCclockToMaxConversionRate(); while(1) { - - printf( "\nPress the s key to start stats gathering\n" ); - printf( "Press the g key to toggle glitch suppression...\n" ); + + displayMenu(); + bool waitingForKeyInput = true; while ( waitingForKeyInput ){ @@ -77,52 +111,97 @@ case 'G': glitchSuppressionWanted = ! glitchSuppressionWanted; if ( glitchSuppressionWanted ) - printf( "...glitch suppression on...\n" ); + printf( "...glitch suppression on...\r\n" ); else - printf( "...glitch suppression off...\n" ); + printf( "...glitch suppression off...\r\n" ); + break; + + case 'x': + case 'X': + useExternalADC = ! useExternalADC; + if ( useExternalADC ) + printf( "...external ADC will be used...\r\n\r\n" ); + else + printf( "...only internal ADC will be used...\r\n" ); + break; + + case 't': + for ( int cnt = 0; cnt < 50; cnt++ ) + printf( "EXT ADC = %d\r\n", readExternalADC() ); break; + case 's': - case 'S': waitingForKeyInput = false; + case 'S': waitingForKeyInput = false; break; + + default: + displayMenu(); break; } } + + // Clear the histogram arrays. + for ( int k = 0; k <= HGRAM_MAX_INDEX; k++ ) histoGramA[k] = histoGramB[k] = 0; + + bool readFromExternalADC = false; + + referenceValue = getCenterValue( readFromExternalADC ); + + printf( "Internal ADC center value = %d\r\n\r\n", referenceValue ); + printf( "...now gathering... LED4 toggles at each 10,000 readings\r\n\r\n" ); + + glitchCount = 0; + for ( int i = 0; i < NUM_SAMPLES; i++ ) { + newValue = glitchSuppressedAnalogIn( readFromExternalADC ); + delta = newValue - referenceValue + (HGRAM_MAX_INDEX / 2); + if ( delta < 0 ) histoGramA[0]++; + else if ( delta > HGRAM_MAX_INDEX ) histoGramA[HGRAM_MAX_INDEX]++; + else histoGramA[delta]++; + if ( (i % 10000) == 0 ) led4 = !led4; + } + led4 = 0; + + int glitchCountInternal = glitchCount; + int glitchCountExternal; + + if ( useExternalADC ) + { + readFromExternalADC = true; + + referenceValue = getCenterValue( readFromExternalADC ); + + printf( "External ADC center value = %d\r\n\r\n", referenceValue ); + printf( "...now gathering... LED4 toggles at each 10,000 readings\r\n\r\n" ); + + glitchCount = 0; + for ( int i = 0; i < NUM_SAMPLES; i++ ) { + newValue = glitchSuppressedAnalogIn( readFromExternalADC ); + delta = newValue - referenceValue + (HGRAM_MAX_INDEX / 2); + if ( delta < 0 ) histoGramB[0]++; + else if ( delta > HGRAM_MAX_INDEX ) histoGramB[HGRAM_MAX_INDEX]++; + else histoGramB[delta]++; + if ( (i % 10000) == 0 ) led4 = !led4; + } + led4 = 0; + + glitchCountExternal = glitchCount; + } - // Establish center point for histogram by taking three readings - // and selecting the one in the middle as the reference value around - // which deviations will be calculated. - int value1 = ain.read_u16() >> 4; - int value2 = ain.read_u16() >> 4; - int value3 = ain.read_u16() >> 4; - - if ( middle(value1,value2,value3) ) - referenceValue = value1; - else if ( middle(value2,value1,value3) ) - referenceValue = value2; - else - referenceValue = value3; - - printf( "\nreferenceValue: %d value1: %d value2: %d value3: %d\n", - referenceValue, value1, value2, value3 ); - printf( "\n...now gathering...\n\n" ); - - // Clear the histogram array. - for ( int k = 0; k <= HGRAM_MAX_INDEX; k++ ) histoGram[k] = 0; - glitchCount = 0; - - for ( int i = 0; i < NUM_SAMPLES; i++ ) { - newValue = glitchSuppressedAnalogIn(); - delta = newValue - referenceValue + (HGRAM_MAX_INDEX / 2); - if ( delta < 0 ) histoGram[0]++; - else if ( delta > HGRAM_MAX_INDEX ) histoGram[HGRAM_MAX_INDEX]++; - else histoGram[delta]++; - } // Output histoGram for ( int j = 0; j <= HGRAM_MAX_INDEX; j++ ) { - printf( "%4d %8d\n", j, histoGram[j] ); + if ( useExternalADC ) + printf( "%4d %8d %8d\r\n", j - (HGRAM_MAX_INDEX/2), histoGramA[j], histoGramB[j] ); + else + printf( "%4d %8d\r\n", j - (HGRAM_MAX_INDEX/2), histoGramA[j] ); } - printf( "glitchCount: %d\n", glitchCount ); + if ( glitchSuppressionWanted ) { + if ( useExternalADC ) + printf( "\nglitchCount: Internal = %d External = %d\r\n", + glitchCountInternal, glitchCountExternal ); + else + printf( "\nglitchCountInternal = %d\r\n", glitchCountInternal ); + } } } @@ -141,10 +220,14 @@ return; } -int glitchSuppressedAnalogIn( void ) { +int glitchSuppressedAnalogIn( bool externalADC ) { int v1,v2,delta; - v1 = ain.read_u16() >> 4; + if ( externalADC ) + v1 = readExternalADC(); + else + v1 = ain.read_u16() >> 4; + if ( ! glitchSuppressionWanted ) return v1; // While this has the possiblity of never returning, @@ -152,10 +235,56 @@ // that we will eventually find two successive readings that are // within the tolerance band --- i.e., no glitch while(1){ - v2 = ain.read_u16() >> 4; + if ( externalADC ) + v2 = readExternalADC(); + else + v2 = ain.read_u16() >> 4; delta = v1 - v2; if ( (delta > -10) && (delta < 10)) return (v1+v2)/2; v1 = v2; glitchCount++; } +} + +int readExternalADC( void ) { // Hardcoded for channel 0 (for quick test) + mpc3304Select = EXT_ADC_ON; + int byte1 = spi.write( 0xc ); // start=1 sgl=1 d2=0 d1=0 + int byte2 = spi.write( 0x0 ) & 0xf; // d0 = 0 + int byte3 = spi.write( 0xaa ); // dummy value, but nice pattern of logic analyzer + mpc3304Select = EXT_ADC_OFF; + int value = (byte2 << 8) | byte3; + //printf( "byte2 = %2x byte3 = %2x value = %d\r\n", byte2, byte3, value ); + return value; +} + +void displayMenu( void ) { + + if ( glitchSuppressionWanted ) + printf( "\r\n\r\nglitch suppression is enabled.\r\n" ); + else + printf( "\r\nglitch suppression is disabled\r\n" ); + if ( useExternalADC ) + printf( "Results from an external ADC will be included.\r\n" ); + else + printf( "External ADC not in use.\r\n" ); + + printf( "\r\nPress the s key to start data acquisition.\r\n" ); + printf( "Press the g key to toggle glitch suppression.\r\n" ); + printf( "Press the x key to toggle use of external ADC.\r\n\r\n" ); +} + +int getCenterValue( bool externalADC ) { + // Establish center point for histogram by taking three readings + // and selecting the one in the middle as the reference value around + // which deviations will be calculated. + int value1 = glitchSuppressedAnalogIn( externalADC ); + int value2 = glitchSuppressedAnalogIn( externalADC ); + int value3 = glitchSuppressedAnalogIn( externalADC ); + + if ( middle(value1,value2,value3) ) + return value1; + else if ( middle(value2,value1,value3) ) + return value2; + else + return value3; } \ No newline at end of file