Arduino Analog Signal Filter, Analog sensor value Fluctuates a lot
Table of Contents
Arduino Analog Signal Filter:
Arduino Analog Signal Filter, Analog sensor value Fluctuates a lot- In this article, we will fix a common problem that a lot of Arduino users faces: fluctuating analog sensor values. Analog signals from sensors can be noisy. This noise can come from various sources, such as electrical interference, fluctuations in power supply, or even the sensor itself.
When you connect an analog sensor to your Arduino and you read these noisy signals directly, the values can jump around even if the sensor itself it not moving and it really makes it hard to get a stable reading. This can be problematic for many applications, such as controlling motors “DC Motors, Servos, etc”, reading environmental data, or any other situation where you need accurate and stable measurements.
We are going to explore several methods to smooth out these fluctuating Sensor values. We will use a Potentiometer as an analog sensor connected to the analog pin A1 of the Arduino.
Steps to Filter Arduino Analog Signal
Step1: Basic Analog Read
We will start with a basic program that reads the sensor value without any averaging or filtering techniques. This will help us understand the problem and see the raw data as it comes from the sensor.
Step 2: Implementing Averaging
Next, we will introduce an averaging technique to smooth out the data. By averaging multiple readings, we can reduce the impact of any single noisy reading.
Step 3: Implementing a Software Filter
In our third step, we will go beyond simple averaging and implement a software-based filter. This filter will allow us to smooth out the sensor values even more effectively.
Hardware Filtering with a Capacitor
Finally, we will introduce a hardware solution by adding a capacitor to create a low-pass RC filter. This physical filter will help smooth the analog signal before it even reaches the Arduino. This approach can be combined with the software filtering techniques for even better results.
The different techniques I am going to explain can also be implemented on ESP32, ESP8266, STM32, etc.
Testing and Comparison
We will test all three programs with and without the capacitor. By comparing the outputs, you will be able to see how each method affects the stability of the sensor readings. This will give you a clear understanding of the benefits and limitations of each technique.
So, without any further delay let’s get started!!!
Amazon Links:
Arduino Nano USB C type (Recommended)
*Please Note: These are affiliate links. I may make a commission if you buy the components through these links. I would appreciate your support in this way!
Potentiometer with Arduino, Circuit Diagram:
Connect the left and right most legs of the Potentiometer to the Arduino 5V and GND. Connect the middle leg of the potentiometer to the Arduino analog pin A1. Right now you can see that I have not added a capacitor. Because, first, we will check the three programs without the capacitor, and then we will test the same programs with the capacitor. So, let’s go ahead and take a look at the most basic program.
Arduino Potentiometer Basic Program:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
int Potentiometer = A1; // Potentiometer is connected to analog pin A1 of Arduino. int PotData = 0; void setup() { Serial.begin(9600); pinMode(Potentiometer, INPUT); } void loop() { PotData = analogRead(Potentiometer); Serial.print("PoT value: "); Serial.print(PotData); Serial.println(""); //delay(100); } |
Explanation:
The purpose of this program is to read the Potentiometer and print the value on the Serial monitor.
1 |
int Potentiometer = A1; // Potentiometer is connected to analog pin A1 of arduino. |
The Potentiometer is connected to the Arduino analog pin A1.
1 |
int PotData = 0; |
The Potentiometer value is stored in the variable PotData.
Inside the setup() function.
1 2 3 4 5 |
void setup() { Serial.begin(9600); |
First we activate the serial communication. 9600 is the baud rate. Without activating the serial communication, you won’t be able to send the data to the serial monitor or Serial Plotter.
1 |
pinMode(Potentiometer, INPUT); |
Next, we set the Potentiometer as input.
1 2 3 4 5 6 7 8 9 |
} Then inside the loop() function. void loop() { PotData = analogRead(Potentiometer); |
We simply read the Potentiometer using the analogRead() function and store the value in PotData variable.
1 2 3 4 5 6 7 8 9 |
Serial.print("PoT value: "); Serial.print(PotData); Serial.println(""); //delay(100); } |
Finally, we send this value to the serial monitor.
Let’s go ahead and upload this program.
Output:
Let’s open the serial monitor.
As you can see, the value is fluctuating a lot. This means the readings from the potentiometer are not stable. This is what to expect from an analog sensor when you only use the analogRead() function.
To understand this better, let’s open the Serial Plotter. The Serial Plotter will give us a visual graph, making it easier to see how much the value is changing over time.
To open the Serial Plotter, simply go to the Tools menu and under the Serial Monitor you will see Serial Plotter.
On the graph, you can see that the signal is very noisy, even though I have not touched the potentiometer. With such a noisy and fluctuating signal, we cannot efficiently control servos, brushed motors, BLDC motors, and other output devices.
Let us understand why this is a problem. When the signal is noisy, it means that the readings are jumping up and down a lot. This makes it hard for the Arduino to know what the actual value is. If we try to use this noisy signal to control motors or other devices, they will not work smoothly. The motors might jerk or move unpredictably, which is not good.
To fix this problem, we need to smooth out the signal. This means making the readings more stable and less noisy. Let’s implement the Averaging technique.
PCBWay:
PCBWay is a trusted leader in the PCB industry, offering custom-designed boards at competitive prices to suit projects of all sizes—from basic to highly specialized.
Whether you’re working with standard FR-4 or need advanced solutions like Rogers, HDI, or Flexible and Rigid-Flex boards, PCBWay provides high-quality options without the high cost. Get an instant quote at pcbway.com/orderonline.
Curious about what others are creating? Explore innovative projects and ideas from the PCB community on PCBWay’s open-source platform at pcbway.com/project/.
Arduino Analog Value Averaging:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 |
int Potentiometer = A1; // Potentiometer is connected to analog pin A1 of Arduino. int PotData = 0; const int numReadings = 10; // Number of readings for averaging int readings[numReadings]; // Array to hold the sensor readings int readIndex = 0; // Index of the current reading int total = 0; // Running total of the sensor readings int average = 0; // Average of the sensor readings void setup() { Serial.begin(9600); pinMode(Potentiometer, INPUT); // Initialize all the readings to 0 for (int i = 0; i < numReadings; i++) { readings[i] = 0; } } void loop() { // Subtract the last reading total = total - readings[readIndex]; // Read the sensor readings[readIndex] = analogRead(Potentiometer); // Add the reading to the total total = total + readings[readIndex]; // Advance to the next position in the array readIndex = readIndex + 1; // If we're at the end of the array, wrap around to the beginning if (readIndex >= numReadings) { readIndex = 0; } // Calculate the average average = total / numReadings; // Print the average value Serial.print("Average PoT value: "); Serial.print(average); Serial.println(""); // Add a delay if needed // delay(100); } |
Explanation:
I have modified the previous program. This time, it does not send the potentiometer value directly to the Serial Monitor. Instead, it reads the potentiometer value ten times, calculates the average, and then sends the final value to the Serial Monitor or Serial Plotter. Let’s upload this program and see if it’s going to make any difference.
Output:
The averaging technique has made the sensor value much smoother, but there is still some noise. So, let’s go ahead and implement a software filter.
Arduino Filter for Analog Sensors:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
int Potentiometer = A1; // Potentiometer is connected analog pin A1 of arduino. int PotData = 0; int filteredValue = 0; // Initialize filtered value float alpha = 0.1; // Filter coefficient (0 < alpha < 1) void setup() { Serial.begin(9600); pinMode(Potentiometer, INPUT); } void loop() { PotData = analogRead(Potentiometer); filteredValue = alpha * PotData + (1 - alpha) * filteredValue; // Filter equation //vout = (filteredValue * 5.0) / 1023.0; //vout = vout * cf ; Serial.print("Filtered Pot Value: "); Serial.print(filteredValue); Serial.println(""); //delay(100); } |
Explanation:
This code is much simpler than the previous one. This time, after reading the value from the potentiometer, we pass it through a filter equation to get filtered values.
Alpha is a Filter coefficient between 0 and 1. It controls how much of the new sensor reading (PotData) will be included in the filtered value.
PotData: This is the raw sensor reading from the potentiometer.
filteredValue: This is the smoothed value that we get after applying the filter.
In this equation:
“alpha * PotData” This part of the equation takes the new sensor reading and multiplies it by alpha. If alpha is 0.1, it means that 10% of the new reading is used in the final filtered value. You can try different values from 0.1 to 0.9.
“(1 – alpha) * filteredValue” This part takes the previous filtered value and multiplies it by (1 – alpha). If alpha is 0.1, then (1 – alpha) is 0.9. This means that 90% of the previous filtered value is kept in the new filtered value.
By combining these two parts, the filter smooths out the fluctuations in the sensor readings. The result is a filteredValue that changes more slowly and is less noisy compared to the raw PotData.
If you want to know more about this equation read my article available on electorniclinic.com.
Anyway, let’s go ahead and upload this program.
The signal is much smoother now, but there is still a bit of noise. So, let’s test all three programs with a capacitor.
Simply connect the positive leg of a 4.7 or 10uF capacitor to the middle leg of the potentiometer, and connect the ground leg of the potentiometer to the Arduino ground. This makes a simple low-pas RC filter.
Now, let’s go ahead and upload all the three programs one by one.
Just by adding a single capacitor, you can significantly reduce the noise.
The value is only fluctuating between 861 and 862. Let’s also take a look at the graph.
Let’s upload the 2nd program “Averaging”.
When you connect the capacitor and also use the averaging technique on the sensor value, you can see the result. The code might get a bit longer, but the end result is quite satisfactory. You can see there is still a little bit fluctuation.
Now let’s upload the 3rd program.
Hardware and software filter combined.
And when you have a low-pass filter on the hardware side and also implement a filter in the program, you get an almost perfectly smooth value that you can completely rely on.
Now the value is perfectly stable. So, that’s all about how to smooth an analog value.
Support me on Patreon for more articles and videos.
Great article . Well explained . Thankyou I will add it to my library of great snipits of code