Using a Potentiometer
The Raspberry Pi’s GPIO pins are digital pins, so you can only set outputs to high or low, or read inputs as high or low. However, using an ADC chip (Analogue-to-Digital converter), you can read the value of analogue input devices such as a Potentiometer.
SPI
The analogue values are communicated to the Pi using the SPI protocol. While this will work in GPIO Zero out of the box. You may get better results if you enable full SPI support.
What I used
- 10-bit ADC (SPI) – 8 Channel
- 5mm diffused LED
- 830 Point Solderless Breadboard
- Breadboard Jumper Cable
- Potentiometer single turn carbon linear PCB 2K
Setup
We will assume that you have your raspberry pi setup and ready to go. If you need help with this visit our blog
Wiring the ADC (MCP3008)
The MCP3008 is an ADC providing eight input channels. The Pi’s GPIO pins are connected to eight connectors on one side. And the other eight are available to connect analogue input devices to read their values.
Place the MCP3008 chip on a breadboard and carefully wire it up: First 2 to the + gutter, 3rd to -, 4th,5th,6th,and 7th to your GPIO pins and the last one to – gutter again. You should see a small notch, or dot, in one end of the chip.
Add a potentiometer
Now that the ADC is connected to the Pi. You can wire devices up to the input channels. A potentiometer is a good example of an analogue input device: in other words, it’s simply a variable resistor, and the Pi reads the voltage (from 0V to 3.3V).
A potentiometer’s pins are ground, data, and 3V3. This means you connect it to ground and a supply of 3V3, and read the actual voltage from the middle pin. Place a potentiometer on the breadboard and wire one side to the ground rail, the other to the 3V3 rail, and the middle pin to the first input channel.
Code
Open Python 3 from the main menu.
In the shell, start by importing the MCP3008 class from the GPIO Zero library:
from gpiozero import MCP3008
Create an object representing your analogue device:
pot = MCP3008(0)
Note the 0 represents the ADC’s channel 0. There are 8 channels (0 to 7), and you’re using the first one.
Try to read its value:
print(pot.value)
You should see a number between 0 and 1. How far the dial is turn is represented here.
Now read the value in a loop:
while True:
print(pot.value)
Try twisting the dial around to see the value change.
PWMLED
You can read values from the potentiometer, therefore, you should connect it to another GPIO device.
Add an LED to your breadboard and wire it to the Pi. Connecting it to GPIO pin 21
In your Python code, start by importing the PWMLED class:
from gpiozero import PWMLED
The PWMLED class lets you control the brightness of an LED using PWM, or pulse-width modulation.
Create a PWMLED object on pin 21:
led = PWMLED(21)
Test you can control the LED manually:
led.on() # the led should be lit
led.off() # the led should go off
led.value = 0.5 # the led should be lit at half brightness
Now connect the LED to the potentiometer:
led.source = pot.values
Turn the dial to change the LED brightness!
Source and values
GPIO Zero has a powerful feature: source and values.
Every device has a value property (the current value) and a values property (a stream of the device’s values at all times).
Every output device has a source property therefore it can be used to set what the device’s value should be.
pot.value gives the potentiometer’s current value (it’s read only, as it’s an input device)
led.value is the LED’s current value (it’s read/write: you can see what it is, and you can change it)
pot.values is a generator constantly yielding the potentiometer’s current value led.source is a way of setting where the LED gets its values from, rather than continuously setting the value of the LED to the value of the potentiometer in a loop, you can just pair the two devices. Therefore the line led.source = pot.values is equivalent to the following loop:
while True:
led.value = pot.value
Multiple potentiometers
Add a second potentiometer to your breadboard and connect it to the ADC’s channel 1.
Now create a second MCP3008 object on channel 1:
pot2 = MCP3008(1)
Make the LED blink:
led.blink()
The LED will blink continuously, one second on and one second off.
Change the on_time and off_time parameters to make it blink faster or slower:
led.blink(on_time=2, off_time=2)
led.blink(on_time=0.5, off_time=0.1)
Now use a loop to change the blink times according to the potentiometer values:
while True:
print(pot.value, pot2.value)
led.blink(on_time=pot.value, off_time=pot2.value, n=1, background=False)
Note you have to make it blink once in the foreground, so that each iteration gets time to finish before it updates the blink times.
Rotate the dials in order to make it blink at different speeds!
Also try changing blink to pulse and change on_time and off_time to fade_in_time and fade_out_time so that it fades in and out at different speeds, rather than just blinking on and off:
while True:
print(pot.value, pot2.value)
led.pulse(fade_in_time=pot.value, fade_out_time=pot2.value, n=1,background=False)
Rotate the dials in order to change the effect.
Resources
https://projects.raspberrypi.org/en/projects/physical-computing