Continue to Site

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.

  • 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.

filters?

Status
Not open for further replies.

Chris_P

New Member
I am just at the beginning of a new hobby project and I am hoping someone can help. I have a 3 axis accelerometer which is connected to an Atmega16. I am using the Atmega16's 10 bit ADC's to read the voltages from the accelerometer. I am getting the values from the AVR through a comm port then displaying these values on my PC.

What I am finding is that the return values are fluctuating a small amount even when the accelerometer is stationary. And when I move the accelerometer I am getting a lot of variation in the values. I have been reading a lot about what other people have done with accelerometers and there is some talk about both software and hardware filters. They talk about filtering to certain bandwidths but I don't understand what that means when I am just measuring a dc voltage. My understanding of electronics is very basic.

I was hoping someone can explain in idiots terms a bit about filters and how I would use them in my applications. I was also wondering how would I smooth the data using software?
 
Ok what they are saying is you must take several reading on the same channel( switching channel on the ADC is going to introduce noise ) so when i use the ADC on the AVR i tend to read sample a few times before changing chanels (ideally you should throw away the first reading) but I have found at least 8 readings makes the averaging easy but here is some code i wrote 3yrs ago so i will try and explain it (for image craft complier) it does not use the ADC interupt at all but i use the interrupt flag to determine the next sample is ready call ADCinitalise at MCU startup to prep the ADC


void ADCData(void)
{
unsigned char i;
unsigned char j;
for (i=0;i<6;i++)
{
ADMUX=i; // this is your ADC CHANEL being sampled
unANALOGUEBUFF=unANALOGUEIN; // previous sample loaded makes part of the new sample ie(filter)

for (j=0;j<64;j++) //set j for 64 for samples of one channel
{
ADCSRA|=(0x01<<ADSC); //start samples
while(!(ADCSRA&(0x01<<ADIF))){}; // wait for conversion to complete
ADCSRA|=(0x01<<ADIF); // AVR write one to clear flag
unANALOGUEBUFF=unANALOGUEBUFF+ADC; //add old with new makes part of filter
unANALOGUEBUFF=unANALOGUEBUFF/2; // divide by 2 to bring reading to proper value
};
unANALOGUEIN=unANALOGUEBUFF; // store in array for next time also use this array to send average value to your pc
};
}

void ADCInitialise(void)
{
uchCHANNEL=0;
ADCSRA = 0x00; //disable adc
ADMUX = 0x00; //select adc input 0
ACSR = 0x80; // adjust values to your needs read datasheet as my system does not use the interrupt vectors
ADCSRA = 0x83; // adjust to suit
asm("nop"); // gives adc time to settle from setup
asm("nop");
asm("nop");
}

ok in short it takes an average reading of 64 samples+the previous value to give the new result and store it in an array for later use the array contains the 6 channel of the adc Note i didnt use channels 7 and 8 in your case chane the for loop( i ) to sample 3 channels "for (i=0;i<3;i++)"
Less samples change loop for (j) for (j=0;j<32;i++)" will take 32 + the old valus and filter average it
 
Thanks for that advice seveprim. My existing ADC function takes one dummy reading and then averages 8 readings. I change the ADC channel before using this function. Shown here:-
Code:
int ADC_read(void)
{
        char i;
        int ADCr = 0;
        int ADC_temp = 0;

        sbi(ADCSRA, ADEN); // enable the ADC

        // do a dummy reading first
        ADCSRA |= (1<<ADSC);

        // wait for conversion done flag
        while(ADCSRA & (1 << ADSC));

        // do conversion 8 times for accuracy
        for(i=0;i<8;i++)
        {
                ADCSRA |= (1<<ADSC);

                // wait for conversion done flag
                while(ADCSRA & (1 << ADSC));

                // get result
                ADC_temp = ADCL;
                ADC_temp += (ADCH << 8);

                // accumulate results for averaging later
                ADCr += ADC_temp;
        }

        ADCr = ADCr >> 3; // average 8 samples

        cbi(ADCSRA, ADEN); // disable the ADC

    return ADCr;
}
Is the reading going to become more stable if I take more than 8 readings and average them? Do I need to enable and disable the ADC in this function as I have done, or can I leave it enabled?

