![]() | ![]() | ![]() |
| | |||||||
| Electronic Projects Design/Ideas/Reviews Are you building an electronic project or want to? Maybe you need some assistance? Come and submit your electronic questions here and let our experienced members find a solution. |
| | LinkBack | Thread Tools | Display Modes |
| | (permalink) |
| 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? | |
| |
| | (permalink) |
| 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[i]; // 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[i]=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 | |
| |
| | (permalink) |
| 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;
} 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. | |
| |
| | (permalink) |
| Go on msn add seveprim@hotmail.com easier to talk then here | |
| |
| | (permalink) |
| 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 | |
| |
| | (permalink) | ||
| Quote:
Quote:
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 by Chris_P; 27th July 2007 at 06:41 AM. | |||
| |
| | (permalink) | |
| Quote:
| ||
| |
| | (permalink) | |
| Quote:
| ||
| |
| | (permalink) |
| 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 | |
| |
| | (permalink) | |
| Quote:
No one is using a pre amp nor do we want to introduce one as accelometers already do that for you. | ||
| |
| | (permalink) | |
| Quote:
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. | ||
| |
| | (permalink) |
| 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 by seveprim; 28th July 2007 at 12:56 PM. | |
| |
| | (permalink) | |||
| Quote:
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 Quote:
Quote:
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. | ||||
| |
| | (permalink) | |
| Quote:
| ||
| |
| Bookmarks |
| Thread Tools | |
| Display Modes | |
| |
| | ||||
| Title | Starter | Forum | Replies | Latest |
| Filters Choice? | mo7mad | General Electronics Chat | 4 | 6th April 2006 02:50 PM |
| filters | mstechca | General Electronics Chat | 3 | 27th May 2005 04:35 AM |
| Filters, plz help! | elec123 | General Electronics Chat | 2 | 18th April 2005 07:18 PM |
| controlling band-pass filters | aidanbre | Micro Controllers | 4 | 15th April 2003 08:32 AM |
| band pass filters | aidanbre | Electronic Projects Design/Ideas/Reviews | 1 | 29th November 2002 07:43 AM |