Dependencies:   mbed

Committer:
bobanderson
Date:
Fri Feb 18 00:43:05 2011 +0000
Revision:
1:ecca38babc13
Parent:
0:7c70badd2847
Child:
2:e1781d02ec0d
This rev incorporates an external ADC (MCP3304) for comparison with internal ADC.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
bobanderson 0:7c70badd2847 1 /* Bob Anderson (bob.anderson.ok@gmail.com)
bobanderson 0:7c70badd2847 2
bobanderson 0:7c70badd2847 3 This program...
bobanderson 0:7c70badd2847 4
bobanderson 0:7c70badd2847 5 1) Uses AnalogIn but speeds it up by setting
bobanderson 0:7c70badd2847 6 the ADC clock to 12MHz (13MHz is max from spec sheet)
bobanderson 0:7c70badd2847 7
bobanderson 0:7c70badd2847 8 2) Produces a histogram of deviations around a center
bobanderson 0:7c70badd2847 9 value that is determined at the beginning of a run
bobanderson 0:7c70badd2847 10 by a "vote" taken from three successive readings.
bobanderson 0:7c70badd2847 11
bobanderson 0:7c70badd2847 12 3) Introduces a "glitch" suppression method that appears
bobanderson 1:ecca38babc13 13 to be effective. I consider a glitch to have occurred
bobanderson 1:ecca38babc13 14 when two consecutive reading differ in value by more than
bobanderson 1:ecca38babc13 15 3 sigma (approximately 10 for the noise distributions
bobanderson 1:ecca38babc13 16 exhibited by the internal ADC).
bobanderson 1:ecca38babc13 17
bobanderson 1:ecca38babc13 18 4) Provides for side-by-side comparison of an external ADC
bobanderson 1:ecca38babc13 19 (MCP3304 or MCP3208) running at about 20,000 sps (because
bobanderson 1:ecca38babc13 20 I'm running the part at 3.3v).
bobanderson 0:7c70badd2847 21
bobanderson 0:7c70badd2847 22 With a 100nf capacitor from the analog pin to ground and
bobanderson 0:7c70badd2847 23 a reasonably low impedance source ( < 5K ) and glitch suppression
bobanderson 0:7c70badd2847 24 enabled, the LPC1768/9 onboard analog to digital converter subsystem
bobanderson 0:7c70badd2847 25 becomes quite useable. Without the capacitor and glitch suppression,
bobanderson 0:7c70badd2847 26 it is not a reliable ADC --- it is glitch prone, even with the
bobanderson 0:7c70badd2847 27 cleanest of inputs. This program will help you determine for
bobanderson 0:7c70badd2847 28 yourself whether that statement is true. Play with it.
bobanderson 0:7c70badd2847 29
bobanderson 1:ecca38babc13 30 The comparison of the internal ADC with the external ADC show that the
bobanderson 1:ecca38babc13 31 external ADC is well behaved in circumstances that wipe out the internal ADC
bobanderson 1:ecca38babc13 32 which is apparently quite sensitive to noise, whereas the external ADC is quite
bobanderson 1:ecca38babc13 33 tolerant of noise. The external ADC produces very narrow "distributions".
bobanderson 1:ecca38babc13 34
bobanderson 0:7c70badd2847 35 */
bobanderson 0:7c70badd2847 36
bobanderson 0:7c70badd2847 37 #include "mbed.h"
bobanderson 0:7c70badd2847 38
bobanderson 0:7c70badd2847 39 Serial pc( USBTX, USBRX );
bobanderson 0:7c70badd2847 40
bobanderson 0:7c70badd2847 41 AnalogIn ain( p20 );
bobanderson 0:7c70badd2847 42
bobanderson 1:ecca38babc13 43 DigitalOut mpc3304Select(p8);
bobanderson 1:ecca38babc13 44 DigitalOut led4(LED4);
bobanderson 1:ecca38babc13 45
bobanderson 1:ecca38babc13 46 SPI spi(p5,p6,p7); // spi(mosi,miso,sck)
bobanderson 1:ecca38babc13 47
bobanderson 0:7c70badd2847 48 #define NUM_SAMPLES 1000000
bobanderson 0:7c70badd2847 49 #define HGRAM_MAX_INDEX 60
bobanderson 1:ecca38babc13 50
bobanderson 1:ecca38babc13 51 int histoGramA[ HGRAM_MAX_INDEX + 1 ]; // histogram array for internal ADC
bobanderson 1:ecca38babc13 52 int histoGramB[ HGRAM_MAX_INDEX + 1 ]; // histogram array for (possible) external ADC
bobanderson 0:7c70badd2847 53
bobanderson 0:7c70badd2847 54 int glitchCount = 0;
bobanderson 0:7c70badd2847 55 bool glitchSuppressionWanted = false;
bobanderson 1:ecca38babc13 56 bool useExternalADC = false;
bobanderson 0:7c70badd2847 57
bobanderson 1:ecca38babc13 58 void setADCclockToMaxConversionRate( void );
bobanderson 1:ecca38babc13 59 int glitchSuppressedAnalogIn( bool );
bobanderson 1:ecca38babc13 60 int readExternalADC( void );
bobanderson 1:ecca38babc13 61 void displayMenu( void );
bobanderson 1:ecca38babc13 62 int getCenterValue( bool externalADC );
bobanderson 0:7c70badd2847 63
bobanderson 0:7c70badd2847 64 int max( int a, int b ) {
bobanderson 0:7c70badd2847 65 if ( a > b ) return a;
bobanderson 0:7c70badd2847 66 return b;
bobanderson 0:7c70badd2847 67 }
bobanderson 0:7c70badd2847 68
bobanderson 0:7c70badd2847 69 int min( int a, int b ) {
bobanderson 0:7c70badd2847 70 if ( a < b ) return a;
bobanderson 0:7c70badd2847 71 return b;
bobanderson 0:7c70badd2847 72 }
bobanderson 0:7c70badd2847 73
bobanderson 0:7c70badd2847 74 // middle( a, b, c ) returns true if a is between b and c
bobanderson 0:7c70badd2847 75 bool middle( int a, int b, int c ) {
bobanderson 0:7c70badd2847 76 return (a <= max(b,c)) && (a >= min(b,c));
bobanderson 0:7c70badd2847 77 }
bobanderson 0:7c70badd2847 78
bobanderson 1:ecca38babc13 79 // The MPC3304 chip select line is inverted: low == selected
bobanderson 1:ecca38babc13 80 #define EXT_ADC_OFF 1
bobanderson 1:ecca38babc13 81 #define EXT_ADC_ON 0
bobanderson 1:ecca38babc13 82
bobanderson 1:ecca38babc13 83
bobanderson 1:ecca38babc13 84
bobanderson 0:7c70badd2847 85 int main() {
bobanderson 0:7c70badd2847 86
bobanderson 0:7c70badd2847 87 int referenceValue;
bobanderson 0:7c70badd2847 88 int delta;
bobanderson 0:7c70badd2847 89 int newValue;
bobanderson 0:7c70badd2847 90
bobanderson 1:ecca38babc13 91 led4 = 0; // This led shows progress during data acquisition.
bobanderson 1:ecca38babc13 92
bobanderson 1:ecca38babc13 93 mpc3304Select = EXT_ADC_OFF; // deselect
bobanderson 1:ecca38babc13 94
bobanderson 1:ecca38babc13 95 spi.format( 8, 0 );
bobanderson 1:ecca38babc13 96 spi.frequency( 500000 );
bobanderson 1:ecca38babc13 97
bobanderson 0:7c70badd2847 98 // Speedup the AnalogIn conversion rate by readjusting
bobanderson 0:7c70badd2847 99 // the ADC clock to 12 MHz (assuming SystemCoreClock = 96MHz)
bobanderson 0:7c70badd2847 100 setADCclockToMaxConversionRate();
bobanderson 0:7c70badd2847 101
bobanderson 0:7c70badd2847 102 while(1) {
bobanderson 1:ecca38babc13 103
bobanderson 1:ecca38babc13 104 displayMenu();
bobanderson 1:ecca38babc13 105
bobanderson 0:7c70badd2847 106 bool waitingForKeyInput = true;
bobanderson 0:7c70badd2847 107
bobanderson 0:7c70badd2847 108 while ( waitingForKeyInput ){
bobanderson 0:7c70badd2847 109 switch (pc.getc()) {
bobanderson 0:7c70badd2847 110 case 'g':
bobanderson 0:7c70badd2847 111 case 'G':
bobanderson 0:7c70badd2847 112 glitchSuppressionWanted = ! glitchSuppressionWanted;
bobanderson 0:7c70badd2847 113 if ( glitchSuppressionWanted )
bobanderson 1:ecca38babc13 114 printf( "...glitch suppression on...\r\n" );
bobanderson 0:7c70badd2847 115 else
bobanderson 1:ecca38babc13 116 printf( "...glitch suppression off...\r\n" );
bobanderson 1:ecca38babc13 117 break;
bobanderson 1:ecca38babc13 118
bobanderson 1:ecca38babc13 119 case 'x':
bobanderson 1:ecca38babc13 120 case 'X':
bobanderson 1:ecca38babc13 121 useExternalADC = ! useExternalADC;
bobanderson 1:ecca38babc13 122 if ( useExternalADC )
bobanderson 1:ecca38babc13 123 printf( "...external ADC will be used...\r\n\r\n" );
bobanderson 1:ecca38babc13 124 else
bobanderson 1:ecca38babc13 125 printf( "...only internal ADC will be used...\r\n" );
bobanderson 1:ecca38babc13 126 break;
bobanderson 1:ecca38babc13 127
bobanderson 1:ecca38babc13 128 case 't':
bobanderson 1:ecca38babc13 129 for ( int cnt = 0; cnt < 50; cnt++ )
bobanderson 1:ecca38babc13 130 printf( "EXT ADC = %d\r\n", readExternalADC() );
bobanderson 0:7c70badd2847 131 break;
bobanderson 1:ecca38babc13 132
bobanderson 0:7c70badd2847 133 case 's':
bobanderson 1:ecca38babc13 134 case 'S': waitingForKeyInput = false; break;
bobanderson 1:ecca38babc13 135
bobanderson 1:ecca38babc13 136 default:
bobanderson 1:ecca38babc13 137 displayMenu(); break;
bobanderson 0:7c70badd2847 138 }
bobanderson 0:7c70badd2847 139 }
bobanderson 1:ecca38babc13 140
bobanderson 1:ecca38babc13 141 // Clear the histogram arrays.
bobanderson 1:ecca38babc13 142 for ( int k = 0; k <= HGRAM_MAX_INDEX; k++ ) histoGramA[k] = histoGramB[k] = 0;
bobanderson 1:ecca38babc13 143
bobanderson 1:ecca38babc13 144 bool readFromExternalADC = false;
bobanderson 1:ecca38babc13 145
bobanderson 1:ecca38babc13 146 referenceValue = getCenterValue( readFromExternalADC );
bobanderson 1:ecca38babc13 147
bobanderson 1:ecca38babc13 148 printf( "Internal ADC center value = %d\r\n\r\n", referenceValue );
bobanderson 1:ecca38babc13 149 printf( "...now gathering... LED4 toggles at each 10,000 readings\r\n\r\n" );
bobanderson 1:ecca38babc13 150
bobanderson 1:ecca38babc13 151 glitchCount = 0;
bobanderson 1:ecca38babc13 152 for ( int i = 0; i < NUM_SAMPLES; i++ ) {
bobanderson 1:ecca38babc13 153 newValue = glitchSuppressedAnalogIn( readFromExternalADC );
bobanderson 1:ecca38babc13 154 delta = newValue - referenceValue + (HGRAM_MAX_INDEX / 2);
bobanderson 1:ecca38babc13 155 if ( delta < 0 ) histoGramA[0]++;
bobanderson 1:ecca38babc13 156 else if ( delta > HGRAM_MAX_INDEX ) histoGramA[HGRAM_MAX_INDEX]++;
bobanderson 1:ecca38babc13 157 else histoGramA[delta]++;
bobanderson 1:ecca38babc13 158 if ( (i % 10000) == 0 ) led4 = !led4;
bobanderson 1:ecca38babc13 159 }
bobanderson 1:ecca38babc13 160 led4 = 0;
bobanderson 1:ecca38babc13 161
bobanderson 1:ecca38babc13 162 int glitchCountInternal = glitchCount;
bobanderson 1:ecca38babc13 163 int glitchCountExternal;
bobanderson 1:ecca38babc13 164
bobanderson 1:ecca38babc13 165 if ( useExternalADC )
bobanderson 1:ecca38babc13 166 {
bobanderson 1:ecca38babc13 167 readFromExternalADC = true;
bobanderson 1:ecca38babc13 168
bobanderson 1:ecca38babc13 169 referenceValue = getCenterValue( readFromExternalADC );
bobanderson 1:ecca38babc13 170
bobanderson 1:ecca38babc13 171 printf( "External ADC center value = %d\r\n\r\n", referenceValue );
bobanderson 1:ecca38babc13 172 printf( "...now gathering... LED4 toggles at each 10,000 readings\r\n\r\n" );
bobanderson 1:ecca38babc13 173
bobanderson 1:ecca38babc13 174 glitchCount = 0;
bobanderson 1:ecca38babc13 175 for ( int i = 0; i < NUM_SAMPLES; i++ ) {
bobanderson 1:ecca38babc13 176 newValue = glitchSuppressedAnalogIn( readFromExternalADC );
bobanderson 1:ecca38babc13 177 delta = newValue - referenceValue + (HGRAM_MAX_INDEX / 2);
bobanderson 1:ecca38babc13 178 if ( delta < 0 ) histoGramB[0]++;
bobanderson 1:ecca38babc13 179 else if ( delta > HGRAM_MAX_INDEX ) histoGramB[HGRAM_MAX_INDEX]++;
bobanderson 1:ecca38babc13 180 else histoGramB[delta]++;
bobanderson 1:ecca38babc13 181 if ( (i % 10000) == 0 ) led4 = !led4;
bobanderson 1:ecca38babc13 182 }
bobanderson 1:ecca38babc13 183 led4 = 0;
bobanderson 1:ecca38babc13 184
bobanderson 1:ecca38babc13 185 glitchCountExternal = glitchCount;
bobanderson 1:ecca38babc13 186 }
bobanderson 0:7c70badd2847 187
bobanderson 0:7c70badd2847 188
bobanderson 0:7c70badd2847 189
bobanderson 0:7c70badd2847 190 // Output histoGram
bobanderson 0:7c70badd2847 191 for ( int j = 0; j <= HGRAM_MAX_INDEX; j++ ) {
bobanderson 1:ecca38babc13 192 if ( useExternalADC )
bobanderson 1:ecca38babc13 193 printf( "%4d %8d %8d\r\n", j - (HGRAM_MAX_INDEX/2), histoGramA[j], histoGramB[j] );
bobanderson 1:ecca38babc13 194 else
bobanderson 1:ecca38babc13 195 printf( "%4d %8d\r\n", j - (HGRAM_MAX_INDEX/2), histoGramA[j] );
bobanderson 0:7c70badd2847 196 }
bobanderson 0:7c70badd2847 197
bobanderson 1:ecca38babc13 198 if ( glitchSuppressionWanted ) {
bobanderson 1:ecca38babc13 199 if ( useExternalADC )
bobanderson 1:ecca38babc13 200 printf( "\nglitchCount: Internal = %d External = %d\r\n",
bobanderson 1:ecca38babc13 201 glitchCountInternal, glitchCountExternal );
bobanderson 1:ecca38babc13 202 else
bobanderson 1:ecca38babc13 203 printf( "\nglitchCountInternal = %d\r\n", glitchCountInternal );
bobanderson 1:ecca38babc13 204 }
bobanderson 0:7c70badd2847 205 }
bobanderson 0:7c70badd2847 206 }
bobanderson 0:7c70badd2847 207
bobanderson 0:7c70badd2847 208 void setADCclockToMaxConversionRate(void) {
bobanderson 0:7c70badd2847 209 // Set pclk = cclk / 4 (pclk = 96Mhz/4 = 24Mhz)
bobanderson 0:7c70badd2847 210 LPC_SC->PCLKSEL0 &= ~(0x3 << 24); // Clear bits 25:24
bobanderson 0:7c70badd2847 211
bobanderson 0:7c70badd2847 212 // software-controlled ADC settings
bobanderson 0:7c70badd2847 213 LPC_ADC->ADCR = (0 << 0) // SEL: 0 = no channels selected
bobanderson 0:7c70badd2847 214 | (1 << 8 ) // CLKDIV: ADCCLK = PCLK / (CLKDIV + 1) (12MHz)
bobanderson 0:7c70badd2847 215 | (0 << 16) // BURST: 0 = software control
bobanderson 0:7c70badd2847 216 | (0 << 17) // CLKS: not applicable
bobanderson 0:7c70badd2847 217 | (1 << 21) // PDN: 1 = operational
bobanderson 0:7c70badd2847 218 | (0 << 24) // START: 0 = no start
bobanderson 0:7c70badd2847 219 | (0 << 27); // EDGE: not applicable}
bobanderson 0:7c70badd2847 220 return;
bobanderson 0:7c70badd2847 221 }
bobanderson 0:7c70badd2847 222
bobanderson 1:ecca38babc13 223 int glitchSuppressedAnalogIn( bool externalADC ) {
bobanderson 0:7c70badd2847 224 int v1,v2,delta;
bobanderson 0:7c70badd2847 225
bobanderson 1:ecca38babc13 226 if ( externalADC )
bobanderson 1:ecca38babc13 227 v1 = readExternalADC();
bobanderson 1:ecca38babc13 228 else
bobanderson 1:ecca38babc13 229 v1 = ain.read_u16() >> 4;
bobanderson 1:ecca38babc13 230
bobanderson 0:7c70badd2847 231 if ( ! glitchSuppressionWanted ) return v1;
bobanderson 0:7c70badd2847 232
bobanderson 0:7c70badd2847 233 // While this has the possiblity of never returning,
bobanderson 0:7c70badd2847 234 // the probability of that is vanishingly small. We assume
bobanderson 0:7c70badd2847 235 // that we will eventually find two successive readings that are
bobanderson 0:7c70badd2847 236 // within the tolerance band --- i.e., no glitch
bobanderson 0:7c70badd2847 237 while(1){
bobanderson 1:ecca38babc13 238 if ( externalADC )
bobanderson 1:ecca38babc13 239 v2 = readExternalADC();
bobanderson 1:ecca38babc13 240 else
bobanderson 1:ecca38babc13 241 v2 = ain.read_u16() >> 4;
bobanderson 0:7c70badd2847 242 delta = v1 - v2;
bobanderson 0:7c70badd2847 243 if ( (delta > -10) && (delta < 10)) return (v1+v2)/2;
bobanderson 0:7c70badd2847 244 v1 = v2;
bobanderson 0:7c70badd2847 245 glitchCount++;
bobanderson 0:7c70badd2847 246 }
bobanderson 1:ecca38babc13 247 }
bobanderson 1:ecca38babc13 248
bobanderson 1:ecca38babc13 249 int readExternalADC( void ) { // Hardcoded for channel 0 (for quick test)
bobanderson 1:ecca38babc13 250 mpc3304Select = EXT_ADC_ON;
bobanderson 1:ecca38babc13 251 int byte1 = spi.write( 0xc ); // start=1 sgl=1 d2=0 d1=0
bobanderson 1:ecca38babc13 252 int byte2 = spi.write( 0x0 ) & 0xf; // d0 = 0
bobanderson 1:ecca38babc13 253 int byte3 = spi.write( 0xaa ); // dummy value, but nice pattern of logic analyzer
bobanderson 1:ecca38babc13 254 mpc3304Select = EXT_ADC_OFF;
bobanderson 1:ecca38babc13 255 int value = (byte2 << 8) | byte3;
bobanderson 1:ecca38babc13 256 //printf( "byte2 = %2x byte3 = %2x value = %d\r\n", byte2, byte3, value );
bobanderson 1:ecca38babc13 257 return value;
bobanderson 1:ecca38babc13 258 }
bobanderson 1:ecca38babc13 259
bobanderson 1:ecca38babc13 260 void displayMenu( void ) {
bobanderson 1:ecca38babc13 261
bobanderson 1:ecca38babc13 262 if ( glitchSuppressionWanted )
bobanderson 1:ecca38babc13 263 printf( "\r\n\r\nglitch suppression is enabled.\r\n" );
bobanderson 1:ecca38babc13 264 else
bobanderson 1:ecca38babc13 265 printf( "\r\nglitch suppression is disabled\r\n" );
bobanderson 1:ecca38babc13 266 if ( useExternalADC )
bobanderson 1:ecca38babc13 267 printf( "Results from an external ADC will be included.\r\n" );
bobanderson 1:ecca38babc13 268 else
bobanderson 1:ecca38babc13 269 printf( "External ADC not in use.\r\n" );
bobanderson 1:ecca38babc13 270
bobanderson 1:ecca38babc13 271 printf( "\r\nPress the s key to start data acquisition.\r\n" );
bobanderson 1:ecca38babc13 272 printf( "Press the g key to toggle glitch suppression.\r\n" );
bobanderson 1:ecca38babc13 273 printf( "Press the x key to toggle use of external ADC.\r\n\r\n" );
bobanderson 1:ecca38babc13 274 }
bobanderson 1:ecca38babc13 275
bobanderson 1:ecca38babc13 276 int getCenterValue( bool externalADC ) {
bobanderson 1:ecca38babc13 277 // Establish center point for histogram by taking three readings
bobanderson 1:ecca38babc13 278 // and selecting the one in the middle as the reference value around
bobanderson 1:ecca38babc13 279 // which deviations will be calculated.
bobanderson 1:ecca38babc13 280 int value1 = glitchSuppressedAnalogIn( externalADC );
bobanderson 1:ecca38babc13 281 int value2 = glitchSuppressedAnalogIn( externalADC );
bobanderson 1:ecca38babc13 282 int value3 = glitchSuppressedAnalogIn( externalADC );
bobanderson 1:ecca38babc13 283
bobanderson 1:ecca38babc13 284 if ( middle(value1,value2,value3) )
bobanderson 1:ecca38babc13 285 return value1;
bobanderson 1:ecca38babc13 286 else if ( middle(value2,value1,value3) )
bobanderson 1:ecca38babc13 287 return value2;
bobanderson 1:ecca38babc13 288 else
bobanderson 1:ecca38babc13 289 return value3;
bobanderson 0:7c70badd2847 290 }