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.

Strange Moving Average results

Status
Not open for further replies.

CMOS

Advanced Member level 3
Advanced Member level 3
Joined
Jan 6, 2004
Messages
862
Helped
94
Reputation
186
Reaction score
50
Trophy points
1,308
Location
USA
Activity points
5,673
Hi all,
I am re-coding the firmware of a weighing scale which uses a discretely made sigma-delta ADC using op-amps and counters and an 8051 microcontroller.

I am using moving-average filter for stability. Now the problem is if I increase the number of samples for averaging, the final count reduces to a considerable amount and vice versa. I don't get similar weight values for different window sizes!!

However I think this should not happen.. no matter what the filter window size is, the reading should fluctuate around same value for a given weight.

Any solutions ??

Here is my update weight ISR where averaging is carried out
Code:
#define AVG_FILTER_WINDOW_SIZE	8

void new_weight_interrupt(void) interrupt 2 using 0
{
	EX1 = 0;	// Disable INT1 interrupt
	ET1 = 1;	// Disable TMR0 interrupt
	TR0 = 0;	// Stop Timer-0

	val_393 = P1;
	val_393 &= 0x0F;
	CLR_393 = 1;

	new_weight  = ((long)overflow) << 16;
	new_weight |= ((long)TH0) << 8;
	new_weight |= ((long)TL0);
	new_weight <<= 4;
	new_weight |= (long)val_393;

	// AVERAGING IS DONE HERE
	avg_weight += new_weight;
	avg_weight /= AVG_FILTER_WINDOW_SIZE;

	overflow = 0;
	TH0 = 0;
	TL0 = 0;
	TR0 = 1;
	CLR_393 = 0;

	EX1 = 1;
	ET1 = 1;
}
 

Hi,

I am not sure I understand completely your code, but I do agree that results should be close for different windows sizes.

So if you increase your windows, the sum of weight should also increase. You have to provide more samples before divide.

You can accomplish that modifying something else not only the windows size.

When I used moving average I recall using and array so I could subtract the oldest sample and include the new one in the sum. The size of the array (count of samples) was related with the windows size, so average was convergent
 
I'm new to this type of code, so I have some questions for you:

Can you explain me on which part of the code are you adding the 8 values to avg_weight ?
 

CMOS,

Could you post some data that you're getting for different window sizes? For example, you could post an Excel sheet or a CSV file (zipped), where each column is a certain window size and the columns are the time series of averages with that window size.

Kender
 

daviddlc said:
I'm new to this type of code, so I have some questions for you:

Can you explain me on which part of the code are you adding the 8 values to avg_weight ?
This does the averaging
// AVERAGING IS DONE HERE
avg_weight += new_weight;
avg_weight /= AVG_FILTER_WINDOW_SIZE;

After eight operations...I should get the first average result.

kender said:
CMOS,

Could you post some data that you're getting for different window sizes? For example, you could post an Excel sheet or a CSV file (zipped), where each column is a certain window size and the columns are the time series of averages with that window size.

Kender
Here is the CSV file

I guess there is something wrong with my calculations....I cant use array for storing samples as each sample is a long integer and I have very limited memory in 8051!
 

CMOS,

like someone before me, I don't see were you count the samples. So I can not tell were you clean (set to zero) the sum variable every AVG_FILTER_WINDOW_SIZE samples.

If you are really want to make the calculation at every sample and NOT every AVG_FILTER_WINDOW_SIZE samples then you must add a new sample everytime but remove the oldest, I think

Sometimes these little details make you have a hard time
 
Can you explain me on which part of the code are you adding the 8 values to avg_weight ?[/quote]
This does the averaging
// AVERAGING IS DONE HERE
avg_weight += new_weight;
avg_weight /= AVG_FILTER_WINDOW_SIZE;

After eight operations...I should get the first average result.

After 8 operations, but you are dividing by 8 all the time, check it out, you need to divide by 8 only after you have added 8 operations, otherwise your calculation is not correct.


And as Kender mentioned you should be using a type of array or table to have the 8 measurements and then calculate the average.

Added after 5 minutes:

daviddlc said:
Can you explain me on which part of the code are you adding the 8 values to avg_weight ?
This does the averaging
// AVERAGING IS DONE HERE
avg_weight += new_weight;
avg_weight /= AVG_FILTER_WINDOW_SIZE;

After eight operations...I should get the first average result.

After 8 operations, but you are dividing by 8 all the time, check it out, you need to divide by 8 only after you have added 8 operations, otherwise your calculation is not correct.


And as Kender mentioned you should be using a type of array or table to have the 8 measurements and then calculate the average.[/quote]

Corrections:

You are dividing by 8 all the time, check it out, you need to divide by 8 only after you have added 8 operations, otherwise your calculation is not correct.

And as Odiseo mentioned you should be using a type of array or table to have the 8 measurements and then calculate the average
 
Yes...I guess you people are right there. My method works right only for the first eight samples and not any further.

I'll modify the code and post the results.
 

If Xi is sample at the time i than output is calculated as average of M previous samples.
Yi=(Xi+ Xi-1 +Xi-2+... Xi-M)/M
Theese operations are very simple if you use M as some exponent of 2, because instead of division you can use rotate right instruction.
Actually you can make MAV fast like a flash with recursive implementation. Just notice that for the next moment i+1
Yi+1=(Xi+1+ Xi +Xi-2+... Xi-M+1)/M=(Xi+1 + Yi*M - Xi-M )/M
i.e read newest sample and put into a buffer, read i-M sample from a buffer, and make addition with previous filter output. Finally divide it by M.
The width of moving average filter M is inversly proportional to its bandwidth (only are filtered signals that vary significantly in the time interval M).
If you need sharper filter than you can filter Y signals with same method...
 
Status
Not open for further replies.

Similar threads

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top