atmega8 adc - always same readings

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

Hi everybody,

 

I know this subject's been done over and over again, there are plenty of tutorials on the internet but still I can't get my atmega8 convert voltage more than once. I do the first reading without saving its value ("This first conversion performs initialization
of the ADC."), and then in a while loop I read adc0 value every ~200ms. The problem is readings never change - they always are the same as the first one - I've got a floating wire connected to adc0 which on the other side I connect to gnd and then to vcc to check the results.

Here is my code:

void adc_init()
{
    ADCSRA = (1 << ADPS2); // 16 prescaler
    ADMUX = (1 << REFS0) | (1 << ADLAR);
    ADCSRA |= (1 << ADEN);
}

int  adc_read(uint8_t channel)
{
    int result;

    channel &= ((1 << MUX0) | (1 << MUX1) | (1 << MUX2) | (1 << MUX3));
    ADMUX &= ~((1 << MUX0) | (1 << MUX1) | (1 << MUX2) | (1 << MUX3));
    ADMUX |= channel;

    ADCSRA |= (1 << ADSC);

    while(ADCSRA & (1 << ADSC));

    result = ((ADCH & ((1 << 0) | (1 << 1))) << 8) + ADCL;
    return result;
}

#define F_CPU 1000000UL

int main()
{
    DDRC &= ~(1 << PC0);
    adc_init();
    _delay_ms(200);
    adc_read(0);

    int bat0, oldBat0, i = 0;

    while(1)
    {
        char bat0string[8];
        bat0 = adc_read(0);

        if(i != 0 && bat0 != odlBat0)
        {
        }
        else if(i != 0 && bat0 == oldBat0)
        {
        }

        _delay_ms(200);
        i += 1;
    }
}

My code always goes to the second if (where bat0 == oldbat0)... I can't find any useful info in the datasheet - maybe you guys will help me out...

 

Some more info:

- AVCC is connected to VCC signal

- say adc0 pin is connected to GND, I get readings of 0, then I connect adc0 pin to vcc (without disconnecting atmega from vcc) and  the reading doesn't change

- on the other hand - say I got a reading of 0 (adc0 connected to gnd), I disconnect atmega from vcc, connect adc0 to vcc and then connect vcc to usb (I always us it for tests), the reading is 960 - of course it won't change if I reconnect adc0 to gnd - only after a reset

- I tried shutting adc down (by setting ADEN to 0) and then initializing it again but it didn't work

 

Another question is - why am I getting 960 not 1023, when I connect adc0 pin to vcc? That's strange as well.

 

Best regards,

Aranha

This topic has a solution.
Last Edited: Mon. Oct 30, 2017 - 07:58 PM
This reply has been marked as the solution. 
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Instead of this mess:

 result = ((ADCH & ((1 << 0) | (1 << 1))) << 8) + ADCL;

try this:

 result = ADC;

 

Jim

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

You are setting the ADLAR bit (Left adjust) but then trying to read as if right adjusted (ki0bk has valid code for reading a right adjusted register).

You state AVCC is connected to VCC, but do you have a capacitor on AREF?

 

Edit: typo

David (aka frog_jr)

Last Edited: Mon. Oct 30, 2017 - 07:39 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thank you for your replies!

I cannot explain how embarrassed I am for this ADLAR bit being set to 1 ;). After leaving it as 0 and returning ADC instead of my messy (still not working, dunno why) result, it all works. When it comes to the capacitor on AREF - I know there should be one but I can't find any information about it in the documentation. In other sections it's kinda clear - use, say 12-22 pF, but in ADC section I can't find any table or anything else. Can you help me out with that and I promise I'll go away instantly? :D

 

edit: right now the readings are just great so both of your replies helped.

Last Edited: Mon. Oct 30, 2017 - 08:03 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Aranha wrote:
(still not working, dunno why)
That does not guarantee (from datasheet):

If the result is left adjusted and no more than 8-bit precision is required, it is sufficient to read
ADCH. Otherwise, ADCL must be read first, then ADCH, to ensure that the content of the Data
Registers belongs to the same conversion. Once ADCL is read, ADC access to Data Registers
is blocked. This means that if ADCL has been read, and a conversion completes before ADCH is
read, neither register is updated and the result from the conversion is lost. When ADCH is read,
ADC access to the ADCH and ADCL Registers is re-enabled.

 

David (aka frog_jr)

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

Aranha wrote:
When it comes to the capacitor on AREF...

 

David (aka frog_jr)

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

Yes, I'm looking right at it but sadly I'm not a electronic engineer so I have no idea how to calculate the capacitor's value.

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

Typically, 100nF...

David (aka frog_jr)

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

frog_jr wrote:

Typically, 100nF...

Also know as a 0.1uf

 

Jim