Go Down

### Topic: Smooth a value in one instruction. (Read 2773 times)previous topic - next topic

#### RIN67630

##### Feb 12, 2020, 08:43 pmLast Edit: Feb 12, 2020, 08:47 pm by RIN67630
Here is the way to smooth a value in one line:
Code: [Select]
`A0smooth = A0smooth + (A0 - A0smooth) / 2;`
smoothes A0 to A0smooth.
You should run that with A0 and A0smooth being floats.
If you want a stronger smoothing replace /2 by /3 or more.
The higher the value the stronger the smoothing.

This code does a smoothing in the same way than a RC filter in electronics.

#### DrAzzy

#1
##### Feb 21, 2020, 01:44 amLast Edit: Feb 21, 2020, 01:47 am by DrAzzy
That's one line of code, not one instruction (by my count, it's like 10-12 instructions - load, sub, rightshift, add, store - times 2 because on an 8-bit avr, and 16-bit operands...)

As an aside, dividing by 3 is much worse, while dividing by 4 (or other powers of 2) is not - division on AVRs is implemented in software and slow.
ATTinyCore and megaTinyCore for all ATtiny, DxCore for DA/DB-series! github.com/SpenceKonde
http://drazzy.com/package_drazzy.com_index.json
ATtiny breakouts, mosfets, awesome prototyping board in my store http://tindie.com/stores/DrAzzy

#### PaulMurrayCbr

#2
##### Jul 10, 2020, 04:40 am
AKA a recursive lowpass filter. In general
Code: [Select]
`weight = .95;value = value * weight + newValue * (1-weight);`

See http://www.dspguide.com/ for a free webbook on this topic.

#### TheMemberFormerlyKnownAsAWOL

#3
##### Jul 12, 2020, 06:59 pm
Quote
Here is the way to smooth a value in one line:
Code: [Select]
`A0smooth = A0smooth + (A0 - A0smooth) / 2;`

smoothes A0 to A0smooth.
... but remember that on a UNO, A0 always has the value 14, so doesn't really need smoothing.
Please don't PM technical questions - post them on the forum, then everyone benefits/suffers equally

#### RIN67630

#4
##### Jul 24, 2020, 10:58 pm
Code: [Select]
`weight = .95;value = value * weight + newValue * (1-weight);`
That will not do: You must add the weighted increment*, not the newValue

#### PaulMurrayCbr

#5
##### Jul 26, 2020, 06:18 am
That will not do: You must add the weighted increment*, not the newValue
The weighted increment is (newValue-value)*(1-weight), and - looking at it - I agree that doing it that way is better, as it involves one fewer floating-point multiplications. BUt mathematically it comes out the same.

Of course, subtracting the weight from 1 is just a result of what you decide that "weight" means.

#### johnerrington

#6
##### Sep 16, 2020, 09:40 am
I'm hesitant to contribute in such distinguished company; however I'd suggest it would be better to use integer arithmentic.

Suppose you get a 12 bit integer value "newValue" from the ADC;

using a weight of .75 ..

to smooth it you take int smoothValue = (smoothValue*3 + newValue) /4

as smoothValue = (smoothValue + smoothValue<1 + newValue) >>2
I'm trying to help. If I find your question interesting I'll give you karma. If you find my input useful please give me karma (I need it)

#### TheMemberFormerlyKnownAsAWOL

#7
##### Sep 16, 2020, 09:50 am
I'm hesitant to contribute in such distinguished company; however I'd suggest it would be better to use integer arithmentic.

Suppose you get a 12 bit integer value "newValue" from the ADC;

using a weight of .75 ..

to smooth it you take int smoothValue = (smoothValue*3 + newValue) /4

as smoothValue = (smoothValue + smoothValue<1 + newValue) >>2
better still, "smoothValue<<1"

Or just leave it as "(smoothValue*3 + newValue) /4", and let the compiler figure it out.
Please don't PM technical questions - post them on the forum, then everyone benefits/suffers equally

#### johnerrington

#8
##### Sep 16, 2020, 10:18 am
smoothValue<<1  loses precision.

Quote
Or just leave it as "(smoothValue*3 + newValue) /4", and let the compiler figure it out.
my suggestion is based on several factors:

firstly that CHOOSING to use integer arithmetic forces the use of a sensible weighting - i.e. not something like 0.93;

and secondly that  it helps to see where precision could be lost.

also I get very fustrated when reading that someone has read the value of a voltage with the adc as 3.4326171875 volts,  just because the reading was 703 on a 5V=1024 scale.

Maintaining precision in a digital filter is important.
I'm trying to help. If I find your question interesting I'll give you karma. If you find my input useful please give me karma (I need it)

#### TheMemberFormerlyKnownAsAWOL

#9
##### Sep 16, 2020, 10:20 am
as smoothValue = (smoothValue + smoothValue<1 + newValue) >>2
Loses even more precision
Please don't PM technical questions - post them on the forum, then everyone benefits/suffers equally

#### johnerrington

#10
##### Sep 16, 2020, 06:54 pmLast Edit: Sep 17, 2020, 09:12 am by johnerrington
Yes;  the precision is of course lost in the final divide (or shift)

the integer values need to be manipulated at hgher precision for the results to be sensible.

My old brain was struggling so I used excel.

This filter is Vn+1 = (3*Vn + 256*Sn) >>2

the "voltage" is calculated at the END by (integer) dividing by 256.

You can see that by using higher order bits in the integer value precision is maintained in the filter calculation.

A single bit is lost in the conversion to "voltage" - as it would be in converting from a float.

I've attached the spreadsheet as a zip file.  Change the yellow value to change the "seed" sample value.  Its filtering a step function.

The graph shows the filter response: Its important to realise that at any instant the filtered value is unlikely to match the current value of your reading.

I'm trying to help. If I find your question interesting I'll give you karma. If you find my input useful please give me karma (I need it)

#### TheMemberFormerlyKnownAsAWOL

#11
##### Sep 16, 2020, 07:01 pm
It wasn't a shift I was highlighting, it was a Boolean expression
Please don't PM technical questions - post them on the forum, then everyone benefits/suffers equally

#### johnerrington

#12
##### Sep 16, 2020, 07:06 pmLast Edit: Sep 17, 2020, 09:13 am by johnerrington
My bad - a typo - unacceptable in a program!  However it triggered an interesting excursion.  Thanks.
I've updated the spreadsheet and graph above.
I'm trying to help. If I find your question interesting I'll give you karma. If you find my input useful please give me karma (I need it)

Go Up