Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

[SOLVED] Multiple ADC channels

Status
Not open for further replies.

fsoender

Member level 2
Joined
Aug 7, 2012
Messages
45
Helped
0
Reputation
0
Reaction score
0
Trophy points
1,286
Activity points
1,553
I need some help with my project. Im reading a accelerometer with ADC on port PA0 on a Atmega16. Im reading only X-axes. I want to add Y and Z also, but I dont know how.
Im reading the input with TeraTerm, line by line downwards. I want the y and Z to be added on the side of the X value.
IM using AVR studio 4.

Can anyone help me with this?

Code:
 #include<avr/io.h> 
#include<util/delay.h> 
#include<avr/interrupt.h> 
  


#define LONGOUT 7 
char buffer[LONGOUT]; 

void adc_init(void); 
unsigned int adc_read(void); 
void adc_conversion(uint16_t); 




// ADC configuration 
void ADC_init(void) { 
  ADMUX=(1<<REFS0); 
  ADCSRA=(1<<ADEN)|(7<<ADPS0); 
} 

uint16_t ADC_get_reading(void) { 
  ADCSRA |= (1<<ADSC); 
  while(ADCSRA & (1<<ADSC)); 
  return ADC; 
} 

uint16_t ADC_read(void) { 
  uint8_t i; 
  uint16_t retval = 0; 
  ADC_get_reading(); // dummy read - just discarded 
  for (i=0; i<8; i++) { 
    retval += ADC_get_reading(); 
  } 
  return retval / 8; 
} 


void init_UART(void) 
{ 
   UCSRB = ((1 << RXCIE) | (1 << RXEN) | (1 << TXEN)); 
    UCSRC = ((1 << UCSZ1) | (1 << UCSZ0)); 
    
    //Baud rate till 19200.  
    UBRRL = 25; 
    UBRRH = 0; 
} 


void uart_sendchar(char c) { 
   while(!(UCSRA & (1<<UDRE))); 
   UDR = c; 
} 

void uart_printstring(char * str) { 
  while (*str) { 
   uart_sendchar(*str++); 
  } 
} 


void main(void) { 
    
 DDRC = 0x00;    
 init_UART(); 
 ADC_init(); 
  
  
  while(1) 
  { 
    if (PINC & 0x01) //If PortC pin 0 is True, program stops. 
   { 
 ADC_read(); 
            
 char buffer[8]; 
 itoa(ADC, buffer, 10); 
 uart_printstring(buffer); 
 uart_printstring("\r\n"); 
 _delay_ms(1500); 
  
    } 
  } 
}
 

You can use this function, call it with the number of the channel you want to convert (0,1,2....)


Code C - [expand]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
/*****************************************************************************
** Function name:   read_adc    
**
** Descriptions:    makes an ADC measurment in the specified channel
**                  
** parameters:      unsigned char adc_input: channel number
** Returned value:  unsigned int: returns 0-1023
** 
*****************************************************************************/
unsigned int read_adc(unsigned char adc_input)
{
    // clear the channel bits ane set the new channel
    ADMUX =  (ADMUX & 0xF8) | adc_input;
    
    // 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 & (1 << ADSC)) 
 
    // return result
    return ADCW;
}



just modify it to do 8 readings and return the average like you did in your code
 

Thanks!
Sorry im new to this, but how do I call it, and where in my program?
 

You call it from main.

In your current code you are calling ADC_read(); which in turn calls ADC_get_reading
Also in your code you don't store the result of ADC_read(); anywhere and you just use the ADC register value (last conversion result, not the calculated average)

If you use the code I have provided you can replace ADC_read(); with read_adc(x) where x is the channel number and store the result to the variables.

You are supposed to do
Code:
uint16_t x,y,z;

x=read_adc(0); 
y=read_adc(1);
z=read_adc(2);
 

Thanks, That worked fine :)

My last question is:

Im now only displaying the X-axe on TeraTerm, I want all of the axes to show up like this with their values:

x-Value y-Value z-Value

xxxx xxxx xxxx
 

This is what makes the conversion and converts the values 0-1023 to four ascii characters in buffer[0] buffer[1] buffer[2] buffer[3]
Code:
itoa(ADC, buffer, 10);

you cant to convert x to the above positions , y to buffer[5] buffer[6] buffer[7] buffer[8]
and z to buffer[10] buffer[11] buffer[12] buffer[13]

buffer needs to be bigger
Code:
#define LONGOUT 15 
char buffer[LONGOUT]="0000 0000 0000";

itoa(x, buffer, 10);
itoa(y, &buffer[5], 10);
itoa(z, &buffer[10], 10);

