coding query in ADC in atmega 328

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

i want to print the digital output of adc on serial monitor .

so when i read the registers ADCL and ADCH i get the binary form of my digital output ,now i want to convert this binary form into decimal form so that i can read the potientiometer values.

so for that i made the function bindec() which converts my binary into decimal.

now in bindec() i am storing decimal value of myy binary in    dec   variable which is integer 

now when i am printing dec variable on serial monitor  wiyh Uart_txchar() , it is printing ASCII value as u can see in giveen pics .

so any suggestion ?????????

Attachment(s): 

This topic has a solution.

Kunal Gupta

Last Edited: Tue. Jan 7, 2020 - 06:00 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

what you read from the ADC is already an integer in binary from. You don't need to convert it to decimal,  [BCD form which is what your function appears to do] you need to convert to ASCII. There are functions like sprintf() which are designed for this, though you can write your own.

 

Also please don't use screenshots via your mobile phone to post code.... post the actual code here using the formatting features of the forum.

Writing code is like having sex.... make one little mistake, and you're supporting it for life.

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

Post your code. Somethings amiss in your functions.

Jim

I would rather attempt something great and fail, than attempt nothing and succeed - Fortune Cookie

 

"The critical shortage here is not stuff, but time." - Johan Ekdahl

 

"Step N is required before you can do step N+1!" - ka7ehk

 

"If you want a career with a known path - become an undertaker. Dead people don't sue!" - Kartman

"Why is there a "Highway to Hell" and only a "Stairway to Heaven"? A prediction of the expected traffic load?"  - Lee "theusch"

 

Speak sweetly. It makes your words easier to digest when at a later date you have to eat them ;-)  - Source Unknown

Please Read: Code-of-Conduct

Atmel Studio6.2/AS7, DipTrace, Quartus, MPLAB, RSLogix user

Last Edited: Fri. Jan 3, 2020 - 11:41 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

glitch wrote:

what you read from the ADC is already an integer in binary from. You don't need to convert it to decimal,  [BCD form which is what your function appears to do] you need to convert to ASCII. There are functions like sprintf() which are designed for this, though you can write your own.

One thing ..the output of adc is stored in register ADCH and ADCL ...so now i can read these registers in binary form ...so i am using bit () now but i want to get the values like 263, 150, 500 on moving the knob of potentiometer .
So what should i do ...
U r suggesting me to convert it directly to ascii??
And sprintf() is used for strings ??? How can i use here

 

here is the code

/*
 * GccApplication4.cpp
 *
 * Created: 1/3/2020 1:30:55 PM
 * Author : kunal
 */ 

#include <avr/io.h>
#include <util/delay.h>
void UART_Init();
void UART_TxChar(char data);
char UART_RxChar();
void bit(uint8_t val);
void printString( char myString[]);
void USART_bindec(uint8_t val);
void bindec(int16_t x);

void UART_Init()
{
    UBRR0L = 103;
    UCSR0B = (1<<TXEN0)|(1<<RXEN0);
    UCSR0C = (1<<UCSZ00)|(1<<UCSZ01);
}

void UART_TxChar(char data)
{
    while((UCSR0A & (1<<UDRE0))==0);
    UDR0 = data;
    
}

char UART_RxChar()
{
    while( (UCSR0A & (1<<RXC0))==0);
    return UDR0;

}

void bit(uint8_t val)
{
    int8_t ptr;
    for(ptr=7;ptr>=0;ptr--)
    {
        if ((val & (1<<ptr))==0)
        {
            UART_TxChar('0');
        }
        else
        {
            UART_TxChar('1');
        }
    }
}
  void printString(  char myString[])      /////to print any string
  {
      int i = 0;
      while (myString[i])
      {
          UART_TxChar(myString[i]);
          i++;
      }
  }
  void bindec(int16_t x)
  { 
      char dec;
      uint8_t wei=1;
      while(x!=0)
    {   dec=dec+((x%10)*wei);
        x=x/10;
        wei=wei*2;
        UART_TxChar(dec);
    }
      //printString(dec);
  }
  
      
  
