Tutorial: Potentiometers with Arduino and Filtering

In this blogpost we will go through what a potentiometer is and how they work, how to connect it up to an Arduino as well as describe a common problem with regards to potentiometer usage and a workaround to that problem.

What Is a Potentiometer?

A potentiometer, henceforth referred to as a pot, is a variable resistor. It is an electrical component with three terminals (i.e. pins or legs): one for input voltage (e.g. 5V), one for output voltage (e.g. GND) and one for picking up the value of the pot (we’ll call this the wiper).

Mechanically speaking, pots are physically adjusted usually using your fingers. Both rotational and linear pots are common.

A rotational and a linear pot (source: Wikipedia)
A rotational and a linear pot (source: Wikipedia)

Pots are used a lot in all kinds of electrical appliances. Volume knobs, light dimmers and faders in audio mixers are often pots. They also come in digital and even motorized versions, but those are outside of the scope of this post.

If you want to control the speed of your electric motor, position of your servo, LED brightness, filter cutoff on your synthesizer, gain on your guitar amp or thousands of other cool things in your own embedded system, a pot might just be the solution for you.

The Theory

For an introduction to electrical theory, take a look at this post we wrote a while back where we explain fundamentals such as voltage, resistance and current as well as the relationship between these.

So, what’s happening in a circuit with a pot is basically voltage division in practice.

"R<sub
R1 and R2 are within the pot itself. (Source: Wikipedia)

In the schematics above, the resistors R1 and R2 are part of the pot itself. RL is the resistance of the load (a motor, a LED or whatever). When you turn or slide the pot, you will change the values of R1 and R2. Moving the pot one way will reduce R1 and increase R2, and vice versa. This results in various voltage values on the wiper (the one that goes to RL in the schematics above). The voltage value itself can be calculated by using the following equation:

voltage_division

where VL is the voltage difference between the wiper and the output pin, and VS is the voltage difference between the input and output pin. To simplify this a bit: if the output pin is connected to GND, you can simply say that VL is the voltage on the wiper and VS is the voltage on the input pin (and then just ignore the “voltage difference” mumbo jumbo since GND is defined as 0V).

The Pot and the Arduino – an Example

Enough with the theory, let’s get things up and running with an example!

The Hardware

In the following example we’ve used a small 10K plastic pot for breadboard, a breadboard, a few jump wires (these are excellent for this purpose) and of course an Arduino (in this case a Leonardo).

We let 5V go to one of the pins on the sides of the pot and GND to the other. The middle one needs to go to one of the ANALOG IN pins on the Arduino, in this instance A0. And that’s it!

The circuit is up and running! Red wire: 5V, black wire: GND, yellow wire: wiper signal to ADC.
The circuit is up and running! Red wire: 5V, black wire: GND, yellow wire: wiper signal to ADC.
ADC (Analog-to-Digital Converter)

The signal from the pot is analog, but we want it to be digital so that we can read the value on the screen. Arduino has a built-in ADC (analog-to-digital converter) which creates a digital representation of the analog signal. The higher the input voltage, the larger the digital value. Arduino’s ADC takes in 0 to 5 volts and has a 10-bit resolution which lets it output 1024 digital values. To summarize: 0 volts is equivalent to a digital value of 0, and 5 volts is equivalent to a digital value of 1023.

You can read more about Arduino’s ADC here.

The Software

The most basic way to read the pot value is to print the digital value to the serial monitor, so that’s what we’re going to do.

The flow of this simple program will go like this:

  1. Initialize global variables.
  2. Set up the serial module.
  3. The loop
    1. Read the voltage of the pot and run it through the ADC.
    2. Write the digital value of the pot to the serial monitor.
    3. Wait 50ms before repeating.

Below is the code we’re running on the Leonardo:

//Global Variables
int sensorPin = 0;		//pin number to use the ADC
int sensorValue = 0;	//initialization of sensor variable

void setup(){
	Serial.begin(115200);	//setup of Serial module, 115200 bits/second
}

void loop(){
	sensorValue = analogRead(sensorPin);	//read the sensor value using ADC
	Serial.println(sensorValue);			//print digital value to serial monitor
	delay(50);								//50ms delay
}

When the code is up and running, open the Serial Monitor in the Arduino IDE to see the pot value change as you turn the knob. Remember to set the baudrate to the same value as in the serial initialization in the software (115200 in our case)!

A Common Problem and Filtering

If your software should react significally to changes on the pot (for instance change a major state) you’re gonna have a bad time. The reason for this is that while you’re not touching the pot, the values might change anyway. And the larger the resolution of your ADC is, the more probable it is that you encounter this measurement noise.

The reason for this issue is that the pot is continously adjusted and that it often is positioned in the middle of two digital values. Remember that the real world is not ideal, so tiny inevitable changes in the voltage from noise is enough to bump it back and forth between two or more digital values.

A Couple of Solutions

So, how do we cope with this? Firstly, don’t design your program so that a small change on the pot does something major.

Secondly, to reduce this measurement noise you can try adding simple low-pass filtering in the software. A moving average algorithm will often suffice. We will implement an exponential moving average algorithm, henceforth reffered to as EMA, to smooth out the signal in this example. Feel free to try out some of the other moving average algorithms as well.

The EMA algorithm goes as follows:

S_Y

 

and for t>1:
EMA_2

 

where St is the result of the EMA at time t, Yt is the pot measurement at time t, and α is a coefficient in the range <0,1> that decides how many samples the EMA algorithm should take into account. A low α will be very slow to rapid input changes and take many samples into account. A high α will be fast, but average over fewer samples. You can look at α as kind of a cutoff frequency in a low-pass filter.

A visualization of how the EMA operates. The X-axis is the samples with the most recent sample to the left. The Y-axis is the "weight" of each sample, i.e. how "important" each sample is when calculating the EMA. (Source: Wikipedia)
A visualization of how the EMA operates. The columns along the X-axis are the samples with the most recent one to the left. The height of the columns on the Y-axis is the “weight” of each sample, i.e. how “important” each sample is when calculating the EMA. (Source: Wikipedia)

Here’s the final code with the EMA:

//Global Variables
	int sensorPin = 0;		//pin number to use the ADC
	int sensorValue = 0;	//initialization of sensor variable, equivalent to EMA Y
	float EMA_a = 0.6;		//initialization of EMA alpha
	int EMA_S = 0;			//initialization of EMA S

void setup(){
	Serial.begin(115200);			//setup of Serial module, 115200 bits/second
	EMA_S = analogRead(sensorPin);	//set EMA S for t=1
}

void loop(){
	sensorValue = analogRead(sensorPin);				//read the sensor value using ADC
	EMA_S = (EMA_a*sensorValue) + ((1-EMA_a)*EMA_S);	//run the EMA
	Serial.println(EMA_S);								//print digital value to serial
	delay(50);											//50ms delay
}

Experiment with different values of α to see the difference in speed when rapidly changing the pot position.

Finding the actual cutoff-frequency is not trivial, but with some mathematical calculations it is possible. Take a look at this page to see how to do this.

You can use EMA to create quick and easy high-pass, band-pass and band-stop filters as well. If this sounds interesting, take a look at this blog post.

A Short Conclusion

We hope that this little tutorial was helpful to you. Potentiometers are super useful in embedded systems and really fun to play around with. Use them to control whatever you’d like! 🙂

Related Posts