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.

How to add an avarage of 8 readings to this code for better result

Status
Not open for further replies.

fsoender

Member level 2
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 want to get a better result on my ADC port by reading it 8 times, and get an avarage meassurement, any help to get?


Code:
/* AccelerometerRead.c
 * This program demonstrates the use of ADMUX to read multiple ADC inputs.
 * Runs on a Atmega32, 8MHz, 19200 Baud.
 * Compiled using AVR Studio 4.
 * Jan 25 2013. FS.
 */


#include<avr/io.h> 
#include<util/delay.h> 
#include<avr/interrupt.h> 
#include <stdio.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); 
} 

// Getting reading from ADC.
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
	ADMUX =  (ADMUX & 0xF8) | (adc_input & 0x07);
    
    // Delay needed for the stabilization of the ADC input voltage
    //_delay_us(10);
    
    // Start the AD conversion
    //ADCSRA |= 0x40;
	ADCSRA |= (1 << ADSC);
 
    // 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) 
{ 
    
    
 init_UART(); 
 ADC_init(); 
  
  
  while(1) 
  { 

// Reading x,y,z values
x=Read_ADC(0); 
y=Read_ADC(1);
z=Read_ADC(2);
            
// Sending values to UART.
sprintf(buffer,"%.4u %.4u %.4u ",x,y,z);
uart_printstring(buffer); 
uart_printstring("\r\n"); 
_delay_ms(5000); 
  
   } 
}
 

You can do something like this:

Code:
for (i=0; i <8; i++){
   ADR = ADR+Read_ADC(0);
   //Add some delay
}
ADR = ADR >> 3;

or

Code:
ADR=Read_ADC(0);
for (i=0; i <7; i++){
   ADR = ADR+Read_ADC(0);
   //Add some delay
}
ADR = ADR >> 3;

Declare ADR as a 16-bit variable and i as an 8-bit variable.

EDIT: Error made previously. Fixed. See posts below.

Hope this helps.
Tahmid.
 
Last edited:

Code:
[COLOR="#FF0000"]ADR=Read_ADC(0);[/COLOR]
for (i=0; i <8; i++){
   ADR = ADR+Read_ADC(0);
   //Add some delay
}
ADR = ADR >> 3;

That will not give a correct result, it adds nine results (one before the loop and 8 inside the loop) and divides by 8, the red line has to be removed
 

OK, but I mean where in my program am I adding it?
 

In the place you want a result, in your case
Code:
x=Read_ADC(0); 
y=Read_ADC(1);
z=Read_ADC(2);

Maybe make a function for it

Code:
uint16_t adc_average8(uint8_t channel)
{
    uint8_t i;
    uint16_t ADR=0;

    for (i=0; i <8; i++) {
        ADR = ADR+Read_ADC(channel);       
    }

    ADR = ADR >> 3;

}

and then use

Code:
x=adc_average8(0); 
y=adc_average8(1);
z=adc_average8(2);

- - - Updated - - -

In your code x,y,z are all unsigned char , are you sure the result will never be >255 ?
 

Yes I get max 250 in value

- - - Updated - - -

I have problem getting stable values on the channels, they are bouncing around. Any suggetions how to fix that?
 

Your ADC vref is set to Vcc, have you placed a capacitor in the AREF pin?
Have you added decoupling capacitors in the mcu supply?
Have you used any filter to the Avcc pin?
What is the max expected input voltage for the ADC?

How steady do you expect the output of the sensor to be, there is probably some bouncing from that too
 

No have not used any capacitor on AREF. What value should I use?
No capacitor on mcu either, is 0.1uF ok?
No filter at AVcc pin
Max expected voltage at pin is 2.5v

I guess I have to aply these changes :)
 

Thanks for that.

I got it all connected with capasitors.
There is something weird going on here, all the ADC channels are showing the same output...
 

You mean that this happened after the capacitor addition?
So they change when you move the sensor and they all show the same thing of now they don't change?

I would suggest you also change
Code:
unsigned int x;
unsigned int y;
unsigned int z;
 

No its been like that all the time.
I read the voltage input to ADC, and that shows fine. Get all the right voltages.
If I test one port, say I test the X-axis only (delete the y and z in program), its shows up correct in TeraTerm. Same with y and z. But when I connect all of them, it doesnt work.
How come?
 

If you want to check the ADC connect four 1k resistors in series, one end to 5v and the other to gnd, connect every middle point between resistors to one ADC input.
You should get 1.25v, 2.5v, 3.75v (~ 255, 511, 767 )
 

Status
Not open for further replies.

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top