int main(void)
{UART_Init();
    ADCSRA=0x87;
    ADMUX=0b01100000;
  
    while (1) 
    { ADCSRA|=(1<<ADSC);
      while((ADCSRA&(1<<ADIF))==0);
     bit(ADCL);
     bindec(ADCL);
    printString("\n");
     bit(ADCH);
     bindec(ADCH);
     printString("\n");
   _delay_ms(5000);

    } 
    return 0;
}

 

Kunal Gupta

Last Edited: Sat. Jan 4, 2020 - 12:12 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

yes you are reading two 8 bit values, though you can also read it as a single 16 bit value [the compiler will do the 2 reads for you. Either way it is an integer, and no need to convert... you just need to combine.

uint16_t adcval = ADCL | ((uint16_t)ADCH<<8);

Though I'm willing to bet your device. header has ADCW defined and you can just do

uint16_t adcval = ADCW;

the compiler will take care of reading ADCL and ADCH in the right order for you.

 

Now that you have the full 16bit value, you can output in ASCII form using any of the standard C library routines for converting and outputting.

[hint google "sprintf" to learn how to use it]

 

Writing code is like having sex.... make one little mistake, and you're supporting it for life.

Last Edited: Sat. Jan 4, 2020 - 01:02 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

glitch wrote:
[hint google "sprintf" to learn how to use it]

 

ITOA is another, but clunky at times option as well.

 

JIm

I would rather attempt something great and fail, than attempt nothing and succeed - Fortune Cookie

 

"The critical shortage here is not stuff, but time." - Johan Ekdahl

 

"Step N is required before you can do step N+1!" - ka7ehk

 

"If you want a career with a known path - become an undertaker. Dead people don't sue!" - Kartman

"Why is there a "Highway to Hell" and only a "Stairway to Heaven"? A prediction of the expected traffic load?"  - Lee "theusch"

 

Speak sweetly. It makes your words easier to digest when at a later date you have to eat them ;-)  - Source Unknown

Please Read: Code-of-Conduct

Atmel Studio6.2/AS7, DipTrace, Quartus, MPLAB, RSLogix user

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

jgmdesign wrote:

glitch wrote:
[hint google "sprintf" to learn how to use it]

 

ITOA is another, but clunky at times option as well.

 

JIm

 

Yep, just suggested sprintf as it's more generalized and applicable to other conversions... having said that it is heavy, but not likely an issue in this case.

Writing code is like having sex.... make one little mistake, and you're supporting it for life.

This reply has been marked as the solution. 
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0
/*
 * GccApplication4.cpp
 *
 * Created: 1/3/2020 1:30:55 PM
 * Author : kunal
 */ 
#include <avr/io.h>
#include <util/delay.h>
#include <stdio.n>

void UART_Init();
void UART_TxChar(char data);
char UART_RxChar();
void bit(uint8_t val);
void printString( char *myString);

void UART_Init()
{
    UBRR0L = 103;
    UCSR0B = (1<<TXEN0)|(1<<RXEN0);
    UCSR0C = (1<<UCSZ00)|(1<<UCSZ01);
}
void UART_TxChar(char data)
{
    while((UCSR0A & (1<<UDRE0))==0);
    UDR0 = data;
    
}
char UART_RxChar()
{
    while( (UCSR0A & (1<<RXC0))==0);
    return UDR0;
}

void bit(uint8_t val)
{
    uint8_t count = 8;
    while(count--)
    {
        if (val & 0x80)
        {
            UART_TxChar('1');
        }
        else
        {
            UART_TxChar('0');
        }
        val <<=1;
    }
}
  void printString(char *myString)      /////to print any string
  {

      while (*myString)
      {
          UART_TxChar(*myString++);
      }
  }
  
      
  
