Language: EN

reducir-ruido-sensores-arduino-muestreo-multiple

Reduce noise in Arduino sensors with multiple sampling

Noise, noise, noise. At this point in the blog it should be clear that in any electronic system one of the main problems is the noise of the signals. In this context, we understand noise to be high-frequency and random signals that interfere with the signal of interest.

Noise is a clear and annoying reality when using sensors. Although the quality of the sensor significantly influences the amount of noise in the measurement, the truth is that all sensors present noise.

With the price range of the sensors that we buy for our home projects, unfortunately, noise in the measurements will be a constant problem to deal with.

In some cases, we can incorporate some physical filtering system, but in general, if we want to use sensors seriously in our projects, we will have to learn to treat and filter the noise of sensor measurements digitally.

Multiple sampling to the rescue

Assuming that we have already done everything possible to improve the physics of the sensor and its environment, the problem reduces to the fact that we are going to acquire samples and these will not correctly reflect the measured magnitude.

Since individually taken samples are unreliable and we have already done everything possible to improve them, it is deduced that the only possibility is to perform multiple sampling, that is, to acquire the sensor measurement several times.

Later, we will have to apply some type of algorithm to combine the samples and obtain a measurement with greater precision than the individual samples.

Let’s imagine, for example, that we are taking the temperature of an instance. When taking measurements on a temperature sensor, we will receive a sequence that, for example, is 24.9, 24.8, 24.7, 24.8, 27, 24.8.

We see that there are small variations between samples (noise, oscillations) and a point (27) that at first seems “anomalous” (we will call these types of points spurious or outliers).

What is the temperature of the instance? Surely, as a first intuition, we would say about 24.8 degrees. But it is worth reflecting for a second on this very quick response.

Before answering, we should know, for example, the precision of the sensor, the time between samples, and the speed of the system we are measuring. Could it be that they are taken every 30 minutes, and we have actually reached 27º at one point?

Measurement, sampling, and filtering are important, broad, and complex topics. There are many parameters to consider, and a huge variety of filtering algorithms (mean, median, exponential…) each with its advantages and disadvantages.

In the blog, we will see many ways to filter signals and, in particular, how to use them to reduce noise in sensor acquisition. For now, let’s start with two simple procedures to perform multiple sampling of a sensor.

Constant sample acquisition

Probably the simplest way to perform multiple sampling is to measure a fixed number of times. For example, we have a sensor but instead of taking a single measurement, we take 20, 50, or 100 consecutive ones.

The number of samples will depend on the speed of the sensor and the time we want to be measuring.

Later, we will have to process the data. In the example, we are going to use the mean, because it is quick to calculate and does not require storing the measured values. In other posts, we will see other filters.

float MeasureN(int samplesNumber, float (*funct)())
{
  float sum;
  for (int i = 0; i < samplesNumber; i++)
  {
    sum += funct();
  }

  return sum / samplesNumber;
}

// Function that simulates the measurement of a sensor
float getMeasure()
{
  return 0.0;
}

void setup()
{
  float measureN = MeasureN(100, getMeasure);
}

void loop()
{

}

Constant time acquisition

A variation is to measure at a constant time interval. For example, we take a sensor and decide that we want to make all the possible measurements for 20, 50, or 100 ms.

Again, the time depends on the speed of the sensor and the time we want to dedicate to the measurement, but in this case we have much greater control of the time we are going to make the measurement. This makes it often more convenient to integrate into our programs.

float MeasureT(int msInterval, float(*funct)())
{
  float sum;
  long startTime = millis();
  int samplesNumber = 0;

  while (millis() - startTime < msInterval)
  {
    samplesNumber++;
    sum += getMeasure();
  }
  return sum / samplesNumber;
}

// Function that simulates the measurement of a sensor
float getMeasure()
{
  return 0.0;
}

void setup()
{
  float measureT = MeasureT(50, getMeasure);
}

void loop()
{

}

Add Max, Min, and Mid points

Sometimes, we not only want to obtain the filtered value (in this case the mean) of the sampling, but we are also interested in the range of variation of the sample. For example, to determine if a process is within an appropriate stability range.

With the presented algorithms, it is easy to make modifications to obtain the minimum, maximum, and the midpoint between both. However, performing these calculations involves some additional work, so only use them if really necessary.

float min, max, mid;
float MeasureN(int samplesNumber, float(*funct)())
{
  float value;

  for (int i = 0; i < samplesNumber; i++)
  {
    value = funct();
    if (value > max) max = value;
    if (value < min) min = value;
  }

  mid = (max - min) / 2;
  return sum / samplesNumber;
}

float MeasureT(int msInterval, float(*funct)())
{
  float value;
  long startTime = millis();

  while (millis() - startTime < msInterval)
  {
    value = funct();
    if (value > max) max = value;
    if (value < min) min = value;
  }

  mid = (max - min) / 2;
  return sum / samplesNumber;
}

float getMeasure()
{
  return 0.0;
}

void setup()
{
  MeasureN(100, getMeasure);
  MeasureT(50, getMeasure);
}

void loop()
{

} 

In future posts, we will see different advanced and efficient ways of filtering sensor measurements, such as the mean, median, and exponential filters.

Download the code

All the code from this post is available for download on Github. github-full