Wednesday 12 September 2012

Analog to digital sample code

First i bring a simple sample code on an analog to digital conversion





#include <avr/io.h>
int ADC_Read;        //Variable used to store the value read from the ADC converter
#define PB5 5
int main(void){

  DDRB |= (1<<PB5);    ///PB5/digital 13 is an output

  ADCSRA |= ((1<<ADPS2)|(1<<ADPS1)|(1<<ADPS0));    //Prescaler at 128 so we have an 125Khz clock source
  ADMUX |= (1<<REFS0);
  ADMUX &= ~(1<<REFS1);                //Avcc(+5v) as voltage reference
  ADCSRB &= ~((1<<ADTS2)|(1<<ADTS1)|(1<<ADTS0));    //ADC in free-running mode
  ADCSRA |= (1<<ADATE);                //Signal source, in this case is the free-running
  ADCSRA |= (1<<ADEN);                //Power up the ADC
  ADCSRA |= (1<<ADSC);                //Start converting

  for(;;){            //The infinite loop
    ADC_Read = ADCW;    //Read the ADC value, really that's just it
    if(ADC_Read > 512){
      PORTB |= (1<<PB5);    //If ADC value is above 512 turn led on
    }
    else {
      PORTB &= ~(1<<PB5);    //Else turn led off
    }
  }

  return 0;
}

This example demonstrates the use of the ADC of a ATmega328 
using the internal reference voltage  
To adapt to other AVR and / or other reference voltages 
see comments in this tutorial and in the data sheet




// This example demonstrates the use of the ADC of a ATmega169 
// using the internal reference voltage of nominally 1.1 V 
// To adapt to other AVR and / or other reference voltages 
// see comments in this tutorial and in the data sheet

/* Initialize the ADC */
void ADC_Init ( void )  {

  uint16_t result;

  // Select voltage reference for the ADC=> Avcc(+5v) 
  ADMUX = (1<< REFS0);
  ADMUX &= ~(1<<REFS1);                

  // Bit ADFR ("freerunning") in ADCSRA stands at power 
  // already set to 0, ie single conversion 
  ADCSRA = (1<<ADPS2)|(1<<ADPS1)|(1<<ADPS0) ;      // frequency prescaler 
  ADCSRA |= (1<<ADEN) ;                   // enable ADC

  /* After activating the ADC is a "dummy readout" recommended reading
   So a value and rejects this in order to "warm up" the ADC */

  ADCSRA |= ( 1 << ADSC ) ;                   // an ADC conversion 
  while  ( ADCSRA & ( 1 << ADSC )  )  {          // wait for the conversion is complete 
  } 
  /* ADCW must be read once, otherwise the result of the next
   Conversion is not taken. */
  result = ADCW;
}

/* ADC single measurement */
uint16_t ADC_Read (uint8_t channel) 
{ 
  // channel choose to influence without other bits 
  ADMUX = (ADMUX &~ (0xF0))|(channel &0x0F) ;
  ADCSRA |= (1<<ADSC) ;             // a  "single conversion" 
  while  (ADCSRA & (1<<ADSC) ) {    // wait for the conversion is complete 
  } 
  return ADCW;                     // ADC read and return 
}

/* ADC with multiple measurement  */
/* Note: Range of sum variables */
uint16_t ADC_Read_Avg (uint8_t channel, uint8_t nsamples) 
{ 
  uint32_t sum = 0 ;

  for  (uint8_t i = 0; i< nsamples;  i++ )  { 
    sum += ADC_Read (channel) ;
  }

  return  ( uint16_t ) ( sum/nsamples ) ;
}


/* Example calls: 
 */

int main ( ) 
{
  uint16_t adcval;
  uint16_t adcval1;
  ADC_Init ( ) ;

  while (  1  )  { 
    adcval= ADC_Read(0) ;   // channel 0 
    // do something with adcval

    adcval1= ADC_Read_Avg(2,4) ;   // Channel 2, mean of 4 measurements 
    // do something with adcval 
  } 
}

Reference (Part. 1) : http://dubworks.blogspot.co.uk/2012/08/beyond-gpio-pins-peripherals-intro-to.html

2 comments:

  1. can i get a code for printing the values of adc values from a ldr in the serial monitor.Im using Atmega328p in arduino uno board.

    ReplyDelete
  2. Just serial print the result. If youre using arduino ide, you can use their serial library, and consult their reference for it

    ReplyDelete

Feel free to contact me with any suggestions, doubts or requests.

Bless