1. Welcome to our site! Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.
    Dismiss Notice

ATMega32 ADC problem

Discussion in 'AVR' started by Cantafford, Jan 14, 2017.

  1. Cantafford

    Cantafford Member

    Joined:
    Jul 5, 2015
    Messages:
    251
    Likes:
    2
    Hey,

    I'm reading the value of a POT with the ADC of ATMega32 and displaying it on an LCD.
    I have initialised the ADC to 10 bit result left justified. I convert the result to a string then try to display it on a LCD.

    I have one problem. When the pot is at it's highest value I get 1023 displayed on my LCD. All good. But when I move it downwards my values don't coincide with the position of the pot. I get weird values like 6035 or 9055 that shouldn't be there at all no matter the position of the pot. Please help me correct this.

    This is the code:
    Code (text):

    /*
     * AVRGCC1.c
     *
     * Created: 1/10/2017 10:10:28 AM
     *  Author: Paul
     */

    #include <avr/io.h>
    #include <stdlib.h>
    #include <util/delay.h>
    #include <avr/interrupt.h>
    #include "lcd.h"

    void InitLCD();

    char Buffer[4];

    int main(void)
    {
        InitLCD();
         
        ADCSRA |= 1<<ADPS2; // prescaler
        ADMUX  |= 1<<ADLAR; // result left justified(we'll use 8 bits)
        ADMUX  |= 1<<REFS0; // using AVCC pin as reference
        ADCSRA |= 1<<ADIE;  // enable ADC interrupts
        ADCSRA |= 1<<ADEN;  // turn the ADC ON
        sei();                // enable global interrupts
        ADCSRA |= 1<<ADSC;  // start FIRST conversion. Setting bit ADSC will start the conversion
           
        while(1)
        {  
        }
    }

    void InitLCD()
    {
        LCDInit(LS_NONE|LS_NONE);
        LCDClear();
        LCDWriteString("ADC Program ");
        _delay_ms(1500);
        LCDClear();
    }

    ISR(ADC_vect)
    {
     //uint16_t tenBitValue = ADC; // put the ADC value into the tenBitValue variable

     itoa(ADC, Buffer, 10); // convert ADC result to base 10 number
     LCDWriteStringXY(0,0,Buffer);
     ADCSRA |= 1<<ADSC;  // start NEXT conversion
    }
     
     
  2. Ian Rogers

    Ian Rogers Super Moderator Most Helpful Member

    Joined:
    Mar 28, 2011
    Messages:
    9,251
    Likes:
    911
    Location:
    Rochdale UK
    Looks to me like you are writing a three digit number and a two digit number over a four digit number..

    You need to use sprintf() rather than itoa() with sprintf() you can do this

    sprintf(buffer," %4d ", ADC);

    and then it will print right justified and it will look correct..
     
  3. wkrug

    wkrug Active Member

    Joined:
    May 30, 2010
    Messages:
    280
    Likes:
    29
    Location:
    Germany
    Another problem:
    You should never put an output or an math routine into an interrupt.
    While this interrupt runs no other interrupt can be computed. That will give You ugly overrun problems.
    It's better to store the ADC Result into a variable ( like adc_value ), set a marker ( variable e.g. NEWADC ) and make the Output in a function in the main loop.
    Like:
    char main (void)
    {...
    ...
    while(1)
    {...
    ...
    if ( NEWADC > 0 )
    {
    NEWADC = 0;
    disp_out ( adc_value );
    }
    ...
    }
    ....
    return(0);
    }

    ISR(ADC_vect)
    {
    adc_value=ADC;
    NEWADC=1;
    ADCSRA |= 1<<ADSC; // start NEXT conversion
    }
     

Share This Page