Smoothing analog readings

I know there are already million of similar question and 10 million of answers. I have also tried some libraries and came up with decision for the sake of customization to work on own method for filtering. I have different kind of analog inputs and one of them is voltage measurement for example. Currently it is constantly jumping from 3.1 to 3.2. I would like to apply some kind of filter to it. SO I have came up with this method. However for some reason it does not do any filtering. What might be the reason?

 void readAnalogInputs()
{
  voltageValue = smooth(A2);
}

int smooth(int sensor){
  int i;
  int value = 0;
  int numReadings = 10;

  for (i = 0; i < numReadings; i++){
    // Read sensor data.
    value = value + analogRead(sensor);

    // 1ms pause adds more stability between reads.
    delay(1);
  }

  // Take an average of all the readings.
  value = value / numReadings;

  return value;
}

I have also tried for example

#include <ResponsiveAnalogRead.h>

but it rounds to absolute number that is 3, I would like to receive more precise values 3.1 or 3.2...

That's the average value, I guess, since integers don't have anything to the right of the decimal point. And for the same reason, I'd say that's "smoothed"... :wink: Maybe the raw numbers are jumping between 3 & 4, or "worse".

And if you're reading about 3 on the 10-bit ADC (0-1023 range) you're not using much of its resolution and that might be a problem.

The ADC is integer, but for example if you convert that to voltage you can use a type-float in your calculation and you could get a meaningful result like 3.2V.

P.S.

I don't know what that library is doing but by-default integers are truncated, not properly rounded (3.99 becomes 3).

Instead of using volts, use millivolts.

consider

// running average (leaky integration)

float  avg;
const float K = 0.125;

// -----------------------------------------------------------------------------
void
loop ()
{
    int samp = analogRead (A0);

    if (0 != avg)
        avg += (samp - avg) * K;
    else
        avg = samp;

    Serial.println (avg, 0.01);
    delay (250);
}

// -----------------------------------------------------------------------------
void
setup ()
{
    Serial.begin (9600);
}

Beyond what @DVDdoug said regarding precision, I would recommend a running average to smooth the analogs. Here is how I did it:

int smoothAnalog(int reading) 
{
  const int numSamples = 10;
  static int samples[numSamples];
  static int sampleIndex = 0;
  static int sampleSum = 0;

  //
  // Analogs are a 10-bit value (0-1023), therefore we could
  // average up to 32 values with a signed int.
  // NOTE: It will take 10 measurements to fill the sample
  // array and return a true smoothed value.  This is not a
  // problem for this application and not worth compensating for.
  //
  
  // Update sum
  sampleSum -= samples[sampleIndex];
  samples[sampleIndex] = reading;
  sampleSum += samples[sampleIndex++];
  sampleIndex = sampleIndex % numSamples;

  // Return average of last numSamples measurements
  return sampleSum/numSamples;
}

"sample array" ?

My first version used an array and I then decided it was not needed. "Tsk tsk" on me for not updating the comment. BAD programmer! :open_mouth:

It probably was.

You are correct...or accumulate the sum until 10 samples have been added.

...and now you've changed the post, and made nonsense of both our comments.

1 Like

Yes I did.

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