Ultrasonic Sensor Averaging

Heu guys, I am currently woking on a small code which averages the distance measurements of the Ultrasonic Sensor after every 10 values. I'm having a hard time understanding how to make the averaging work and continuously display the avaerge every 10 outputs?

If someone can help, it would really help.

Thanks,

Take a reading and add it to the total. After 10 readings divide the total by 10 and display the result. Set the total back to zero. Rinse and repeat

What have you tried and where are you stuck ?

1 Like

Do you want a lumpy, once every ten sample period average, or do you want a rolling average with a new result every sample period?

Hi, what is the goal of averaging distance measurements?

Yep, so a rolling average. It for a small obstacle avoidance car and I want ti avaerage the data after every 10 distnace measurments.

1 Like

Think I have this right. Sometimes this simple logic does your head in! Hope you get the idea
reading9=reading8
reading8=reading7
reading7=reading6
reading6=reading5
reading5=reading4
reading4=reading3
reading3=reading2
reading2=reading1
reading1=reading0
reading0= latest_value
reading = reading0+reading1....../10
or
reading = reading0/10 + reading1/10 .....

It looks like you could benefit from reading up on arrays and circular buffers

The reason for averaging is to get a better idea of the current state of the system.
Suppose your car is approaching an obstacle. The "best" reading is the new one. Each previous reading is progressively less relevant. And introduces its own errors because an average of ten readings tells you where you were 5 clicks ago.

A better (and simpler) approach is an Exponential moving average filter - sounds complicated but the algorithm is very simple and easy to implement in software:
new EMA =A * new reading + (1-A) * last EMA.
the value A controls how much weighting you give to the latest value. 0.25 is a good starting point
This graph shows the successive weighting of each reading

2 Likes

No.

Have it your own way

1 Like

That's an unfortunate notation, because it implies a lot of shuffling of data, when, of course, it's the pointers that shuffle, and not the data.
And it implies you don't keep a running total, but re-sum every iteration, when all you need is one subtraction and one addition per iteration.

But, it seems you don't want to learn about arrays, so I guess that's the way to go.
Ho-hum.

@johnerrington

Well explained!

new EMA =A * new reading + (1-A) * last EMA.
can be calculated in three instead of four float operations.
EMA = EMA + A * (new reading - last EMA);

Although the gain is small, it adds up

2 Likes

This is the way to do it, and one I've done for decades. If you cleverly have A be a negative power of 2, you can implement the algorithm using only shifts and integer arithmetic which makes it particularly efficient on generally anemic microcontrollers.

Here is what I had written about averaging ADC readings:

We can easily add a filter to average the readings. Lets say each new conversion counts as 1/16 of the current result value. That means that currentResult = 15/16 lastResult + 1/16 newConversion. To make things easy, store 16 times the values. Then currentResult = lastResult - lastResult/16 + currentResult. The division by 16 is quickly done by shifting right 4 bits. Eight is added before the division to get a rounded result.

Code is: result = result - ((result+8) >> 4) + ADCW;

2 Likes

While you can of course use integer arithmetic (thats one reason to choose A=0.25) the rounding errors very soon become significant if you take a smaller value (or non- negative power of 2 value) for A.
Generally I prefer to use integer arithmetic with ADC values as it avoids incorrect notions of precision.
It also makes you realise the order of operations is important!

1 Like

Thanks, that makes alot of sense now.

Thanks for the help.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.