What I took from your example and tried was on the PC program I take the last reading and the new reading and average them before displaying them. This seems to have smoothed the result quite a bit. I also discard any readings that are too different to get rid of the spikes that occur every now and then. I thought I would do it on the PC as it is much faster and I want the AVR to be able to poll it's sensors as fast as possible and just send raw data to the PC where it does all the calculations. Is this the right approach? Or should I let the AVR do the calculations?

I am wondering if my circuit would be improved with some sort of RC filter between the AVR and the accelerometer? And if so, how do I determine the best values for R and C?

Any advice will be a great help.
 
Um why arent you waiting for the coversion to complete ?

ie this line is wrong

while(ADCSRA & (1 << ADSC)); this is wrong !!!! you are not waiting for anything here this is the start conversion flag !!!

you should be checking the ADIF flag and clearing flag like the code i wrote !!!

while(!(ADCSRA&(0x01<<ADIF))){}; // wait for conversion to complete
ADCSRA|=(0x01<<ADIF); // AVR write one to clear flag
 
seveprim said:
Go on msn add seveprim@hotmail.com easier to talk then here


Um why arent you waiting for the coversion to complete ?

ie this line is wrong

while(ADCSRA & (1 << ADSC)); this is wrong !!!! you are not waiting for anything here this is the start conversion flag !!!

you should be checking the ADIF flag and clearing flag like the code i wrote !!!

while(!(ADCSRA&(0x01<<ADIF))){}; // wait for conversion to complete
ADCSRA|=(0x01<<ADIF); // AVR write one to clear flag
I do struggle understanding the details of a lot of code. I am not sure how I came about the code I posted, but I have used it for ADC for quite a while now and it seems to work OK. I just found this in the Atmega16 manual:-
A single conversion is started by writing a logical one to the ADC Start Conversion bit, ADSC. This bit stays high as long as the conversion is in progress and will be cleared by hardware when the conversion is completed.
So my code was using Single Conversion mode and not Free Running mode. So I don't think it is outright wrong.

But then reading further it does talk about the ADC Interrupt Flag and constant sampling. So I will change it to use the ADIF. Thanks.
 
Last edited:
Chris_P said:
I do struggle understanding the details of a lot of code. I am not sure how I came about the code I posted, but I have used it for ADC for quite a while now and it seems to work OK. I just found this in the Atmega16 manual:-
So my code was using Single Conversion mode and not Free Running mode. So I don't think it is outright wrong.

But then reading further it does talk about the ADC Interrupt Flag and constant sampling. So I will change it to use the ADIF. Thanks.

No after reading the manual (atmega128) you code is correct you actually found a neater way of doing the same thing (waiting for conversion to complete) with my code it is basically same deal except I had to then clear the ADIF flag (wasted time ) so your code is correct and better !!! ( i am going to steal your mod lol )
 
Chris_P said:
I am wondering if my circuit would be improved with some sort of RC filter between the AVR and the accelerometer? And if so, how do I determine the best values for R and C?

Any advice will be a great help.

Sorry I missed this question earlier well the last time I used the ADXL202E from anolog devices it had two outputs(per axis) one was a PWM value derived from the analog voltage on a capacitor if memory serves me the larger the cap value the longer the sample time was on the chips internal timing (ie gave fewer internal samples to the averaging circuit but less noise) as for adding passives to the output of the chip I would say not to do that ... what chip are you using ?
 
ezpcb said:
Have you ever try to see the waveform of the input pin of the adc with a oscillatorscope when the accelerometer is stationary? the impedance of accelerometer is high so the designing of the pre-amplifier must be very carefully.

Another suggestion is try to power the circuit with batttery. if the noise disappeared, you'll have to re-design the circuit and the PCB.

Mike


No one is using a pre amp nor do we want to introduce one as accelometers already do that for you.
 
