Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
main.cpp
00001 /* Bob Anderson (bob.anderson.ok@gmail.com) 00002 00003 This program... 00004 00005 1) Uses AnalogIn but speeds it up by setting 00006 the ADC clock to 12MHz (13MHz is max from spec sheet) 00007 00008 2) Produces a histogram of deviations around a center 00009 value that is determined at the beginning of a run 00010 by a "vote" taken from three successive readings. 00011 00012 3) Introduces a "glitch" suppression method that appears 00013 to be effective. I consider a glitch to have occurred 00014 when two consecutive reading differ in value by more than 00015 3 sigma (approximately 10 for the noise distributions 00016 exhibited by the internal ADC). 00017 00018 4) Provides for side-by-side comparison of an external ADC 00019 (MCP3304 or MCP3208) running at about 20,000 sps (because 00020 I'm running the part at 3.3v). 00021 00022 With a 100nf capacitor from the analog pin to ground and 00023 a reasonably low impedance source ( < 5K ) and glitch suppression 00024 enabled, the LPC1768/9 onboard analog to digital converter subsystem 00025 becomes quite useable. Without the capacitor and glitch suppression, 00026 it is not a reliable ADC --- it is glitch prone, even with the 00027 cleanest of inputs. This program will help you determine for 00028 yourself whether that statement is true. Play with it. 00029 00030 The comparison of the internal ADC with the external ADC show that the 00031 external ADC is well behaved in circumstances that wipe out the internal ADC 00032 which is apparently quite sensitive to noise, whereas the external ADC is quite 00033 tolerant of noise. The external ADC produces very narrow "distributions". 00034 00035 */ 00036 00037 #include "mbed.h" 00038 00039 Serial pc( USBTX, USBRX ); 00040 00041 AnalogIn ain( p20 ); 00042 00043 DigitalOut extAdcSelect(p8); 00044 DigitalOut led4(LED4); 00045 00046 SPI spi(p5,p6,p7); // spi(mosi,miso,sck) 00047 00048 #define MCP3208 // or MCP3304 00049 00050 #define EXT_ADC_CHAN 5 00051 00052 #define NUM_SAMPLES 1000000 00053 #define HGRAM_MAX_INDEX 60 00054 00055 int histoGramA[ HGRAM_MAX_INDEX + 1 ]; // histogram array for internal ADC 00056 int histoGramB[ HGRAM_MAX_INDEX + 1 ]; // histogram array for (possible) external ADC 00057 00058 int glitchCount = 0; 00059 bool glitchSuppressionWanted = false; 00060 bool useExternalADC = false; 00061 00062 void setADCclockToMaxConversionRate( void ); 00063 int glitchSuppressedAnalogIn( bool ); 00064 int readExternalADC( int ); 00065 void displayMenu( void ); 00066 int getCenterValue( bool externalADC ); 00067 00068 int max( int a, int b ) { 00069 if ( a > b ) return a; 00070 return b; 00071 } 00072 00073 int min( int a, int b ) { 00074 if ( a < b ) return a; 00075 return b; 00076 } 00077 00078 // middle( a, b, c ) returns true if a is between b and c 00079 bool middle( int a, int b, int c ) { 00080 return (a <= max(b,c)) && (a >= min(b,c)); 00081 } 00082 00083 // The MPC3304 chip select line is inverted: low == selected 00084 #define EXT_ADC_OFF 1 00085 #define EXT_ADC_ON 0 00086 00087 00088 00089 int main() { 00090 00091 int referenceValue; 00092 int delta; 00093 int newValue; 00094 00095 led4 = 0; // This led shows progress during data acquisition. 00096 00097 extAdcSelect = EXT_ADC_OFF; // deselect 00098 00099 spi.format( 8, 0 ); 00100 spi.frequency( 500000 ); 00101 00102 // Speedup the AnalogIn conversion rate by readjusting 00103 // the ADC clock to 12 MHz (assuming SystemCoreClock = 96MHz) 00104 setADCclockToMaxConversionRate(); 00105 00106 while(1) { 00107 00108 displayMenu(); 00109 00110 bool waitingForKeyInput = true; 00111 00112 while ( waitingForKeyInput ){ 00113 switch (pc.getc()) { 00114 case 'g': 00115 case 'G': 00116 glitchSuppressionWanted = ! glitchSuppressionWanted; 00117 if ( glitchSuppressionWanted ) 00118 printf( "...glitch suppression on...\r\n" ); 00119 else 00120 printf( "...glitch suppression off...\r\n" ); 00121 break; 00122 00123 case 'x': 00124 case 'X': 00125 useExternalADC = ! useExternalADC; 00126 if ( useExternalADC ) 00127 printf( "...external ADC will be used...\r\n\r\n" ); 00128 else 00129 printf( "...only internal ADC will be used...\r\n" ); 00130 break; 00131 00132 case 't': 00133 for ( int cnt = 0; cnt < 50; cnt++ ) 00134 printf( "EXT ADC = %d\r\n", readExternalADC(EXT_ADC_CHAN) ); 00135 break; 00136 00137 case 's': 00138 case 'S': waitingForKeyInput = false; break; 00139 00140 default: 00141 displayMenu(); break; 00142 } 00143 } 00144 00145 // Clear the histogram arrays. 00146 for ( int k = 0; k <= HGRAM_MAX_INDEX; k++ ) histoGramA[k] = histoGramB[k] = 0; 00147 00148 bool readFromExternalADC = false; 00149 00150 referenceValue = getCenterValue( readFromExternalADC ); 00151 00152 printf( "Internal ADC center value = %d\r\n\r\n", referenceValue ); 00153 printf( "...now gathering... LED4 toggles at each 10,000 readings\r\n\r\n" ); 00154 00155 glitchCount = 0; 00156 for ( int i = 0; i < NUM_SAMPLES; i++ ) { 00157 newValue = glitchSuppressedAnalogIn( readFromExternalADC ); 00158 delta = newValue - referenceValue + (HGRAM_MAX_INDEX / 2); 00159 if ( delta < 0 ) histoGramA[0]++; 00160 else if ( delta > HGRAM_MAX_INDEX ) histoGramA[HGRAM_MAX_INDEX]++; 00161 else histoGramA[delta]++; 00162 if ( (i % 10000) == 0 ) led4 = !led4; 00163 } 00164 led4 = 0; 00165 00166 int glitchCountInternal = glitchCount; 00167 int glitchCountExternal = 0; 00168 00169 if ( useExternalADC ) 00170 { 00171 readFromExternalADC = true; 00172 00173 referenceValue = getCenterValue( readFromExternalADC ); 00174 00175 printf( "External ADC center value = %d\r\n\r\n", referenceValue ); 00176 printf( "...now gathering... LED4 toggles at each 10,000 readings\r\n\r\n" ); 00177 00178 glitchCount = 0; 00179 for ( int i = 0; i < NUM_SAMPLES; i++ ) { 00180 newValue = glitchSuppressedAnalogIn( readFromExternalADC ); 00181 delta = newValue - referenceValue + (HGRAM_MAX_INDEX / 2); 00182 if ( delta < 0 ) histoGramB[0]++; 00183 else if ( delta > HGRAM_MAX_INDEX ) histoGramB[HGRAM_MAX_INDEX]++; 00184 else histoGramB[delta]++; 00185 if ( (i % 10000) == 0 ) led4 = !led4; 00186 } 00187 led4 = 0; 00188 00189 glitchCountExternal = glitchCount; 00190 } 00191 00192 // Output histoGram(s) 00193 for ( int j = 0; j <= HGRAM_MAX_INDEX; j++ ) { 00194 if ( useExternalADC ) 00195 printf( "%4d %8d %8d\r\n", j - (HGRAM_MAX_INDEX/2), histoGramA[j], histoGramB[j] ); 00196 else 00197 printf( "%4d %8d\r\n", j - (HGRAM_MAX_INDEX/2), histoGramA[j] ); 00198 } 00199 00200 // Show glitch stats if glitch suppression was enabled 00201 if ( glitchSuppressionWanted ) { 00202 if ( useExternalADC ) 00203 printf( "\nglitchCount: Internal = %d External = %d\r\n", 00204 glitchCountInternal, glitchCountExternal ); 00205 else 00206 printf( "\nglitchCountInternal = %d\r\n", glitchCountInternal ); 00207 } 00208 } 00209 } 00210 00211 void setADCclockToMaxConversionRate(void) { 00212 // Set pclk = cclk / 4 (pclk = 96Mhz/4 = 24Mhz) 00213 LPC_SC->PCLKSEL0 &= ~(0x3 << 24); // Clear bits 25:24 00214 00215 // software-controlled ADC settings 00216 LPC_ADC->ADCR = (0 << 0) // SEL: 0 = no channels selected 00217 | (1 << 8 ) // CLKDIV: ADCCLK = PCLK / (CLKDIV + 1) (12MHz) 00218 | (0 << 16) // BURST: 0 = software control 00219 | (0 << 17) // CLKS: not applicable 00220 | (1 << 21) // PDN: 1 = operational 00221 | (0 << 24) // START: 0 = no start 00222 | (0 << 27); // EDGE: not applicable} 00223 return; 00224 } 00225 00226 int glitchSuppressedAnalogIn( bool externalADC ) { 00227 int v1,v2,delta; 00228 00229 if ( externalADC ) 00230 v1 = readExternalADC(EXT_ADC_CHAN); 00231 else 00232 v1 = ain.read_u16() >> 4; 00233 00234 if ( ! glitchSuppressionWanted ) return v1; 00235 00236 // While this has the possiblity of never returning, 00237 // the probability of that is vanishingly small. We assume 00238 // that we will eventually find two successive readings that are 00239 // within the tolerance band --- i.e., no glitch 00240 while(1){ 00241 if ( externalADC ) 00242 v2 = readExternalADC(EXT_ADC_CHAN); 00243 else 00244 v2 = ain.read_u16() >> 4; 00245 delta = v1 - v2; 00246 if ( (delta > -10) && (delta < 10)) return (v1+v2)/2; 00247 v1 = v2; 00248 glitchCount++; 00249 } 00250 } 00251 00252 int readExternalADC( int channel ) { 00253 int ch = channel & 0x7; 00254 extAdcSelect = EXT_ADC_ON; 00255 00256 #ifdef MCP3208 00257 int byte1 = spi.write( 0x6 | (ch >> 2) ); 00258 int byte2 = spi.write( (ch << 6) ) & 0xf; // d0 = 0 00259 #else 00260 #ifdef MCP3304 00261 int byte1 = spi.write( 0xc | (ch >> 1) ); 00262 int byte2 = spi.write( (ch << 7) ) & 0xf; // d0 = 0 00263 #else 00264 error( "Undefined external ADC device" ); 00265 #endif 00266 #endif 00267 00268 int byte3 = spi.write( 0xaa ); // dummy value, but nice pattern of logic analyzer 00269 extAdcSelect = EXT_ADC_OFF; 00270 int value = (byte2 << 8) | byte3; 00271 //printf( "byte2 = %2x byte3 = %2x value = %d\r\n", byte2, byte3, value ); 00272 return value; 00273 } 00274 00275 void displayMenu( void ) { 00276 00277 if ( glitchSuppressionWanted ) 00278 printf( "\r\n\r\nglitch suppression is enabled.\r\n" ); 00279 else 00280 printf( "\r\nglitch suppression is disabled\r\n" ); 00281 if ( useExternalADC ) 00282 printf( "Results from an external ADC will be included.\r\n" ); 00283 else 00284 printf( "External ADC not in use.\r\n" ); 00285 00286 printf( "\r\nPress the s key to start data acquisition.\r\n" ); 00287 printf( "Press the g key to toggle glitch suppression.\r\n" ); 00288 printf( "Press the x key to toggle use of external ADC.\r\n\r\n" ); 00289 } 00290 00291 int getCenterValue( bool externalADC ) { 00292 // Establish center point for histogram by taking three readings 00293 // and selecting the one in the middle as the reference value around 00294 // which deviations will be calculated. 00295 int value1 = glitchSuppressedAnalogIn( externalADC ); 00296 int value2 = glitchSuppressedAnalogIn( externalADC ); 00297 int value3 = glitchSuppressedAnalogIn( externalADC ); 00298 00299 if ( middle(value1,value2,value3) ) 00300 return value1; 00301 else if ( middle(value2,value1,value3) ) 00302 return value2; 00303 else 00304 return value3; 00305 }
Generated on Sat Jul 16 2022 11:07:21 by
1.7.2