then send buffer to uart
 

I didnt get it to work, see any misstake(s):

Code:
#include<avr/io.h> 
#include<util/delay.h> 
#include<avr/interrupt.h> 
  


#define LONGOUT 15 
char buffer[LONGOUT]="0000 0000 0000";
 

void adc_init(void); 
unsigned int adc_read(void); 
void adc_conversion(uint16_t); 

unsigned char x;
unsigned char y;
unsigned char z;


// ADC configuration 
void ADC_init(void) { 
  ADMUX=(1<<REFS0); 
  ADCSRA=(1<<ADEN)|(7<<ADPS0); 
} 

uint16_t ADC_get_reading(void) { 
  ADCSRA |= (1<<ADSC); 
  while(ADCSRA & (1<<ADSC)); 
  return ADC; 
} 

unsigned int read_adc(unsigned char adc_input)
{
    // clear the channel bits ane set the new channel
    ADMUX =  (ADMUX & 0xF8) | adc_input;
    
    // 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 & (1 << ADSC)) 
 
    // return result
    return ADCW;
}


void init_UART(void) 
{ 
   UCSRB = ((1 << RXCIE) | (1 << RXEN) | (1 << TXEN)); 
    UCSRC = ((1 << UCSZ1) | (1 << UCSZ0)); 
    
    //Baud rate till 19200.  
    UBRRL = 25; 
    UBRRH = 0; 
} 


void uart_sendchar(char c) { 
   while(!(UCSRA & (1<<UDRE))); 
   UDR = c; 
} 

void uart_printstring(char * str) { 
  while (*str) { 
   uart_sendchar(*str++); 
  } 
} 


void main(void) { 
    
 DDRC = 0x00;    
 init_UART(); 
 ADC_init(); 
  
  
  while(1) 
  { 
    
x=read_adc(0); 
y=read_adc(1);
z=read_adc(2);
            
 char buffer[8];
 itoa(x, buffer, 10);
 itoa(y, &buffer[5], 10);
 itoa(z, &buffer[10], 10);
 
  
 uart_printstring(buffer); 
 uart_printstring("\r\n"); 
 _delay_ms(1500); 
  
    } 
  }
 

You have a global variable
Code:
char buffer[LONGOUT] = "0000 0000 0000";

and then you add a local variable that hides the visibility of the global one and in adition has a wrong length, remove it
Code:
char buffer[8];
 

Oh, my misstake, but it still doesnt work.
Is rest of the code right?
I still only get one column with value...
 

Yes, itoa adds a null after the result

A quick fix is

Code:
#define LONGOUT 15 
char buffer[LONGOUT]="0000 0000 0000";

itoa(x, buffer, 10);
buffer[4]=' ';
itoa(y, &buffer[5], 10);
buffer[9]=' ';
itoa(z, &buffer[10], 10);
 

That didnt help either, it still gives me only one column in TeraTerm.
 

Now I'm not sure why.

By one column you mean the x value, 4 digits?

- - - Updated - - -

Add
Code:
#include <stdio.h>

//and use
sprintf(buffer,"%.4u %.4u %.4u ",x,y,z);

I think the problem was the variable width of the result generated by the itoa, the null character was not always in the same location
 

Yes I want one coulmn with x value, one with y value and one with z value:

0000 0000 0000
0000 0000 0000

and so on...

Sorry, but I cant get this to work. Am I missing something here?

Code:
while(1) 
  { 
    
x=read_adc(0); 
y=read_adc(1);
z=read_adc(2);
            
 
itoa(x, buffer, 10);
buffer[4]=' ';
itoa(y, &buffer[5], 10);
buffer[9]=' ';
itoa(z, &buffer[10], 10);
 
sprintf(buffer,"%.4u %.4u %.4u ",x,y,z);
 //uart_printstring(buffer); 
 //uart_printstring("\r\n"); 
 _delay_ms(1500); 
  
    } 
  }
 
Last edited:

remove all this
Code:
itoa(x, buffer, 10);
buffer[4]=' ';
itoa(y, &buffer[5], 10);
buffer[9]=' ';
itoa(z, &buffer[10], 10);

I have replaced the three itoa with the sprintf

- - - Updated - - -

and uncomment the uart

- - - Updated - - -

the sprintf just converts the three values to ascii and writes the buffer array, you still need the uart function to send then to the pc
 

That worked :)

Thank you so much for your time and help Alexan_e!!!

- - - Updated - - -

Next now is to read the ADC 8 times and get the average value, any suggestions?
 

Status
Not open for further replies.

Similar threads

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top