Go Down

Topic: Smoothing Analog values (different numReadings) (Read 9550 times)previous topic - next topic

nsteckhan

Jul 01, 2012, 09:53 pm
Hi everybody,

most of you dealing with analog sensor know the problem of jittering values.
There is this nice example in the standard arduino library called "Smoothing" (Examples>Analog).
See down
I would like to choose different Smoothing strenght in my code (with buttons).
All I want to do is to change the numReadings... but as const int
its read-only! and not changeable in later code...
Has anybody an idea ? I am really new to programming.
Help would be great

Best
Nico

Code: [Select]
`const int numReadings = 10;int readings[numReadings];      // the readings from the analog inputint index = 0;                  // the index of the current readingint total = 0;                  // the running totalint average = 0;                // the averageint inputPin = A0;void setup(){  // initialize serial communication with computer:  Serial.begin(9600);                     // initialize all the readings to 0:   for (int thisReading = 0; thisReading < numReadings; thisReading++)    readings[thisReading] = 0;          }void loop() {  // subtract the last reading:  total= total - readings[index];           // read from the sensor:    readings[index] = analogRead(inputPin);   // add the reading to the total:  total= total + readings[index];         // advance to the next position in the array:    index = index + 1;                      // if we're at the end of the array...  if (index >= numReadings)                  // ...wrap around to the beginning:     index = 0;                             // calculate the average:  average = total / numReadings;           // send it to the computer as ASCII digits  Serial.println(average);     delay(1);        // delay in between reads for stability            }`

marco_c

#1
Jul 01, 2012, 10:19 pm
Simply remove the 'const' to make it a variable.

Code: [Select]
`int numReadings = 10;`
Arduino Libraries https://github.com/MajicDesigns?tab=Repositories
Parola for Arduino https://github.com/MajicDesigns/Parola
Arduino++ blog https://arduinoplusplus.wordpress.com

nsteckhan

#2
Jul 01, 2012, 10:25 pm
would be nice, but then I got this error
"array bound is not an integer constant"

int readings[numReadings];      // the readings from the analog input

dc42

#3
Jul 01, 2012, 10:49 pm
1. What are you reading from? Unless the device itself produces a jittery result (e.g. acceleration sensor), jittery readings can be caused by noise pickup or ground wire current, both of which you can do something about.

2. Try:

Code: [Select]
`const int maxReadings = 20;int readings[maxReadings];int numReadings = 10;    //  must always be between 1 and maxReadings inclusive`

Rest of code as in original.
Formal verification of safety-critical software, software development, and electronic design and prototyping. See http://www.eschertech.com. Please do not ask for unpaid help via PM, use the forum.

nsteckhan

#4
Jul 01, 2012, 11:26 pm
thanks a lot for your answers.

I am reading from IR sensor. I know some people talking about capacity elements wich avoid this noise. but first I wanted to give the software solution a try.

with the code from dc42 I now can change numReadings. which is great. thanks alot.

but somehow changing different numReadings ( button 1= numReadings = 10 or button 2 numReadings = 100)
causes strange behaviour. the minimum value of the sensor readout seems now affected by the last value of Reading...

nsteckhan

#5
Jul 01, 2012, 11:31 pm
maybe this describes better:

if the state is button=2 (numReadings = 100)and sensor value is 50% of the maximal output value (caused by my hand)

I can not get under the level of 50% when switching to button=2

understand ?

Magician

#6
Jul 01, 2012, 11:48 pm
There was no buttons in your original code, can you re-post your code with all mods?

PGT

#7
Jul 02, 2012, 12:01 am
for smoothing i often use code like this

Code: [Select]
`void loop(){a = inputPin(A0); average = ( average * 9 + a ) /10     // it requires a few loops for average to get near "a"// your stuff here...}`
you could use other numbers (as 9 and 10) too here, this construction will always average lag behind a, which is kind of nice; if the data contains a lot of statistical spikes use for example 29 and 30  / if there only a few spikes and you want faster response use 4 and 5
Typical for this construction is that on startup and average still is zero, the function climbs to "a".
I know there are other math constructions, but its small and fast computer code.
instead of *9 one might do *8 or even faster do bitshifts to get *8 (2^3 == thats 3 bitshifts left) and then do only one 'complex' division command.

nsteckhan

#8
Jul 02, 2012, 12:03 am
there are plus/minus buttons changeing for states

Code: [Select]
`switch (remainder+1) {    case 1:  numReadings = 1;  break;  case 2:  numReadings = 40;  break;    case 3:  numReadings = 40;  break;    case 4:  numReadings = 100;  break;}   nothing special so far, just choosing a specified numReading via buttons `

Magician

#9
Jul 02, 2012, 12:13 am
Quote
instead of *9 one might do *8 or even faster do bitshifts to get *8 (2^3 == thats 3 bitshifts left) and then do only one 'complex' division command.
Division is much slower, than multiplication. So to optimize speed, better instead of *9, do *7 , add new value, than shift right >>3 replacing slow division by 8.  Or *15, sum, >>4.

nsteckhan

#10
Jul 02, 2012, 12:33 am
The Code supplied ba PGTBOOS was straight forward..

elegant and easy way, so I got it to work

(maybe this code has more latency? or?, there must be a reason why they put this more complicated code in the examples )

Thanks all you guys. This forum is ***** helpful

tmd3

#11
Jul 02, 2012, 01:13 am
Here's what I see about your original code:

If you used this declaration for your array of readings -
Code: [Select]
`const int maxReadings = 20;int readings[maxReadings];`
then the compiler has set aside 20 integer-sized memory locations for the array.  If you later execute this -
Code: [Select]
`  numReadings = 100;`
- then your program will read from, and write to, 100 locations, 80 of which aren't reserved for the array, and many of which may be in use for storing something else.  We don't know what variables use those locations, but they might be index, total, or average, in which case you'd be writing analog readings to those variables.  I'm not surprised that you got unexpected results.

If you want the maximum number of readings to be as high as 100, under program control, then you'll need to declare your array of readings to have space for 100 values.  Otherwise, chaos ensues.

dc42

#12
Jul 02, 2012, 08:00 am

maybe this describes better:

if the state is button=2 (numReadings = 100)and sensor value is 50% of the maximal output value (caused by my hand)

I can not get under the level of 50% when switching to button=2

understand ?

You need to change the type of 'total' from 'int' to 'long', otherwise it may overflow when the analog reading is near its maximum value of 1023 and numReadings is greater than 32.

Also, when changing numReadings, you need to adjust 'total'. Multiply it by the new numReadings and divide it by the old numReadings. Again, this may overflow unless you change its type to long.
Formal verification of safety-critical software, software development, and electronic design and prototyping. See http://www.eschertech.com. Please do not ask for unpaid help via PM, use the forum.

Go Up