seveprim said:
Sorry I missed this question earlier well the last time I used the ADXL202E from anolog devices it had two outputs(per axis) one was a PWM value derived from the analog voltage on a capacitor if memory serves me the larger the cap value the longer the sample time was on the chips internal timing (ie gave fewer internal samples to the averaging circuit but less noise) as for adding passives to the output of the chip I would say not to do that ... what chip are you using ?
I am using a Freescale MMA7260Q, and now that I go back and look at the schematic I see it already has RC filters on each axis. And I am powering it with batteries at the moment too, so I guess I have covered most of the noise problems. It is probably just the inaccuracy of the ADC causing the fluctuations. They are minor but I am using the readings to move a 3D object on my PC and it does shake continually even when it is stationary.

As far as Mike's suggestion of redesigning the pcb and circuit. The AVR is in an STK500 development board, the MMA7260Q is on a breakout board pcb but it is all connected through a breadboard. I guess this is all contributing to the noise problems.

Appreciate the advice though, I am learning all the time.
 
You could work more on the software/firmware and look for more changes that relate to actual movement ie dont move the 3d object unless you see a reading with a difference of x because when you move an acceloromter you get an inital higher value until you hand accelation stops ( ie hand reaches top speed) can you post your ADC reading ie data sent to PC

from the freescale datasheet
2. Physical coupling distance of the accelerometer to
the microcontroller should be minimal.

I am wondering how far apart your lines are

3. Flag underneath package is connected to ground.

Make sure you got nice ground and did you use a star topology on the AVR ananlog ground pin ( look at data sheet ) to the freescale they should be isolated from the digital ground via a zero ohm link smt-0805

........................................... 0 ohm link smt -0805
AVR analog gnd________________/\/\/\_________________ gnd
Freescale gnd_______________/
 
Last edited:
seveprim said:
You could work more on the software/firmware and look for more changes that relate to actual movement ie dont move the 3d object unless you see a reading with a difference of x because when you move an acceloromter you get an inital higher value until you hand accelation stops ( ie hand reaches top speed) can you post your ADC reading ie data sent to PC
These are just the raw 10 bit adc values but from a stationary accelerometer I get readings like this:-
X - 450 454 450 447 450 452 451 453 450 447 452 454
Y - 541 540 538 544 534 542 541 538 541 539 541 541
Z - 781 781 785 779 780 780 779 781 781 783 779 784
seveprim said:
from the freescale datasheet
2. Physical coupling distance of the accelerometer to
the microcontroller should be minimal.

I am wondering how far apart your lines are
hmmm .. I missed reading that, my lines are way to far apart.
seveprim said:
3. Flag underneath package is connected to ground.

Make sure you got nice ground and did you use a star topology on the AVR ananlog ground pin ( look at data sheet ) to the freescale they should be isolated from the digital ground via a zero ohm link smt-0805

........................................... 0 ohm link smt -0805
AVR analog gnd________________/\/\/\_________________ gnd
Freescale gnd_______________/
I have not used a star topology as you suggested. I can't seem to find a reference to this in the data sheet. Which one mentions this, the AVR or the accelerometer?

I was trying to get nice smooth tilt and direction angles just using a 3 axis accelerometer and a 2 axis magnetometer, but I have since realised that the accelerometer can't really distinguish between tilt and directional movement so I think I need to incorporate a 2 axis gyroscope into my design. So I am not going to worry too much about improving this till I have the gyro. Then the fun will begin merging the data from the accel and gyro to give me accurate tilt angles independent of directional movement.
 
Chris_P said:
I have not used a star topology as you suggested. I can't seem to find a reference to this in the data sheet. Which one mentions this, the AVR or the accelerometer?

No it is not mentioned in the Data sheets but I like to incorporate it in my designs a 2 cent resistor forces all the analog lines(using route software) to one pad and the other side digital GND stops alot of noise, you can even up the resistance a bit say to 10 ohms can help sometimes but it more the forcing the traces to one point on analog gnd path.
 
Status
Not open for further replies.

Latest threads

New Articles From Microcontroller Tips

Back
Top