ADC

Go To Last Post
12 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

i'm trying to get the adc work, but for some reason i don't get and i don't really understand it.

when i use the internal ref of 2.56v.
ADMUX will be: ADMUX = (1<<7)|(1<<6);. since MUX0...MUX4 = 0, ADC0 is my input.

if i understand this correctly then, when i put 2v on ADC0, some leds will burn because i read both ADCL and ADCH and make them visible on the leds.

my question:
- do i understand the working of the ADC correctly?
- do i have to make PORTA an input because i use ADC0 as input for the voltage?

Thanks, Robbin

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

For most of your questions, we need to know which AVR model you are referring to 'cause the answers will vary.

It appears you are writing in C. Knowing which brand of compiler will help to point to examples.

For a good discussion of ADC try the worked example at www.avrbeginners.net

[Be sure to read ADCH and ADCL in the correct order]

Lee

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

We could tell in seconds if we saw the a/d init instructions. Since it is very flexible, there are different inits for 8 bit or 10 bit mode, single conversion or free running mode, etc. In general, You set the start conversion bit, then hang in a loop waiting for that bit to go low. Then you can read result=ADC to get all 10 bits.

Imagecraft compiler user

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Also show us the code that you are using to initialize and read the ADC. Just putting a voltage on the inputs and then reading the ADC registers is not enough.

Regards,
Steve A.

The Board helps those that help themselves.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

#include 

unsigned char channel=0; // measure ADC0
int analog_result, adlow, adhigh;

void main(void)
{

    DDRB = 0x00;   //  We put port B pins in input mode  
    PORTB = 0x00;   // no internal pull-up
    DDRD = 0xFF;    // We put port D pins in output mode  
    PORTD = 0xFF; //  we activate the internal pull-up 

while (1)
      {
// use internal 2.56V ref:
ADMUX=(1<<7)|(1<<6);
ADCSRA=(1<<7);

//  start conversion
ADCSRA|= (1<<6);
while(ADCSRA== (1<<6)); // wait for result
adlow=ADCL; // read low first !!
adhigh=ADCH;
analog_result=((adhigh<<8)|(adlow & 0xFF));
PORTD = analog_result;

      };
}

i use STK500, codevision, ATmega16L.

as far as i know, you read low first then high.

i find AVRbeginners.net not usful because i program in C and not asm. thanks anyway :)

Robbin

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:

i find AVRbeginners.net not usful because i program in C and not asm.

The worked examples of peripheral devices are 90% setting I/O registers and subsequent handling. I opine that if you can't handle the "ADMUX = ...;" equivalent of "LDI ... OUT/STS ..." then you are in the wrong business. The discussion is very well done.

For setup and first ADC-read program, why not use the CV Wizard and go from there?

PORTD = 0xff; sets the output bits all high. It would enable pullups if the port (pins) were configured as inputs.

As written, the lamps may not change with your given test conditions of 2V on 2.56V reference, as you are dumping a 10-bit result to an 8-bit port.

Lee

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Why are you using signed ints for analog_result, adhigh and adlow? The result (though the upper 8 bits never makes it to a PORT) should surely be "unsigned int" and as adlow and adhigh are just being read from an unsigned 8 bit port so it doesn't make much sense for them to be any larger than "unsigned char" (and the mask of adlow with 0xFF becomes pointless)

But why not just "PORTD = ADCL;" anyway? Though I suspect you'll find the top 8 of 10 bits more interesting than the bottom 8 bits if just using one port for output. So maybe set ADLAR and just read ADCH?

Cliff

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:

while(ADCSRA== (1<<6)); // wait for result

This is never going to be true, is it? [Hint: Bit 7 is set, and other bits may be as well.]

You are never going to get good results with this code; even at 1MHz AVR clock the ADC prescaler should be used.

Again, use the CV Wizard.

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

E.g.:

#include 

#include 

#define ADC_VREF_TYPE 0xC0

// Read the AD conversion result
unsigned int read_adc(unsigned char adc_input)
{
ADMUX=adc_input | (ADC_VREF_TYPE & 0xff);
// Delay needed for the stabilization of the ADC input voltage
delay_us(10);
// Start the AD conversion
ADCSRA|=0x40;
// Wait for the AD conversion to complete
while ((ADCSRA & 0x10)==0);
ADCSRA|=0x10;
return ADCW;
}
...
// ADC initialization
// ADC Clock frequency: 125.000 kHz
// ADC Voltage Reference: Int., cap. on AREF
// ADC Auto Trigger Source: None
ADMUX=ADC_VREF_TYPE & 0xff;
ADCSRA=0x85;

...

while (1)
      {
      frog = read_adc(0);

      // Place your LED code here

      }
}

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

thanks, i will study the code and replace it with mine. my code was a combination with the datasheet and codes from others. i couldn't tell you what the reasons are for some codes.

thanks again,

Robbin

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Provak wrote:
thanks, i will study the code and replace it with mine. my code was a combination with the datasheet and codes from others. i couldn't tell you what the reasons are for some codes.

thanks again,

Robbin

the new code with the wizard:


#include 

#define ADC_VREF_TYPE 0xC0

// Read the AD conversion result
unsigned int read_adc(unsigned char adc_input)
{
ADMUX=adc_input|ADC_VREF_TYPE;
// Start the AD conversion
ADCSRA|=0x40;
// Wait for the AD conversion to complete
while ((ADCSRA & 0x10)==0);
ADCSRA|=0x10;
return ADCW;
}

// Declare your global variables here

void main(void)
{


    DDRB = 0xFF;   //  We put port B pins in output mode  
  PORTB = 0xFF;   // put all leds in off state 

// ADC initialization
// ADC Clock frequency: 115,000 kHz
// ADC Voltage Reference: Int., cap. on AREF
// ADC Auto Trigger Source: None
ADMUX=ADC_VREF_TYPE;
ADCSRA=0x85;

while (1)
      {
      read_adc(0x00);
      PORTB = ADCW;

      };
}

is this correct ?

when i load the program, i connect 2v on the ADC0 and the other to the gnd on the chip,
is this correct too ?

for some reason i don't really understand this shit. grr i have search almost through the whole internet :(. ( i know that ain't possible, but i have the feeling that i did that :P).

can you guys help me :(.

Thanks,
Robbin

Robbin

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

it is working now,

thanks for the help.