Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /**
- * \brief ADC 8-bit fast reading of multiple channels for Arduino/ATMega328P
- * \file adc_speedtest.c
- * \author Cristian Dobre
- * \version 1.0.1
- * \date April 2015
- * \copyright Revised BSD License.
- */
- /**
- * ADC VARIABLES
- * Modify to change analog-to-digital conversion
- */
- #define ADC_SENSOR_CHANNELS 8
- #define ADC_SENSOR_SAMPLES 6
- /** ADC MULTIPLEXER BITS **/
- #define CHN_ADC0 0000
- #define CHN_ADC1 0001
- #define CHN_ADC2 0010
- #define CHN_ADC3 0011
- #define CHN_ADC4 0100
- #define CHN_ADC5 0101
- #define CHN_ADC6 0110
- #define CHN_ADC7 0111
- /** BIT JOIN TO UINT32 **/
- #define ADC_CHN_BIT_CONST( Q0, Q1, Q2, Q3, Q4, Q5, Q6, Q7 ) ( 0b ## Q0 ## Q1 ## Q2 ## Q3 ## Q4 ## Q5 ## Q6 ## Q7 )
- #define ADC_CHN_BIT_EVAL( Q0, Q1, Q2, Q3, Q4, Q5, Q6, Q7 ) ADC_CHN_BIT_CONST( Q0, Q1, Q2, Q3, Q4, Q5, Q6, Q7 )
- #define ADC_CHN_BIT_COMBINE( Q0, Q1, Q2, Q3, Q4, Q5, Q6, Q7 ) ADC_CHN_BIT_EVAL( Q7, Q6, Q5, Q4, Q3, Q2, Q1, Q0 )
- /**
- * ADC SENSOR CHANNELS
- * Analog sensor channels, in order of reading
- */
- static const uint32_t adc_channel_mux_bits = ADC_CHN_BIT_COMBINE( CHN_ADC0, CHN_ADC1, CHN_ADC2, CHN_ADC3, CHN_ADC4, CHN_ADC5, CHN_ADC6, CHN_ADC7 );
- /** ADC CONVERSION VARIABLES **/
- volatile uint8_t adc_channel_samples = ADC_SENSOR_SAMPLES, adc_channel_index, adc_read_value, adc_reading_samples = 0;
- volatile uint8_t adc_channel_value[ ADC_SENSOR_CHANNELS ], *adc_channel_readings;
- volatile uint16_t adc_current_sensor_sum;
- volatile uint32_t adc_current_channel = adc_channel_mux_bits;
- /**
- * SETUP ADC READING
- */
- volatile uint8_t* setup_adc_sweep( void ){
- // set reference to vcc
- ADMUX |= _BV(REFS0);
- ADMUX &= ~(_BV(REFS1));
- // align result to the left, we will only use 8 bits of resolution
- ADMUX |= ( _BV(ADLAR) );
- // enable auto triggering and interrupt on conversion complete
- ADCSRA |= ( _BV(ADIE) );
- // set divider to 8, for fast ADC clock rate
- ADCSRA &= ~( _BV(ADPS2) );
- ADCSRA |= ( _BV(ADPS1) | _BV(ADPS0) );
- // disable digital input buffers
- DIDR0 |= ( _BV(ADC5D) | _BV(ADC4D) | _BV(ADC3D) | _BV(ADC2D) | _BV(ADC1D) | _BV(ADC0D) );
- // enable ADC peripheral
- ADCSRA |= _BV(ADEN);
- // allocate memory for ADC readings
- adc_channel_readings = (uint8_t*) malloc( sizeof(uint8_t) * ADC_SENSOR_CHANNELS );
- return adc_channel_readings;
- }
- /**
- * START ADC SWEEP
- */
- void start_adc_sweep( void ){
- // reset variables
- adc_channel_samples = ADC_SENSOR_SAMPLES;
- adc_current_channel = adc_channel_mux_bits;
- adc_channel_index = adc_current_sensor_sum = 0;
- // set starting channel
- ADMUX = ((uint8_t)( ADMUX & 0xF0 ) + (uint8_t)( adc_current_channel & 0x0F ));
- // start conversion
- ADCSRA |= _BV(ADSC);
- // set a fixed number of samples
- adc_reading_samples = ADC_SENSOR_CHANNELS * ( ADC_SENSOR_SAMPLES + 1 );
- // copy the new readings into a stable array
- for( uint8_t i = 0; i < ADC_SENSOR_CHANNELS ; i++ )
- *( adc_channel_readings + i ) = adc_channel_value[ i ];
- }
- /**
- * ADC INTERRRUPT
- * Triggered when ADC conversion is complete
- */
- ISR( ADC_vect ){
- // store the current conversion
- adc_read_value = ADCH;
- // check for a channel change
- if( adc_channel_samples != 0 ){
- // start the next conversion
- if( adc_reading_samples != 1 ) ADCSRA |= _BV(ADSC);
- // add up the result
- if( adc_channel_samples != ADC_SENSOR_SAMPLES ) adc_current_sensor_sum += adc_read_value;
- adc_channel_samples--;
- } else {
- // switch to the next channel
- if( adc_current_channel == 0UL ) adc_current_channel = adc_channel_mux_bits;
- else adc_current_channel >>= 4;
- // change ADC channel
- ADMUX = ((uint8_t)( ADMUX & 0xF0 ) + (uint8_t)( adc_current_channel & 0x0F ));
- // start the next conversion
- if( adc_reading_samples != 1 ) ADCSRA |= _BV(ADSC);
- // reset channel samples
- adc_channel_samples = ADC_SENSOR_SAMPLES;
- // calculate and save the mean value
- adc_channel_value[ adc_channel_index ] = (uint8_t)((uint16_t)(( adc_current_sensor_sum + adc_read_value ) / ADC_SENSOR_SAMPLES ));
- // reset the sensor sum
- adc_current_sensor_sum = 0;
- // increase sensor index
- if( ++adc_channel_index == ADC_SENSOR_CHANNELS ) adc_channel_index = 0;
- }
- // decrease total samples counter
- adc_reading_samples--;
- }
- volatile uint8_t *sensors;
- void setup(){
- Serial.begin( 115200 );
- sensors = setup_adc_sweep();
- }
- void loop(){
- uint32_t _start = micros(), _end;
- start_adc_sweep();
- while( adc_reading_samples != 0 );
- _end = micros();
- Serial.print( "Read in " ); Serial.print( _end - _start ); Serial.print( "us \t" );
- for( uint8_t i = 0; i < ADC_SENSOR_CHANNELS ; i++ ){
- Serial.print( *(sensors+i) ); Serial.print( "\t" );
- }
- Serial.println( "" );
- delay(50);
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement