Today I bring you a simple trick to improve the analog readings of your Arduino. One of the things you notice when you start using the Arduino and taking analog readings is the fluctuation between measurements due to the sensitivity of the analog pins. In my case, when I noticed it most was the day I wanted to use an STM32, which, having much more sensitivity than the Arduino Uno, fluctuated more.

There is no magic trick to improve these readings, but we can improve them with a few simple tips:

  • Keep the cable length as short as possible to reduce external interference.
  • Keep the wiring and PCB tracks away from sources of interference, such as transformers, inductors…
  • Take several measurements and take the average of all of them

Obviously I have not created this post to be obvious, since who else or who less knows some or all of the tips above. I have brought you here to share with you a library that I have made to manage the last tip. I have called this library Averager, and you can download it from the following link.

Surely you wonder why use a library to simply take the average of several measurements. To me personally, it seems a more realistic average to do it with measurements taken over time, than to take them at the same time.

How to get a mean to improve Arduino analog readings

To get an average you can use two methods:

  1. The simplest, you do X measurements, and divide the total by the number of measurements.
  2. The best, you use the last X measurements to get an average.

The first option is the most comfortable, since you simply take X measurements and take the average, but it is also the slowest. Suppose you have a program that measures an analog pin. To measure correctly you cannot take 5 measurements at once, since they will possibly give you the same measurement, but you have to leave a small space of time between measurements. Let’s say we make 5 measurements with a space of 100ms between them, the result will take 500ms to be ready.

The second option solves this problem by keeping a list of the last 5 measurements, and taking the average of all of them. Thus, following the previous example, every 100ms you could take the average without waiting for X measurements. This is useful for purposes like mine, which is to get a voltage measurement that doesn’t change abruptly every so often, but to smooth them out. To do it well, you have to create an array to keep the items, and every time you add a new one, delete the oldest one, and that’s what my library does. Total, since I have, why not share it.

How to use the library

Installation

The installation is like any other library. We download the downloaded code to C:\Users\<user>\Documents\Arduino\libraries\Averager, and we include the library in our sketch.

#include <averager.h>

Create an averager object

Well, for such a simple job I wasn’t going to create a difficult to use library, so you just have to initialize it indicating the type of variable to use, for example double, and how many measurements you want to keep to make the mean.

averager<double, 6> voltage;

In the example above you initialize an averager object of type double, and that stores the last 6 items.

Add an item and get the average

Once we have the object created, adding items and taking the average is very easy. For this we have two methods that will take care of the management.

# Add an item
voltage.append(15.2);

# Get the Average
double voltAverage = voltage.getAverage();
Serial.println(volAverage);

You can add items with voltage.append, and when it reaches the number indicated when initializing it, it will discard the oldest item. Obviously when adding a measurement we will not obtain any average, and the average will soften as we add more.

Example of how to improve analog readings on Arduino

To say goodbye I will leave you a small example of how to use the library to get the average in a simple loop.

#include <averager.h>

averager<double> voltage;

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

void loop() {
  // Measure voltage
  int measured_voltage = analogRead(1);
  voltage.append(5 / 1024 * measured_voltage);

  // Display average
  Serial.print("Average voltage: ");
  Serial.println(voltage.getAverage());
  
  // Wait a bit
  delay(100);
}

In each loop it will recover the voltage from the analog pin, add it to the averager object and show the average through the serial port.

I hope you liked it, and that it helps you in your projects. Greetings!!

Daniel Carrasco

DevOps with several years of experience, and cloud architect with experience in Google Cloud Platform and Amazon Web Services. In his spare time experimenting with Arduino and electronics.

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.