Skip to content

Commit f25e774

Browse files
authored
Merge pull request raspberrypilearning#6 from raspberrypilearning/analogue
Add analogue worksheet - I'm happy and I know it
2 parents ab82df4 + b261223 commit f25e774

9 files changed

+190
-0
lines changed

analogue.md

+189
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,189 @@
1+
# Analogue Inputs
2+
3+
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 potentiometers.
4+
5+
## SPI
6+
7+
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.
8+
9+
1. Open a terminal window and install the `spidev` package:
10+
11+
```bash
12+
sudo apt-get install python3-spidev python-spidev
13+
```
14+
15+
1. Open the **Raspberry Pi Configuration** dialogue from the main menu and enable **SPI** in the **Interfaces** tab:
16+
17+
![Enable SPI](images/rcgui.png)
18+
19+
1. Click **OK** and reboot the Pi.
20+
21+
## Wiring the ADC (MCP3008)
22+
23+
The MCP3008 is an ADC providing eight input channels. The eight connectors on one side are connected to the Pi's GPIO pins, and the other eight are available to connect analogue input devices to read their values.
24+
25+
Place the MCP3008 chip on a breadboard and carefully wire it up as shown in the following diagram:
26+
27+
![MCP3008 wiring](images/mcp3008.png)
28+
29+
Alternatively, you could use the [Analog Zero](http://rasp.io/analogzero/) board, which provides the MCP3008 chip on a handy add-on board to save you from the complicated wiring.
30+
31+
## Add a potentiometer
32+
33+
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: it's simply a variable resistor, and the Pi reads the voltage (from 0V to 3.3V).
34+
35+
![Potentiometer](images/potentiometer.jpg)
36+
37+
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.
38+
39+
1. 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 as shown:
40+
41+
![Add a potentiometer](images/mcp3008-pot.png)
42+
43+
## Code
44+
45+
Now your potentiometer is connected and its value can be read from Python!
46+
47+
1. Open **Python 3** from the main menu.
48+
49+
1. In the shell, start by importing the `MCP3008` class from the GPIO Zero library:
50+
51+
```python
52+
from gpiozero import MCP3008
53+
```
54+
55+
1. Create an object representing your analogue device:
56+
57+
```python
58+
pot = MCP3008(0)
59+
```
60+
61+
Note the `0` represents the ADC's channel 0. There are 8 channels (0 to 7), and you're using the first one.
62+
63+
1. Try to read its value:
64+
65+
```python
66+
print(pot.value)
67+
```
68+
69+
You should see a number between 0 and 1. This represents how far the dial is turned.
70+
71+
1. Now read the value in a loop:
72+
73+
```python
74+
while True:
75+
print(pot.value)
76+
```
77+
78+
Try twisting the dial around to see the value change.
79+
80+
## PWMLED
81+
82+
Now you've tested you can read values from the potentiometer, you should connect it to another GPIO device.
83+
84+
1. Add an LED to your breadboard and wire it to the Pi, connecting it to GPIO pin 21:
85+
86+
![Add LED](images/mcp3008-pot-led.png)
87+
88+
1. In your Python code, start by importing the `PWMLED` class:
89+
90+
```python
91+
from gpiozero import PWMLED
92+
```
93+
94+
The `PWMLED` class lets you control the brightness of an LED using PWM, or pulse-width modulation.
95+
96+
1. Create a `PWMLED` object on pin 21:
97+
98+
```python
99+
led = PWMLED(21)
100+
```
101+
102+
1. Test you can control the LED manually:
103+
104+
```python
105+
led.on() # the led should be lit
106+
led.off() # the led should go off
107+
led.value = 0.5 # the led should be lit at half brightness
108+
```
109+
110+
1. Now connect the LED to the potentiometer:
111+
112+
```python
113+
led.source = pot.values
114+
```
115+
116+
1. Turn the dial to change the LED brightness!
117+
118+
### Source and values
119+
120+
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 which can be used to set what the device's value should be.
121+
122+
- `pot.value` gives the potentiometer's current value (it's read only, as it's an input device)
123+
- `led.value` is the LED's current value (it's read/write: you can see what it is, and you can change it)
124+
- `pot.values` is a generator constantly yielding the potentiometer's current value
125+
- `led.source` is a way of setting where the LED gets its values from
126+
127+
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:
128+
129+
```python
130+
while True:
131+
led.value = pot.value
132+
```
133+
134+
## Multiple potentiometers
135+
136+
1. Add a second potentiometer to your breadboard and connect it to the ADC's channel 1:
137+
138+
![Second potentiometer](images/mcp3008-2pots-led.png)
139+
140+
1. Now create a second `MCP3008` object on channel 1:
141+
142+
```python
143+
pot2 = MCP3008(1)
144+
```
145+
146+
1. Make the LED blink:
147+
148+
```python
149+
led.blink()
150+
```
151+
152+
The LED will blink continuously, one second on and one second off.
153+
154+
1. Change the `on_time` and `off_time` parameters to make it blink faster or slower:
155+
156+
```python
157+
led.blink(on_time=2, off_time=2)
158+
led.blink(on_time=0.5, off_time=0.1)
159+
```
160+
161+
1. Now use a loop to change the blink times according to the potentiometer values:
162+
163+
```python
164+
while True:
165+
print(pot.value, pot2.value)
166+
led.blink(on_time=pot.value, off_time=pot2.value, n=1, background=False)
167+
```
168+
169+
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.
170+
171+
1. Rotate the dials to make it blink at different speeds!
172+
173+
1. 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:
174+
175+
```python
176+
while True:
177+
print(pot.value, pot2.value)
178+
led.pulse(fade_in_time=pot.value, fade_out_time=pot2.value, n=1, background=False)
179+
```
180+
181+
1. Rotate the dials to change the effect.
182+
183+
## What next?
184+
185+
- Use potentiometers to control other GPIO Zero output devices
186+
- Use potentiometers to control the speed of motors
187+
- Use potentiometers to control the visual settings of a Camera Module in real time
188+
- Find more analogue sensors that will work with the ADC
189+
- Use potentiometers to control a player in a [PyGame Zero](http://pygame-zero.readthedocs.io) game, or in [Minecraft](https://www.raspberrypi.org/learning/getting-started-with-minecraft-pi/)

images/mcp3008-2pots-led.png

269 KB
Loading

images/mcp3008-2pots.png

268 KB
Loading

images/mcp3008-pot-led.png

271 KB
Loading

images/mcp3008-pot.png

267 KB
Loading

images/mcp3008.png

264 KB
Loading

images/potentiometer.jpg

42 KB
Loading

images/rcgui.png

34.9 KB
Loading

worksheet.md

+1
Original file line numberDiff line numberDiff line change
@@ -201,3 +201,4 @@ There are lots of other things you can control or monitor with your Raspberry Pi
201201
- [Using a light-dependent resistor](ldr.md)
202202
- [Using a PIR Sensor](pir.md)
203203
- [Using an ultrasonic distance sensor](distance.md)
204+
- [Analogue inputs](analogue.md)

0 commit comments

Comments
 (0)