int main(void)
{
    
    char sbuff[100];
    
    UART_Init();
    ADCSRA=0x87;
    ADMUX=0b01100000;
  
    while (1) 
    { 
        //put the adc code in its own function!!
        ADCSRA |= (1<<ADSC);
        while( ADCSRA & (1<<ADSC) );
    
        bit(ADCH);
        bit(ADCL);
        printString("\n");
        
        sprintf(sbuff,"%05d\n",ADCW);
        printString(sbuff);
        _delay_ms(5000);
    } 
    return 0;
}

I've simplified it a bit. Note - I've not tested it. Also note how to post code so it is readable -look for the <> button

 

Read this: https://www.nongnu.org/avr-libc/...

 

A quick Google should get you some example code - most likely on avrfreaks. 

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

Kartman wrote:

I've simplified it a bit. Note - I've not tested it. Also note how to post code so it is readable -look for the <> button

 

Read this: https://www.nongnu.org/avr-libc/...

 

A quick Google should get you some example code - most likely on avrfreaks. 

 

A decent cleanup... note that the separate readings of ADCH and ADCL and then later ADCW will result in the prints being from different ADC readings. Practically not likely an issue, but if they were trying to debug by correlating the two, there may be some discrepancies by a LSB or two.

Writing code is like having sex.... make one little mistake, and you're supporting it for life.

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

on doing so ADCW is an 16 bit variable so it is also storing the unused 6 bits of the ADC output . and now when i am printing the value of ADCW it is varying from  -32225 to +32225

.but i want my values to vary from +1024  to -1024 as in the end my final result is of only 10 bit (as lest 6 bits or right 6 bits are unused).

suggestions???????

 

Kartman wrote:


 

 

Read this: https://www.nongnu.org/avr-libc/...

 

A quick Google should get you some example code - most likely on avrfreaks. 

 

int sprintf(char * __s,const char * __fmt... )

sends the formatted characters to string s.

this is defination of sprintf () i found on the given link .

but the arguments for sprintf() which u have written in the code and arguments written on link are different ... so i didnt understand how is sprintf() working.

 

or here in code my formatted character is ADCW and string to which it is send is sbuff.

Kunal Gupta

Last Edited: Sat. Jan 4, 2020 - 07:54 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Kunalgupta wrote:

on doing so ADCW is an 16 bit variable so it is also storing the unused 6 bits of the ADC output . and now when i am printing the value of ADCW it is varying from  -32225 to +32225

.but i want my values to vary from +1024  to -1024 as in the end my final result is of only 10 bit (as lest 6 bits or right 6 bits are unused).

suggestions???????

 

Kartman wrote:


 

 

Read this: https://www.nongnu.org/avr-libc/...

 

A quick Google should get you some example code - most likely on avrfreaks. 

 

int sprintf(char * __s,const char * __fmt... )

sends the formatted characters to string s.

this is defination of sprintf () i found on the given link .

but the arguments for sprintf() which is written in the above code and arguments written on link are different ... so i didnt understand how is sprintf() working.

 

or here in code my formatted character is ADCW and string to which it is send is sbuff.

Kunal Gupta

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

Fix up this code so we can read it easily:

 

 ADCSRA=0x87;
 ADMUX=0b01100000;

If you've set the ADLAR bit, then the 16 bit result will not be what you want.

 

 

int sprintf(char * __s,const char * __fmt... )

 

printf/sprint is what is called a 'variadic' function - that is a function that can accept a variable number of parameters. The variable paramters are denoted by the ellipsis ....

 

I wrote:

sprintf(sbuff,"%05d\n",ADCW);

the first parameter is a pointer to the destination string which I've defined as sbuff

the second parameter - the format is "%05d\n" where I have one format of zero padded, 5 characters decimal value followed by a \n. The parameter is ADCW which will get converted to a decimal string zero padded for 5 chars.

 

 

Also, don't write your SMS abbreviations - we're making an effort, so should you. As well, this is nothing specific to AVR - there's a wealth of information for you just a Google away.

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

Can I suggest %u rather than %d perhaps?