├── CONTRIBUTING.md ├── LICENCE.md ├── README.md ├── analogue.md ├── buzzer.md ├── cover.png ├── distance.md ├── hardware.yml ├── images ├── LDR_and_cap_wired.png ├── Laser-tripwire_1-01.png ├── Laser-tripwire_2-01.png ├── Laser-tripwire_3-01.png ├── analogue-digital.png ├── button.png ├── buzzer-circuit.png ├── camjam1wiring.png ├── capacitor.png ├── gpio-setup.png ├── h-bridge.png ├── ldr.png ├── led-3v3.png ├── led-gpio17.png ├── mcb-wiring.png ├── mcb.png ├── mcp3008-2pots-led.png ├── mcp3008-pot-led.png ├── mcp3008-pot.png ├── mcp3008.png ├── pinout.png ├── pir_module.png ├── pir_potentiometers.png ├── pir_pots.jpg ├── pir_wiring.png ├── potentiometer.jpg ├── python3-app-menu.png ├── raspio-ports.jpg ├── rcgui.png ├── traffic-lights.png ├── ultrasonic-distance-sensor.png └── wiring-uds.png ├── ldr.md ├── learn.md ├── meta.yml ├── motors.md ├── overview.md ├── pir.md ├── trafficlights.md ├── worksheet-es.md └── worksheet.md /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing 2 | 3 | All contributions are assumed to be licensed under the same licence as the source, i.e. [CC BY-SA](http://creativecommons.org/licenses/by-sa/4.0/). This licence must remain in all derivatives of this work. 4 | 5 | ## Issues 6 | 7 | If you find a mistake, bug or other problem, please [open an issue](https://github.com/raspberrypilearning/physical-computing-with-python/issues) in this repository. 8 | 9 | ## Pull Requests 10 | 11 | If you fix a mistake, bug or problem or have something to contribute, please create a pull request for each modification. Please consider grouping modifications sensibly, i.e. don't bundle typo fixes in the same pull request as code changes, instead file them separately. 12 | 13 | Please note that sometimes things are done for pedagogical reasons so changes which make sense from a software engineering perspective (reducing duplication or making use of more advanced programming language features) may not be suitable to maintain the intended educational value. 14 | 15 | ## Derivatives 16 | 17 | The licence must remain in all derivatives of this work. 18 | 19 | ## Licence 20 | 21 | [![Creative Commons License](http://i.creativecommons.org/l/by-sa/4.0/88x31.png)](http://creativecommons.org/licenses/by-sa/4.0/) 22 | 23 | ***Physical Computing with Python*** by the [Raspberry Pi Foundation](http://www.raspberrypi.org) is licenced under a [Creative Commons Attribution 4.0 International License](http://creativecommons.org/licenses/by-sa/4.0/). 24 | 25 | Based on a work at https://github.com/raspberrypilearning/physical-computing-with-python 26 | -------------------------------------------------------------------------------- /LICENCE.md: -------------------------------------------------------------------------------- 1 | # Licence 2 | 3 | Unless otherwise specified, everything in this repository is covered by the following licence: 4 | 5 | [![Creative Commons License](http://i.creativecommons.org/l/by-sa/4.0/88x31.png)](http://creativecommons.org/licenses/by-sa/4.0/) 6 | 7 | ***Physical Computing with Python*** by the [Raspberry Pi Foundation](http://www.raspberrypi.org) is licenced under a [Creative Commons Attribution 4.0 International License](http://creativecommons.org/licenses/by-sa/4.0/). 8 | 9 | Based on a work at https://github.com/raspberrypilearning/physical-computing-with-python 10 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Physical Computing with Python 2 | 3 | **This is an archived resource.** The repo will remain available but the resource will no longer be maintained or updated. Some or all parts of the resource may no longer work. To see our latest resources, please visit [raspberrypi.org](http://projects.raspberrypi.org). 4 | 5 | ![Physical Computing with Python](cover.png) 6 | 7 | In this resource you will learn how to use the GPIO pins on your Raspberry Pi to interface with electronic components, such as LEDs and PIRs. 8 | 9 | # Contents 10 | 11 | - [Getting started](worksheet.md) 12 | - [Using an active buzzer](buzzer.md) 13 | - [Making traffic lights](trafficlights.md) 14 | - [Using a light-dependent resistor](ldr.md) 15 | - [Using a PIR Sensor](pir.md) 16 | - [Using an ultrasonic distance sensor](distance.md) 17 | 18 | ## Licence 19 | 20 | Unless otherwise specified, everything in this repository is covered by the following licence: 21 | 22 | [![Creative Commons License](http://i.creativecommons.org/l/by-sa/4.0/88x31.png)](http://creativecommons.org/licenses/by-sa/4.0/) 23 | 24 | ***Physical Computing with Python*** by the [Raspberry Pi Foundation](http://www.raspberrypi.org) is licenced under a [Creative Commons Attribution 4.0 International License](http://creativecommons.org/licenses/by-sa/4.0/). 25 | 26 | Based on a work at https://github.com/raspberrypilearning/physical-computing-with-python 27 | -------------------------------------------------------------------------------- /analogue.md: -------------------------------------------------------------------------------- 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. You should see a small notch, or dot, in one end of the chip. In the diagram, this end of the chip is alligned with column **19** on the breadboard. 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/) 190 | - Continue to the next worksheet on using [Motors](motors.md) 191 | -------------------------------------------------------------------------------- /buzzer.md: -------------------------------------------------------------------------------- 1 | # Buzzers 2 | 3 | There are two main types of buzzer: *active* and *passive*. 4 | 5 | A *passive* buzzer emits a tone when a voltage is applied across it. It also requires a specific signal to generate a variety of tones. The *active* buzzers are a lot simpler to use, so these are covered here. 6 | 7 | ## Connecting a buzzer 8 | 9 | An *active* buzzer can be connected just like an LED, but as they are a little more robust, you won't be needing a resistor to protect them. 10 | 11 | Set up the circuit as shown below: 12 | 13 | ![buzzer](images/buzzer-circuit.png) 14 | 15 | 1. Add `Buzzer` to the `from gpiozero import...` line: 16 | 17 | ```python 18 | from gpiozero import Buzzer 19 | from time import sleep 20 | ``` 21 | 22 | 1. Add a line below your creation of `button` and `lights` to add a `Buzzer` object: 23 | 24 | ```python 25 | buzzer = Buzzer(17) 26 | ``` 27 | 28 | 1. In GPIO Zero, a `Buzzer` works exactly like an `LED`, so try adding a `buzzer.on()` and `buzzer.off()` into your loop: 29 | 30 | ```python 31 | while True: 32 | buzzer.on() 33 | sleep(1) 34 | buzzer.off() 35 | sleep(1) 36 | 37 | ``` 38 | 39 | 1. A `Buzzer` has a `beep()` method which works like an `LED`'s `blink`. Try it out: 40 | 41 | ```python 42 | while True: 43 | buzzer.beep() 44 | ``` 45 | 46 | ## What Next? 47 | 48 | - Continue to the next worksheet on building a [traffic lights](trafficlights.md) system using GPIO Zero. 49 | -------------------------------------------------------------------------------- /cover.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/raspberrypilearning/physical-computing-with-python/7d9c90b90a728d2edebacaa75b0000fe8176d30f/cover.png -------------------------------------------------------------------------------- /distance.md: -------------------------------------------------------------------------------- 1 | # Ultrasonic distance sensor 2 | 3 | In air, sound travels at a speed of 343 metres per second. An ultrasonic distance sensor sends out pulses of ultrasound which are inaudible to humans, and detects the echo that is sent back when the sound bounces off a nearby object. It then uses the speed of sound to calculate the distance from the object. 4 | 5 | ![Ultrasonic distance sensor](images/ultrasonic-distance-sensor.png) 6 | 7 | ## Wiring 8 | 9 | The circuit connects to two GPIO pins (one for echo, one for trigger), the ground pin, and a 5V pin. You'll need to use a pair of resistors (330Ω and 470Ω) as a potential divider: 10 | 11 | ![wiring](images/wiring-uds.png) 12 | 13 | ## Code 14 | 15 | To use the ultrasonic distance sensor in Python, you need to know which GPIO pins the echo and trigger are connected to. 16 | 17 | 1. Open Python 3. 18 | 19 | 1. In the shell, enter the following line to import `DistanceSensor` from the GPIO Zero library: 20 | 21 | ```python 22 | from gpiozero import DistanceSensor 23 | ``` 24 | 25 | After each line, press **Enter** and the command will be executed immediately. 26 | 27 | 1. Create an instance of `DistanceSensor` using your echo and trigger pins: 28 | 29 | ```python 30 | ultrasonic = DistanceSensor(echo=17, trigger=4) 31 | ``` 32 | 33 | 1. See what distance it shows: 34 | 35 | ```python 36 | ultrasonic.distance 37 | ``` 38 | 39 | You should see a number: this is the distance to the nearest object, in metres. 40 | 41 | 1. Try using a loop to print the distance continuously, while waving your hand in front of the sensor to alter the distance reading: 42 | 43 | ```python 44 | while True: 45 | print(ultrasonic.distance) 46 | ``` 47 | 48 | The value should get smaller the closer your hand is to the sensor. Press **Ctrl + C** to exit the loop. 49 | 50 | ## Ranges 51 | 52 | As well as being able to see the distance value, you can also get the sensor to do things when the object is in or out of a certain range. 53 | 54 | 1. Use a loop to print different messages when the sensor is in range or out of range: 55 | 56 | ```python 57 | while True: 58 | ultrasonic.wait_for_in_range() 59 | print("In range") 60 | ultrasonic.wait_for_out_of_range() 61 | print("Out of range") 62 | ``` 63 | 64 | Now wave your hand in front of the sensor; it should switch between showing the message "In range" and "Out of range" as your hand gets closer and further away from the sensor. See if you can work out the point at which it changes. 65 | 66 | 1. The default range threshold is 0.3m. This can be configured when the sensor is initiated: 67 | 68 | ```python 69 | ultrasonic = DistanceSensor(echo=17, trigger=4, threshold_distance=0.5) 70 | ``` 71 | 72 | Alternatively, this can be changed after the sensor is created, by setting the `threshold_distance` property: 73 | 74 | ```python 75 | ultrasonic.threshold_distance = 0.5 76 | ``` 77 | 78 | 1. Try the previous loop again and observe the new range threshold. 79 | 80 | 1. The `wait_for` functions are **blocking**, which means they halt the program until they are triggered. Another way of doing something when the sensor goes in and out of range is to use `when` properties, which can be used to trigger actions in the background while other things are happening in the code. 81 | 82 | First, you need to create a function for what you want to happen when the sensor is in range: 83 | 84 | ```python 85 | def hello(): 86 | print("Hello") 87 | ``` 88 | 89 | Then set `ultrasonic.when_in_range` to the name of this function: 90 | 91 | ```python 92 | ultrasonic.when_in_range = hello 93 | ``` 94 | 95 | 1. Add another function for when the sensor goes out of range: 96 | 97 | ```python 98 | def bye(): 99 | print("Bye") 100 | 101 | ultrasonic.when_out_of_range = bye 102 | ``` 103 | 104 | Now these triggers are set up, you'll see "hello" printed when your hand is in range, and "bye" when it's out of range. 105 | 106 | 1. You may have noticed that the sensor distance stopped at 1 metre. This is the default maximum and can also be configured on setup: 107 | 108 | ```python 109 | ultrasonic = DistanceSensor(echo=17, trigger=4, max_distance=2) 110 | ``` 111 | 112 | Or after setup: 113 | 114 | ```python 115 | ultrasonic.max_distance = 2 116 | ``` 117 | 118 | 1. Try different values of `max_distance` and `threshold_distance`. 119 | 120 | ## What next? 121 | 122 | Now you've learned to use an ultrasonic distance sensor, you could: 123 | 124 | - Build a proximity sensor alert using a buzzer or a sound file 125 | - Build a Pi camera photo booth which is activated when a person is close enough to the camera 126 | - Build a robot with a distance sensor to stop it bumping into other objects 127 | - Continue to the next worksheet on [analogue inputs](analogue.md) 128 | -------------------------------------------------------------------------------- /hardware.yml: -------------------------------------------------------------------------------- 1 | - name: 1 x Solderless breadboard 2 | img: breadboard 3 | - name: Male-to-female jumper leads 4 | img: jumper-male-to-female 5 | - name: Female-to-female jumper leads 6 | img: jumper-female-to-female 7 | - name: Male-to-male jumper leads 8 | img: jumper-male-to-male 9 | - name: 1 x Tactile button 10 | img: tactile-push-button 11 | - name: 3 x LEDs 12 | img: led 13 | - name: Ultrasonic distance sensor 14 | img: ultrasonic-distance-sensor 15 | - name: Passive infrared motion sensor 16 | img: pir 17 | - name: Light dependent resistor 18 | img: ldr 19 | - name: 2 x 5V Micro Metal Gearmotor 20 | img: motor 21 | - name: 3 x 330Ω resistors 22 | img: resistor-330r 23 | - name: 470Ω resistor 24 | img: resistor-470r 25 | - name: 1 x 1μF Capacitor 26 | img: capacitor 27 | - name: Buzzer 28 | img: piezo-buzzer 29 | - name: motor controller 30 | img: motor-controller 31 | - name: battery pack 32 | img: battery-pack 33 | -------------------------------------------------------------------------------- /images/LDR_and_cap_wired.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/raspberrypilearning/physical-computing-with-python/7d9c90b90a728d2edebacaa75b0000fe8176d30f/images/LDR_and_cap_wired.png -------------------------------------------------------------------------------- /images/Laser-tripwire_1-01.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/raspberrypilearning/physical-computing-with-python/7d9c90b90a728d2edebacaa75b0000fe8176d30f/images/Laser-tripwire_1-01.png -------------------------------------------------------------------------------- /images/Laser-tripwire_2-01.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/raspberrypilearning/physical-computing-with-python/7d9c90b90a728d2edebacaa75b0000fe8176d30f/images/Laser-tripwire_2-01.png -------------------------------------------------------------------------------- /images/Laser-tripwire_3-01.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/raspberrypilearning/physical-computing-with-python/7d9c90b90a728d2edebacaa75b0000fe8176d30f/images/Laser-tripwire_3-01.png -------------------------------------------------------------------------------- /images/analogue-digital.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/raspberrypilearning/physical-computing-with-python/7d9c90b90a728d2edebacaa75b0000fe8176d30f/images/analogue-digital.png -------------------------------------------------------------------------------- /images/button.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/raspberrypilearning/physical-computing-with-python/7d9c90b90a728d2edebacaa75b0000fe8176d30f/images/button.png -------------------------------------------------------------------------------- /images/buzzer-circuit.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/raspberrypilearning/physical-computing-with-python/7d9c90b90a728d2edebacaa75b0000fe8176d30f/images/buzzer-circuit.png -------------------------------------------------------------------------------- /images/camjam1wiring.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/raspberrypilearning/physical-computing-with-python/7d9c90b90a728d2edebacaa75b0000fe8176d30f/images/camjam1wiring.png -------------------------------------------------------------------------------- /images/capacitor.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/raspberrypilearning/physical-computing-with-python/7d9c90b90a728d2edebacaa75b0000fe8176d30f/images/capacitor.png -------------------------------------------------------------------------------- /images/gpio-setup.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/raspberrypilearning/physical-computing-with-python/7d9c90b90a728d2edebacaa75b0000fe8176d30f/images/gpio-setup.png -------------------------------------------------------------------------------- /images/h-bridge.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/raspberrypilearning/physical-computing-with-python/7d9c90b90a728d2edebacaa75b0000fe8176d30f/images/h-bridge.png -------------------------------------------------------------------------------- /images/ldr.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/raspberrypilearning/physical-computing-with-python/7d9c90b90a728d2edebacaa75b0000fe8176d30f/images/ldr.png -------------------------------------------------------------------------------- /images/led-3v3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/raspberrypilearning/physical-computing-with-python/7d9c90b90a728d2edebacaa75b0000fe8176d30f/images/led-3v3.png -------------------------------------------------------------------------------- /images/led-gpio17.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/raspberrypilearning/physical-computing-with-python/7d9c90b90a728d2edebacaa75b0000fe8176d30f/images/led-gpio17.png -------------------------------------------------------------------------------- /images/mcb-wiring.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/raspberrypilearning/physical-computing-with-python/7d9c90b90a728d2edebacaa75b0000fe8176d30f/images/mcb-wiring.png -------------------------------------------------------------------------------- /images/mcb.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/raspberrypilearning/physical-computing-with-python/7d9c90b90a728d2edebacaa75b0000fe8176d30f/images/mcb.png -------------------------------------------------------------------------------- /images/mcp3008-2pots-led.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/raspberrypilearning/physical-computing-with-python/7d9c90b90a728d2edebacaa75b0000fe8176d30f/images/mcp3008-2pots-led.png -------------------------------------------------------------------------------- /images/mcp3008-pot-led.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/raspberrypilearning/physical-computing-with-python/7d9c90b90a728d2edebacaa75b0000fe8176d30f/images/mcp3008-pot-led.png -------------------------------------------------------------------------------- /images/mcp3008-pot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/raspberrypilearning/physical-computing-with-python/7d9c90b90a728d2edebacaa75b0000fe8176d30f/images/mcp3008-pot.png -------------------------------------------------------------------------------- /images/mcp3008.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/raspberrypilearning/physical-computing-with-python/7d9c90b90a728d2edebacaa75b0000fe8176d30f/images/mcp3008.png -------------------------------------------------------------------------------- /images/pinout.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/raspberrypilearning/physical-computing-with-python/7d9c90b90a728d2edebacaa75b0000fe8176d30f/images/pinout.png -------------------------------------------------------------------------------- /images/pir_module.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/raspberrypilearning/physical-computing-with-python/7d9c90b90a728d2edebacaa75b0000fe8176d30f/images/pir_module.png -------------------------------------------------------------------------------- /images/pir_potentiometers.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/raspberrypilearning/physical-computing-with-python/7d9c90b90a728d2edebacaa75b0000fe8176d30f/images/pir_potentiometers.png -------------------------------------------------------------------------------- /images/pir_pots.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/raspberrypilearning/physical-computing-with-python/7d9c90b90a728d2edebacaa75b0000fe8176d30f/images/pir_pots.jpg -------------------------------------------------------------------------------- /images/pir_wiring.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/raspberrypilearning/physical-computing-with-python/7d9c90b90a728d2edebacaa75b0000fe8176d30f/images/pir_wiring.png -------------------------------------------------------------------------------- /images/potentiometer.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/raspberrypilearning/physical-computing-with-python/7d9c90b90a728d2edebacaa75b0000fe8176d30f/images/potentiometer.jpg -------------------------------------------------------------------------------- /images/python3-app-menu.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/raspberrypilearning/physical-computing-with-python/7d9c90b90a728d2edebacaa75b0000fe8176d30f/images/python3-app-menu.png -------------------------------------------------------------------------------- /images/raspio-ports.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/raspberrypilearning/physical-computing-with-python/7d9c90b90a728d2edebacaa75b0000fe8176d30f/images/raspio-ports.jpg -------------------------------------------------------------------------------- /images/rcgui.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/raspberrypilearning/physical-computing-with-python/7d9c90b90a728d2edebacaa75b0000fe8176d30f/images/rcgui.png -------------------------------------------------------------------------------- /images/traffic-lights.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/raspberrypilearning/physical-computing-with-python/7d9c90b90a728d2edebacaa75b0000fe8176d30f/images/traffic-lights.png -------------------------------------------------------------------------------- /images/ultrasonic-distance-sensor.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/raspberrypilearning/physical-computing-with-python/7d9c90b90a728d2edebacaa75b0000fe8176d30f/images/ultrasonic-distance-sensor.png -------------------------------------------------------------------------------- /images/wiring-uds.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/raspberrypilearning/physical-computing-with-python/7d9c90b90a728d2edebacaa75b0000fe8176d30f/images/wiring-uds.png -------------------------------------------------------------------------------- /ldr.md: -------------------------------------------------------------------------------- 1 | # Light-dependent resistor (LDR) 2 | 3 | ## Analogue inputs 4 | 5 | In the world of electrical engineering, there are two type of input and output (I/O): analogue and digital. Digital I/O is fairly easy to understand; it's either *on* or *off*, *1* or *0*. 6 | 7 | When talking about voltages and the Raspberry Pi, any input that is approximately below 1.8V is considered *off* and anything above 1.8V is considered *on*. For output, 0V is off and 3.3V is on. 8 | 9 | Analogue I/O is a little trickier. With an analogue input, we can have a range of voltages from 0V up to 3.3V, and the Raspberry Pi is unable to detect exactly what that voltage is. 10 | 11 | ![](images/analogue-digital.png) 12 | 13 | How, then, can we use a Raspberry Pi to determine the value of an analogue input, if it can only tell when the voltage to a GPIO pin goes above 1.8V? 14 | 15 | ### Using a capacitor for analogue inputs 16 | 17 | Capacitors are electrical components that store charge. 18 | 19 | ![](images/capacitor.png) 20 | 21 | When current is fed into a capacitor, it will begin to store charge. The voltage across the capacitor will start off low, and increase as the charge builds up. 22 | 23 | By putting a resistor in series with the capacitor, you can slow the speed at which it charges. With a high resistance, the capacitor will charge slowly, whereas a low resistance will let it charge quickly. 24 | 25 | If you time how long it takes the capacitor's voltage to get over 1.8V (or be *on*), you can work out the resistance of the component in series with it. 26 | 27 | ## Light-dependent resistors 28 | 29 | An LDR (sometimes called a photocell) is a special type of resistor. 30 | 31 | ![](images/ldr.png) 32 | 33 | When light hits the LDR, its resistance is very low, but when it's in the dark its resistance is very high. 34 | 35 | By placing a capacitor in series with an LDR, the capacitor will charge at different speeds depending on whether it's light or dark. 36 | 37 | ## Creating a light-sensing circuit 38 | 39 | 1. Place an LDR into your breadboard, as shown below: 40 | 41 | ![](images/Laser-tripwire_1-01.png) 42 | 43 | 1. Now place a capacitor in series with the LDR. As the capacitor is a polar component, you must make sure the long leg is on the same track as the LDR leg. 44 | 45 | ![](images/Laser-tripwire_2-01.png) 46 | 47 | 1. Finally, add jumper leads to connect the two components to your Raspberry Pi. 48 | 49 | ![](images/Laser-tripwire_3-01.png) 50 | 51 | ## Coding a light sensor 52 | 53 | Luckily, most of the complicated code you would have to write to detect the light levels received by the LDR has been abstracted away by the `gpiozero` library. This library will handle the timing of the capacitor's charging and discharging for you. 54 | 55 | Use the following code to set up the light sensor: 56 | 57 | ```python 58 | from gpiozero import LightSensor, Buzzer 59 | 60 | ldr = LightSensor(4) # alter if using a different pin 61 | while True: 62 | print(ldr.value) 63 | 64 | ``` 65 | 66 | Run this code, then cover the LDR with your hand and watch the value change. Try shining a strong light onto the LDR. 67 | 68 | ## What Next? 69 | 70 | - You could have a go at using your new knowledge of LDRs to build a [laser-tripwire](https://www.raspberrypi.org/learning/laser-tripwire/). 71 | - Continue to the next worksheet on using a [Passive Infra-red Sensor](pir.md) 72 | -------------------------------------------------------------------------------- /learn.md: -------------------------------------------------------------------------------- 1 | By working through this resource, you will learn how to use Python and GPIO Zero to control: 2 | 3 | - [LEDs and buttons](physical-computing-with-python/worksheet.md) 4 | - [an active buzzer](physical-computing-with-python/buzzer.md) 5 | - [traffic lights](physical-computing-with-python/trafficlights.md) 6 | - [a light-dependent resistor](physical-computing-with-python/ldr.md) 7 | - [a PIR motion sensor](physical-computing-with-python/pir.md) 8 | - [an ultrasonic distance sensor](physical-computing-with-python/distance.md) 9 | - [analogue inputs](physical-computing-with-python/analogue.md) 10 | - [motors](physical-computing-with-python/motors.md) 11 | 12 | This resource covers elements from the following strands of the [Raspberry Pi Digital Making Curriculum](https://www.raspberrypi.org/curriculum/): 13 | 14 | - [Use basic programming constructs to create simple programs](https://www.raspberrypi.org/curriculum/programming/creator) 15 | - [Use basic digital, analogue, and electromechanical components](https://www.raspberrypi.org/curriculum/physical-computing/creator) 16 | -------------------------------------------------------------------------------- /meta.yml: -------------------------------------------------------------------------------- 1 | title: Physical Computing with Python 2 | category: learn 3 | theme: green 4 | -------------------------------------------------------------------------------- /motors.md: -------------------------------------------------------------------------------- 1 | # Motors 2 | 3 | Motors are great for physical computing: they allow you to turn a wheel forwards and backwards, or make something spin around. 4 | 5 | A motor can't be controlled directly from the Raspberry Pi's GPIO pins, because it needs a variable supply of 5 volts. This means you need to power it separately. However, motor controller add-on boards can be used to provide this functionality. 6 | 7 | In this guide, you'll be controlling two motors from your Raspberry Pi using Python on the desktop. First, it's best just to learn how to control the motor. Then, once you have it working, you could easily use your code to drive a Raspberry Pi-powered robot by detaching the monitor, mouse, and keyboard and building a robot around a chassis. 8 | 9 | ## H bridge 10 | 11 | A motor can be driven forwards or backwards depending on which way around current flows through it. However, it would be awkward to have to rewire a motor, every time you want to change the direction it spins. To overcome this issue, motor controller boards include an H bridge. An H bridge uses 4 transistors to allow digital control of which way current flows through the motor. Most H bridges also contain *flyback diodes*. A flyback diode prevents the voltage spike that is generated by the motor when it is no longer powered (but still spinning) from damaging delicate electronics. 12 | 13 | ![H-Bridge](images/h-bridge.png) 14 | 15 | *Image credit: [Wikipedia](https://en.wikipedia.org/wiki/H_bridge), CC BY-SA* 16 | 17 | ## Wiring 18 | 19 | You'll need to wire up two motors and your battery pack using the motor controller. 20 | 21 | 1. With your Pi switched off, mount your motor controller board on the GPIO pins: 22 | 23 | ![Motor controller board](images/mcb.png) 24 | 25 | 1. Connect a battery pack to the power ports of the motor controller, connecting the positive (red) battery wire to the positive (+) power terminal on the motor controller, and the negative (black) battery wire to the negative (-) power terminal on the motor controller, and connect two motors: 26 | 27 | ![Connect battery pack](images/mcb-wiring.png) 28 | 29 | 1. You'll need to know which GPIO pins your motor controller uses. Refer to the board's documentation. This will usually be described as Motor A and Motor B, or MA1, MA2, MB1, and MB2. Make a note of these pin numbers. If you're not sure which is which, you can investigate this next. 30 | 31 | ## Output devices 32 | 33 | First, you should learn to control motors by controlling the pins individually. 34 | 35 | 1. Boot the Pi and open Python 3. 36 | 37 | 1. In the shell, enter the following line to import `OutputDevice` from the GPIO Zero library: 38 | 39 | ```python 40 | from gpiozero import OutputDevice 41 | ``` 42 | 43 | After each line, press **Enter** and the command will be executed immediately. 44 | 45 | 1. Now create an instance of an `OutputDevice` on each of the pins for one motor: 46 | 47 | ```python 48 | a = OutputDevice(4) 49 | b = OutputDevice(14) 50 | ``` 51 | 52 | 1. Now you should be able to make the motor spin by turning one of the pins on: 53 | 54 | ```python 55 | a.on() 56 | ``` 57 | 58 | The motor should now be spinning! If not, check you are addressing the right pin numbers. The two pins should be connected to the same motor. Also, check your wiring and your batteries. 59 | 60 | 1. Now try turning that pin off, and turning the other pin on: 61 | 62 | ```python 63 | a.off() 64 | b.on() 65 | ``` 66 | 67 | The motor should now be spinning in the opposite direction. 68 | 69 | 1. To stop the motor, just make sure both pins are off: 70 | 71 | ```python 72 | a.off() 73 | b.off() 74 | ``` 75 | 76 | 1. Now try the same with the second motor: 77 | 78 | ```python 79 | c = OutputDevice(17) 80 | d = OutputDevice(27) 81 | c.on() 82 | ``` 83 | 84 | 1. And backwards: 85 | 86 | ```python 87 | c.off() 88 | d.on() 89 | ``` 90 | 91 | 1. And stop: 92 | 93 | ```python 94 | c.off() 95 | d.off() 96 | ``` 97 | 98 | 1. Try controlling one of the motors in a loop: 99 | 100 | ```python 101 | from time import sleep 102 | 103 | for i in range(5): 104 | b.off() 105 | a.on() 106 | sleep(5) 107 | a.off() 108 | b.on() 109 | sleep(5) 110 | b.off() 111 | ``` 112 | 113 | The motor should now spin forwards for 5 seconds then backwards for 5 seconds, repeat this 5 times, and then stop. 114 | 115 | ## PWM 116 | 117 | So far, you have used simple on/off commands to control your motors. PWM (pulse-width modulation) allows you to control the speed. The `on()` function sets the motor to go at full speed, but you can control this to make the motor go at a fraction of this speed. 118 | 119 | 1. Since you're going to reuse the same pins in a different way, you'll have to close the connections to the pins. The easiest way to do that is to restart the Python shell by clicking **Shell > Restart shell**. 120 | 121 | 1. Import the `PWMOutputDevice` class: 122 | 123 | ```python 124 | from gpiozero import PWMOutputDevice 125 | ``` 126 | 127 | 1. Create new connections to each of your pins as before, but using `PWMOutputDevice`: 128 | 129 | ```python 130 | a = PWMOutputDevice(4) 131 | b = PWMOutputDevice(14) 132 | c = PWMOutputDevice(17) 133 | d = PWMOutputDevice(27) 134 | ``` 135 | 136 | 1. You can still use `a.on()`, `a.off()` and so on, but you can also set the device's value to a number between `0` and `1`. Try half: 137 | 138 | ```python 139 | a.value = 0.5 140 | ``` 141 | 142 | The motor should now be spinning at half speed. 143 | 144 | 1. To turn the motor in the opposite direction, turn `a` off (or set its value to `0`) and set `b`'s value to `0.5`: 145 | 146 | ```python 147 | a.value = 0 148 | b.value = 0.5 149 | ``` 150 | 151 | The motor should now be spinning backwards at half speed. 152 | 153 | 1. Try controlling both motors at different speeds to compare: 154 | 155 | ```python 156 | a.value = 0.5 157 | b.value = 0 158 | c.value = 1 159 | d.value = 0 160 | ``` 161 | 162 | 1. Try increasing the speed in a loop: 163 | 164 | ```python 165 | b.off() 166 | d.off() 167 | for i in range(1, 11): 168 | speed = i / 10 169 | print(speed) 170 | a.value = speed 171 | b.value = speed 172 | ``` 173 | 174 | The motors should now speed up from 0 (stopped) to 0.1, 0.2 and up to 1. 175 | 176 | Be aware, though, that the motor may not move until it gets above a certain speed, as there may not be enough power to engage it. 177 | 178 | ## Motor class 179 | 180 | Now you've learned how setting pins high and low can control a motor, you should proceed to using the built-in `Motor` class; this has all the functionality you just learned about, provided in a simple way, including PWM for speed. 181 | 182 | 1. Restart the shell again (**Ctrl + F6**). 183 | 184 | 1. Import the `Motor` class: 185 | 186 | ```python 187 | from gpiozero import Motor 188 | ``` 189 | 190 | 1. Now create a `Motor` instance using the pin numbers for each motor: 191 | 192 | ```python 193 | motor1 = Motor(4, 14) 194 | motor2 = Motor(17, 27) 195 | ``` 196 | 197 | Note: to make it easier to see which pin is which, you can use `Motor(forward=4, backward=14)` for future reference. 198 | 199 | 1. Now drive one of the motors forward using the following code: 200 | 201 | ```python 202 | motor1.forward() 203 | ``` 204 | 205 | 1. And the other backwards: 206 | 207 | ```python 208 | motor2.backward() 209 | ``` 210 | 211 | 1. Or try half speed: 212 | 213 | ```python 214 | motor1.forward(0.5) 215 | motor2.backward(0.5) 216 | ``` 217 | 218 | 1. The `Motor` class also allows you to reverse the motor's direction. Try using this loop: 219 | 220 | ```python 221 | motor1.forward() 222 | motor2.backward() 223 | while True: 224 | sleep(5) 225 | motor1.reverse() 226 | motor2.reverse() 227 | ``` 228 | 229 | This will make the motors spin in opposite directions, then switch every five seconds. Press **Ctrl + C** to exit the loop. 230 | 231 | 1. Now stop the motors: 232 | 233 | ```python 234 | motor1.stop() 235 | motor2.stop() 236 | ``` 237 | 238 | ## Robot class 239 | 240 | If you had a robot with two wheels you would want to control the two motors together, rather than separately, just like you did for the two pins of each motor. Luckily, there's also a `Robot` class in GPIO Zero. 241 | 242 | 1. Restart the shell again (**Ctrl + F6**). 243 | 244 | 1. Import the `Robot` class: 245 | 246 | ```python 247 | from gpiozero import Robot 248 | ``` 249 | 250 | 1. Now create a `Robot` instance using the pin numbers for each motor: 251 | 252 | ```python 253 | robot = Robot((4, 14), (17, 27)) 254 | ``` 255 | 256 | Note: to make it easier to see which pin is which, you can use `Robot(left=(4, 14), right=(17, 27))` for future reference. 257 | 258 | 1. Now drive one of the motors forward using the following code: 259 | 260 | ```python 261 | robot.forward() 262 | ``` 263 | 264 | Both motors should now be driving forwards. 265 | 266 | 1. And backwards: 267 | 268 | ```python 269 | robot.backward() 270 | ``` 271 | 272 | Both motors should now be driving backwards. 273 | 274 | 1. Try reverse a few times: 275 | 276 | ```python 277 | robot.reverse() 278 | robot.reverse() 279 | robot.reverse() 280 | ``` 281 | 282 | 1. Or try half speed: 283 | 284 | ```python 285 | robot.forward(0.5) 286 | ``` 287 | 288 | 1. That's not all! What would happen if the left wheel went forwards and the right wheel went backwards? The robot would turn right. Try it: 289 | 290 | ```python 291 | robot.right() 292 | ``` 293 | 294 | 1. Then try this: 295 | 296 | ```python 297 | robot.left() 298 | ``` 299 | 300 | 1. Now stop the robot: 301 | 302 | ```python 303 | robot.stop() 304 | ``` 305 | 306 | ## What next? 307 | 308 | Now you've learned how motors work, you can try: 309 | 310 | - Making your own robot with our [Build a robot](https://www.raspberrypi.org/learning/robo-butler/) resource 311 | - Making a [spinning flower wheel](https://www.raspberrypi.org/learning/spinning-flower-wheel/) 312 | -------------------------------------------------------------------------------- /overview.md: -------------------------------------------------------------------------------- 1 | In this resource you will learn how to use the GPIO pins on your Raspberry Pi to interface with electronic components, such as LEDs and PIRs. 2 | -------------------------------------------------------------------------------- /pir.md: -------------------------------------------------------------------------------- 1 | # Passive infrared motion sensor (PIR) 2 | 3 | Humans and other animals emit radiation all the time. This is nothing to be concerned about, though, as the type of radiation we emit is infrared radiation (IR), which is pretty harmless at the levels at which it is emitted by humans. In fact, all objects at temperatures above absolute zero (-273.15C) emit infrared radiation. 4 | 5 | A PIR sensor detects changes in the amount of infrared radiation it receives. When there is a significant change in the amount of infrared radiation it detects, then a pulse is triggered. This means that a PIR sensor can detect when a human (or any animal) moves in front of it. 6 | 7 | ![pir](images/pir_module.png) 8 | 9 | ## Wiring a PIR sensor 10 | 11 | The pulse emitted when a PIR detects motion needs to be amplified, and so it needs to be powered. There are three pins on the PIR: they should be labelled **Vcc**, **Gnd**, and **Out**. These labels are sometimes concealed beneath the Fresnel lens (the white cap), which you can temporarily remove to see the pin labels. 12 | 13 | ![wiring](images/pir_wiring.png) 14 | 15 | 1. As shown above, the **Vcc** pin needs to be attached to a **5V** pin on the Raspberry Pi. 16 | 1. The **Gnd** pin on the PIR sensor can be attached to **any** ground pin on the Raspberry Pi. 17 | 1. Lastly, the **Out** pin needs to be connected to **any** of the GPIO pins. 18 | 19 | ## Tuning a PIR 20 | 21 | Most PIR sensors have two potentiometers on them. These can control the sensitivity of the sensors, and also the period of time for which the PIR will signal when motion is detected. 22 | 23 | ![pir pots](images/pir_pots.jpg) 24 | 25 | In the image above, the potentiometer on the right controls the sensitivity, and the potentiometer on the left controls the timeout. Here, both are turned fully anti-clockwise, meaning that the sensitivity and timeout are at their lowest. 26 | 27 | When the timeout is turned fully anti-clockwise, the PIR will output a signal for about 2.5 seconds, whenever motion is detected. If the potentiometer is turned fully clockwise, the output signal will last for around 250 seconds. When tuning the sensitivity, it is best to have the timeout set as low as possible. 28 | 29 | ## Detecting motion 30 | 31 | You can detect motion with the PIR using the code below: 32 | 33 | ```python 34 | from gpiozero import MotionSensor 35 | 36 | pir = MotionSensor(4) 37 | 38 | while True: 39 | pir.wait_for_motion() 40 | print("You moved") 41 | pir.wait_for_no_motion() 42 | ``` 43 | 44 | ## What Next? 45 | 46 | - Now you know how to use a PIR, why not have a go at building a [Parent Detector](https://www.raspberrypi.org/learning/parent-detector)? 47 | - Continue to the next worksheet on using an [Ultrasonic Distance Sensor](distance.md). 48 | -------------------------------------------------------------------------------- /trafficlights.md: -------------------------------------------------------------------------------- 1 | # Traffic lights 2 | 3 | For this worksheet you'll need a breadboard, three LEDs, a button, a buzzer, and the necessary jumper cables and resistors. You can purchase these individually, or get everything you need in the [CamJam EduKit](https://thepihut.com/products/camjam-edukit). 4 | 5 | ## Wiring 6 | 7 | To get started, you'll need to place all the components on the breadboard and connect them to the appropriate GPIO pins on the Raspberry Pi. 8 | 9 | 1. First, you need to understand how each component is connected: 10 | 11 | - A push button requires 1 ground pin and 1 GPIO pin 12 | - An LED requires 1 ground pin and 1 GPIO pin, with a current limiting resistor 13 | - A buzzer requires 1 ground pin and 1 GPIO pin 14 | 15 | Each component requires its own individual GPIO pin, but components can share a ground pin. We will use the breadboard to enable this. 16 | 17 | 1. Place the components on the breadboard and connect them to the Raspberry Pi GPIO pins, according to the following diagram: 18 | 19 | ![GPIO diagram](images/camjam1wiring.png) 20 | 21 | Note that the row along the long side of the breadboard is connected to a ground pin on the Raspberry Pi, so all the components in that row (which is used as a ground rail) are hence connected to ground. 22 | 23 | 1. Observe the following table, showing which GPIO pin each component is connected to: 24 | 25 | | Component | GPIO pin | 26 | | --------- | :------: | 27 | | Button | 21 | 28 | | Red LED | 25 | 29 | | Amber LED | 8 | 30 | | Green LED | 7 | 31 | | Buzzer | 15 | 32 | 33 | ## Dive into Python 34 | 35 | Open the Python application IDLE and get started by testing out the button. 36 | 37 | 1. Open **Python 3** from the main menu: 38 | 39 | ![Python 3](images/python3-app-menu.png) 40 | 41 | 1. Create a new file by clicking **File** > **New File**. This will open up a second window. 42 | 43 | 1. Save the new file straight away by clicking **File** > **Save**; name the file `trafficlights.py` and save it in your home folder. 44 | 45 | 1. Enter the following code: 46 | 47 | ```python 48 | from gpiozero import Button 49 | 50 | button = Button(21) 51 | 52 | while True: 53 | print(button.is_pressed) 54 | ``` 55 | 56 | In GPIO Zero, you create an object for each component used. Each component interface must be imported from the `gpiozero` module, and an instance created on the GPIO pin number to which it is connected. 57 | 58 | 1. Save and run the code by pressing `Ctrl + S` and `F5`. 59 | 60 | 1. This will bring the original Python window into focus and will be constantly printing `False`. When you press the button this will switch to `True`, and when you let go it will return to `False`. 61 | 62 | `button.is_pressed` is a property of the `button` object, which provides the state of the button (pressed or not) at any given time. 63 | 64 | 1. Now return to the code window and modify your `while` loop to show the following: 65 | 66 | ```python 67 | while True: 68 | if button.is_pressed: 69 | print("Hello") 70 | else: 71 | print("Goodbye") 72 | ``` 73 | 74 | 1. Run the code again and you'll see "Hello" printed when the button is pressed, and "Goodbye" when the button is not pressed. 75 | 76 | 1. Modify the loop again: 77 | 78 | ```python 79 | while True: 80 | button.wait_for_press() 81 | print("Pressed") 82 | button.wait_for_release() 83 | print("Released") 84 | ``` 85 | 86 | 1. When you run the code this time, nothing will happen until you press the button, when you'll see "Pressed", then when you let go you'll see "Released". This will occur each time the button is pressed, but rather than continuously printing one or the other, it only does it once per press. 87 | 88 | ## Add an LED 89 | 90 | Now you'll add an LED into the code and use GPIO Zero to allow the button to determine when the LED is lit. 91 | 92 | 1. In your code, add to the `from gpiozero import...` line at the top to also bring in `LED`: 93 | 94 | ```python 95 | from gpiozero import Button, LED 96 | ``` 97 | 98 | 1. Add a line below `button = Button(21)` to create an instance of an `LED` object: 99 | 100 | ```python 101 | led = LED(25) 102 | ``` 103 | 104 | 1. Now modify your `while` loop to turn the LED on when the button is pressed: 105 | 106 | ```python 107 | while True: 108 | button.wait_for_press() 109 | led.on() 110 | button.wait_for_release() 111 | led.off() 112 | ``` 113 | 114 | 1. Run your code and the LED will come on when you press the button. Hold the button down to keep the LED lit. 115 | 116 | 1. Now swap the `on` and `off` lines to reverse the logic: 117 | 118 | ```python 119 | while True: 120 | led.on() 121 | button.wait_for_press() 122 | led.off() 123 | button.wait_for_release() 124 | ``` 125 | 126 | 1. Run the code and you'll see the LED stays on until the button is pressed. 127 | 128 | 1. Now replace `led.on()` with `led.blink()`: 129 | 130 | ```python 131 | while True: 132 | led.blink() 133 | button.wait_for_press() 134 | led.off() 135 | button.wait_for_release() 136 | ``` 137 | 138 | 1. Run the code and you'll see the LED blink on and off until the button is pressed, at which point it will turn off completely. When the button is released, it will start blinking again. 139 | 140 | 1. Try adding some parameters to `blink` to make it blink faster or slower: 141 | 142 | - `led.blink(2, 2)` - 2 seconds on, 2 seconds off 143 | - `led.blink(0.5, 0.5)` - half a second on, half a second off 144 | - `led.blink(0.1, 0.2)` - one tenth of a second on, one fifth of a second off 145 | 146 | `blink`'s first two (optional) parameters are `on_time` and `off_time`': they both default to 1 second. 147 | 148 | ## Traffic lights 149 | 150 | You have three LEDs: red, amber, and green. Perfect for traffic lights! There's even a built-in interface for traffic lights in GPIO Zero. 151 | 152 | 1. Amend the `from gpiozero import...` line to replace `LED` with `TrafficLights`: 153 | 154 | ```python 155 | from gpiozero import Button, TrafficLights 156 | ``` 157 | 158 | 1. Replace your `led = LED(25)` line with the following: 159 | 160 | ```python 161 | lights = TrafficLights(25, 8, 7) 162 | ``` 163 | 164 | The `TrafficLights` interface takes three GPIO pin numbers, one for each pin: red, amber, and green (in that order). 165 | 166 | 1. Now amend your `while` loop to control the `TrafficLights` object: 167 | 168 | ```python 169 | while True: 170 | button.wait_for_press() 171 | lights.on() 172 | button.wait_for_release() 173 | lights.off() 174 | ``` 175 | 176 | The `TrafficLights` interface is very similar to that of an individual LED: you can use `on`, `off`, and `blink`, all of which control all three lights at once. 177 | 178 | 1. Try the `blink` example: 179 | 180 | ```python 181 | while True: 182 | lights.blink() 183 | button.wait_for_press() 184 | lights.off() 185 | button.wait_for_release() 186 | ``` 187 | 188 | ## Add a buzzer 189 | 190 | Now you'll add your buzzer to make some noise. 191 | 192 | 1. Add `Buzzer` to the `from gpiozero import...` line: 193 | 194 | ```python 195 | from gpiozero import Button, TrafficLights, Buzzer 196 | ``` 197 | 198 | 1. Add a line below your creation of `button` and `lights` to add a `Buzzer` object: 199 | 200 | ```python 201 | buzzer = Buzzer(15) 202 | ``` 203 | 204 | 1. `Buzzer` works exactly like `LED`, so try adding a `buzzer.on()` and `buzzer.off()` into your loop: 205 | 206 | ```python 207 | while True: 208 | lights.on() 209 | buzzer.off() 210 | button.wait_for_press() 211 | lights.off() 212 | buzzer.on() 213 | button.wait_for_release() 214 | ``` 215 | 216 | 1. `Buzzer` has a `beep()` method which works like `LED`'s `blink`. Try it out: 217 | 218 | ```python 219 | while True: 220 | lights.blink() 221 | buzzer.beep() 222 | button.wait_for_press() 223 | lights.off() 224 | buzzer.off() 225 | button.wait_for_release() 226 | ``` 227 | 228 | ## Traffic lights sequence 229 | 230 | As well as controlling the whole set of lights together, you can also control each LED individually. With traffic light LEDs, a button and a buzzer, you can create your own traffic lights sequence, complete with pedestrian crossing! 231 | 232 | 1. At the top of your file, below `from gpiozero import...`, add a line to import the `sleep` function: 233 | 234 | ```python 235 | from time import sleep 236 | ``` 237 | 238 | 1. Modify your loop to perform an automated sequence of LEDs being lit: 239 | 240 | ```python 241 | while True: 242 | lights.green.on() 243 | sleep(1) 244 | lights.amber.on() 245 | sleep(1) 246 | lights.red.on() 247 | sleep(1) 248 | lights.off() 249 | ``` 250 | 251 | 1. Add a `wait_for_press` so that pressing the button initiates the sequence: 252 | 253 | ```python 254 | while True: 255 | button.wait_for_press() 256 | lights.green.on() 257 | sleep(1) 258 | lights.amber.on() 259 | sleep(1) 260 | lights.red.on() 261 | sleep(1) 262 | lights.off() 263 | ``` 264 | 265 | Try some more sequences of your own. 266 | 267 | 1. Now try creating the full traffic lights sequence: 268 | 269 | - Green on 270 | - Amber on 271 | - Red on 272 | - Red and amber on 273 | - Green on 274 | 275 | Be sure to turn the correct lights on and off at the right time, and make sure you use `sleep` to time the sequence perfectly. 276 | 277 | 1. Try adding the button for a pedestrian crossing. The button should move the lights to red (not immediately), and give the pedestrians time to cross before moving back to green until the button is pressed again. 278 | 279 | 1. Now try adding a buzzer to beep quickly to indicate that it is safe to cross, for the benefit of visually impaired pedestrians. 280 | 281 | ## What next? 282 | 283 | - Try adding a second button for the other side of the road. You'll probably need to use GPIO Zero `button.when_pressed` rather than `wait_for_press`, which can only be used for one button at a time. 284 | - Refer to the documentation at [gpiozero.readthedocs.org](https://gpiozero.readthedocs.org/) for more information on what can be done with GPIO Zero. 285 | - Continue to the next worksheet on using a [Light Dependent Resitor](ldr.md) 286 | -------------------------------------------------------------------------------- /worksheet-es.md: -------------------------------------------------------------------------------- 1 | # Empezando a controlar pins con GPIO Zero 2 | 3 | ## Pins GPIO 4 | 5 | Al conjunto de pines que se encuentran a un lado de la Raspberry Pi se les llama pins GPIO (General-Purpose Input/Output) o Entradas y Salidas de Propósito General. 6 | 7 | Estos pines permiten a la Raspberry controlar cosas en el mundo real. Puedes conectar componentes electrónicos a estos pines: estos componentes pueden ser de salida, como los LEDs (Diodos Emisores de Luz) que se pueden encender y apagar a voluntad, o componentes de entrada, como un botón o un sensor que puedes usar para disparar otros eventos. Por ejemplo, puedes encender un LED cada vez que detectes que un botón ha sido pulsado. 8 | 9 | Con la librería GPIO Zero, podrás controlar los pins GPIO de la Raspberry de manera sencilla. Hay 40 pins en la Raspberry Pi (26 en los modelos más antiguos) que permiten diferentes funciones. 10 | 11 | La etiqueta de identificación RasPIO puede ayudarte a identificar cuál es el uso de cada pin. Asegúrate de que la etiqueta está colocada de manera que el pequeño agujero quede al lado de los puertos USB, ligeramente hacia afuera de la placa. 12 | 13 | ![](images/raspio-ports.jpg) 14 | 15 | Si no tienes una etiqueta, esta guía puede ayudarte a identificar el número de cada pin. 16 | 17 | ![](images/pinout.png) 18 | 19 | Verás que hay pins que están marcados con 3V3, 5V, GND y GP2, GP3, etc: 20 | | | | | 21 | | --- | --- | --- | 22 | |3V3|3.3 voltios|Cualquier cosa que conectes a estos pins recibirá un voltaje de 3.3V| 23 | |5V|5 voltios|Cualquier cosa que conectes a estos pins recibirá un voltaje de 5V| 24 | |GND|Tierra|Tierra o cero voltios, usado para cerrar el circuito.| 25 | |GP2|GPIO pin 2|Estos pines son de propósito general y se pueden configurar como entrada o como salida 26 | |ID_SC/ID_SD/DNC|Pins de propósito especial| 27 | 28 | ## Encender un LED 29 | Prueba a conectar un LED a los pins de 3.3V y GND con una resistencia. 30 | 31 | ![](images/led-3v3.png) 32 | 33 | El LED se debería encender. Siempre estará encendido, porque está conectado a un pin de 3.3 voltios. 34 | 35 | Ahora prueba a moverlo del pin 3.3V al pin GPIO 17: 36 | 37 | ![](images/led-gpio17.png) 38 | 39 | El LED ahora se debería apagar, pero como está conectado a un pin GPIO podemos controlarlo con código. 40 | 41 | ## Encendiendo y apagando un LED 42 | 43 | GPIO Zero es una nueva librería de Python que proporciona una interfaz sencilla para interactuar con componentes a través de los pines GPIO 44 | 1. Abre Python 3 desde el menú principal 45 | 46 | 1. Puedes encender y apagar un LED tecleando comandos directamente en la ventana del intérprete de Python (también llamada Python shell). Vamos a hacerlo así primero, importando la librería GPIO Zero. También es necesario establecer qué pin GPIO es el que vamos a usar; en este caso será el 17. Junto a los símbolos `>>>`, teclea: 47 | 48 | ``` python 49 | from gpiozero import LED 50 | 51 | led = LED(17) 52 | ``` 53 | Pulsa **Enter** en el teclado. 54 | 55 | 1. Para que hacer que el LED se encienda, escribe la siguiente línea y pulsa Enter: 56 | 57 | ``` python 58 | led.on() 59 | ``` 60 | 61 | 1. Para apagar el LED puedes teclear: 62 | 63 | ``` python 64 | led.off() 65 | ``` 66 | 67 | ## Haciendo parpadear el LED 68 | 69 | Con la ayuda de la librería time y un pequeño bucle, podemos hacer que el LED parpadee. 70 | 71 | 1. Crea un nuevo archivo en **Archivo** > **Archivo nuevo**. 72 | 1. Guarda el archivo en **Archivo** > **Guardar**. 73 | 1. Guarda el archivo como `gpio_led.py` 74 | 1. Escribe el siguiente código para empezar: 75 | 76 | ``` python 77 | from gpiozero import LED 78 | from time import sleep 79 | 80 | led = LED(17) 81 | 82 | while True: 83 | led.on() 84 | sleep(1) 85 | led.off() 86 | sleep(1) 87 | 88 | ``` 89 | 14. Guarda con **Ctrl + s** y ejecuta el código con **F5**. 90 | 15. El LED debería estar encendiéndose y apagándose continuamente. Para salir del programa pulsa **Ctrl + c** en el teclado. 91 | 92 | ## Usando los botones para tener una entrada 93 | Ahora eres capaz de controlar un componente de salida, un LED. Vamos a conectar y controlar un componente de entrada: un botón. 94 | 95 | 1. Conecta un botón a un pin GND y a al pin 2 GPIO, como se muestra en el diagrama: 96 | 97 | ![](images/button.png) 98 | 99 | 1. Crea un nuevo archivo en **Archivo** > **Archivo nuevo**. 100 | 1. Guarda el archivo en **Archivo** > **Guardar**. 101 | 1. Guarda el archivo como `gpio_button.py`. 102 | 103 | 1. Esta vez necesitarás la clase Button (botón en inglés), y declarar que el botón estará en el pin 2. Escribe el siguiente código en tu archivo: 104 | 105 | ``` python 106 | from gpiozero import Button 107 | button = Button(2) 108 | ``` 109 | 110 | 1. Ahora puedes hacer que el programa haga algo cuando el botón esté pulsado. Prueba a añadir esta línea: 111 | 112 | ``` python 113 | button.wait_for_press() 114 | print('Me has apretado') 115 | ``` 116 | 117 | 1. Guarda con **Ctrl + S** y ejecuta el código con **F5**. 118 | 1. Pulsa el botón y verás cómo tu texto aparece en pantalla. 119 | 120 | ## Controlando un LED manualmente 121 | 122 | Ahora podemos combinar los dos programas que has escrito hasta ahora para controlar el LED usando el botón 123 | 124 | 1. Crea un nuevo archivo en **Archivo** > **Archivo nuevo**. 125 | 2. Guarda el archivo en **Archivo** > **Guardar**. 126 | 3. Guarda el archivo como `gpio_control.py`. 127 | 4. Ahora escribe el siguiente código: 128 | 129 | ``` python 130 | from gpiozero import LED, Button 131 | from time import sleep 132 | 133 | led = LED(17) 134 | button = Button(2) 135 | 136 | button.wait_for_press() 137 | led.on() 138 | sleep(3) 139 | led.off() 140 | ``` 141 | 142 | 1. Guarda y ejecuta el programa. Cuando pulses el botón, el LED deberé encenderse durante 3 segundos. 143 | 144 | ## Haciendo un interruptor 145 | Con un interruptor, pulsando el botón un avez deberá encender el LED, y con la siguiente pulsación el LED se volverá a apagar. 146 | 147 | 1. Modifica tu código para que quede como este. Estamos usando un flag llamado active para almacenar el estado del LED. La línea `active = not active` conmutará el LED entre los estados `True` y `False`: 148 | 149 | ``` python 150 | from gpiozero import LED, Button 151 | from time import sleep 152 | 153 | led = LED(17) 154 | button = Button(2) 155 | active = False 156 | 157 | while True: 158 | if active == False: 159 | led.off() 160 | else: 161 | led.on() 162 | button.wait_for_press() 163 | button.wait_for_release() 164 | active = not active 165 | ``` 166 | 167 | Estaría genial si pudieramos hacer que el LED se encendiera sólo cuando el botón está pulsado. Con la librería GPIO Zero, es bien sencillo. 168 | 169 | 1. Hay dos métodos de la clase Button llamados `when_pressed` y `when_released`. Estos métodos no bloquean el flujo del programa, así que si se colocan en un bucle, el programa se ejecutará indefinidamente. 170 | 171 | 1. Modifica tu código para que quede como este: 172 | 173 | ``` python 174 | from gpiozero import LED, Button 175 | from signal import pause 176 | 177 | led = LED(17) 178 | button = Button(2) 179 | 180 | button.when_pressed = led.on 181 | button.when_released = led.off 182 | 183 | pause() 184 | 185 | ``` 186 | 1. Guarda y ejecuta el programa. Ahora cuando el botón está pulsado, el LED se encenderá, y se volverá a apagar cuando el botón deje de estar pulsado. 187 | 188 | ## Y ahora qué? 189 | 190 | Hay muchas otras cosas que probar con GPIO Zero. Puedes echarle un vistazo a la documentación [aquí](https://gpiozero.readthedocs.org/). 191 | Intenta controlar otros componentes como un zumbador, un LED RGD, un motor o un robot. 192 | -------------------------------------------------------------------------------- /worksheet.md: -------------------------------------------------------------------------------- 1 | # Getting started with physical computing 2 | 3 | ## GPIO pins 4 | 5 | One powerful feature of the Raspberry Pi is the row of GPIO pins along the top edge of the board. GPIO stands for General-Purpose Input/Output. These pins are a physical interface between the Raspberry Pi and the outside world. At the simplest level, you can think of them as switches that you can turn on or off (input) or that the Pi can turn on or off (output). 6 | 7 | The GPIO pins allow the Raspberry Pi to control and monitor the outside world by being connected to electronic circuits. The Pi is able to control LEDs, turning them on or off, run motors, and many other things. It's also able to detect whether a switch has been pressed, the temperature, and light. We refer to this as physical computing. 8 | 9 | There are 40 pins on the Raspberry Pi (26 pins on early models), and they provide various different functions. 10 | 11 | If you have a RasPiO pin label, it can help to identify what each pin is used for. Make sure your pin label is placed with the keyring hole facing the USB ports, pointed outwards. 12 | 13 | ![](images/raspio-ports.jpg) 14 | 15 | If you don't have a pin label, then this guide can help you to identify the pin numbers: 16 | 17 | ![](images/pinout.png) 18 | 19 | You'll see pins labelled as 3V3, 5V, GND and GP2, GP3, etc: 20 | 21 | | | | | 22 | |---|---|---| 23 | | 3V3 | 3.3 volts | Anything connected to these pins will always get 3.3V of power | 24 | | 5V | 5 volts | Anything connected to these pins will always get 5V of power | 25 | | GND | ground | Zero volts, used to complete a circuit | 26 | | GP2 | GPIO pin 2 | These pins are for general-purpose use and can be configured as input or output pins | 27 | | ID_SC/ID_SD/DNC | Special purpose pins || 28 | 29 | **WARNING**: If you follow the instructions, then playing about with the GPIO pins is safe and fun. Randomly plugging wires and power sources into your Pi, however, may destroy it, especially if using the 5V pins. Bad things can also happen if you try to connect things to your Pi that use a lot of power; LEDs are fine, motors are not. If you're worried about this, then you might want to consider using an add-on board such as the [Explorer HAT](https://shop.pimoroni.com/products/explorer-hat) until you're confident enough to use the GPIO directly. 30 | 31 | ## Lighting an LED 32 | 33 | LEDs are delicate little things. If you put too much current through them they will pop (sometimes quite spectacularly). To limit the current going through the LED, you should always use a resistor in series with it. 34 | 35 | Try connecting the long leg of an LED to the Pi's 3V3 and the short leg to a GND pin. The resistor can be anything over about 50Ω. 36 | 37 | ![](images/led-3v3.png) 38 | 39 | The LED should light up. It will always be on, because it's connected to a 3V3 pin, which is itself always on. 40 | 41 | Now try moving it from 3V3 to GPIO pin 17: 42 | 43 | ![](images/led-gpio17.png) 44 | 45 | The LED should now turn off, but now it's on a GPIO pin, and can therefore be controlled by code. 46 | 47 | ## Switching an LED on and off 48 | 49 | GPIO Zero is a new Python library which provides a simple interface to everyday GPIO components. It comes installed by default in Raspbian. 50 | 51 | 1. Open IDLE from the main menu (`Menu`>`Programming`>`Python 3 (IDLE)`. 52 | 53 | 1. You can switch an LED on and off by typing commands directly into the Python interpreter window (also known as the Python **shell**). Let's do this by first importing the GPIO Zero library. You also need to tell the Pi which GPIO pin you are using - in this case pin 17. Next to the chevrons `>>>`, type: 54 | 55 | ```python 56 | from gpiozero import LED 57 | led = LED(17) 58 | ``` 59 | 60 | Press **Enter** on the keyboard. 61 | 62 | 1. To make the LED switch on, type the following and press **Enter**: 63 | 64 | ```python 65 | led.on() 66 | ``` 67 | 68 | 1. To make it switch off you can type: 69 | 70 | ```python 71 | led.off() 72 | ``` 73 | 74 | 1. Your LED should switch on and then off again. But that's not all you can do. 75 | 76 | ## Flashing an LED 77 | 78 | With the help of the `time` library and a little loop, you can make the LED flash. 79 | 80 | 1. Create a new file by clicking **File > New file**. 81 | 82 | 1. Save the new file by clicking **File > Save**. Save the file as `gpio_led.py`. 83 | 84 | 1. Enter the following code to get started: 85 | 86 | ```python 87 | from gpiozero import LED 88 | from time import sleep 89 | 90 | led = LED(17) 91 | 92 | while True: 93 | led.on() 94 | sleep(1) 95 | led.off() 96 | sleep(1) 97 | ``` 98 | 99 | 1. Save with **Ctrl + S** and run the code with **F5**. 100 | 101 | 1. The LED should be flashing on and off. To exit the program press **Ctrl + C** on your keyboard. 102 | 103 | ## Using buttons to get input 104 | 105 | Now you're able to control an output component (an LED), let's connect and control an input component: a button. 106 | 107 | 1. Connect a button to another GND pin and GPIO pin 2, like this: 108 | 109 | ![](images/button.png) 110 | 111 | 1. Create a new file by clicking **File > New file**. 112 | 113 | 1. Save the new file by clicking **File > Save**. Save the file as `gpio_button.py`. 114 | 115 | 1. This time you'll need the `Button` class, and to tell it that the button is on pin 2. Write the following code in your new file: 116 | 117 | ```python 118 | from gpiozero import Button 119 | button = Button(2) 120 | ``` 121 | 122 | 1. Now you can get your program to do something when the button is pushed. Add these lines: 123 | 124 | ```python 125 | button.wait_for_press() 126 | print('You pushed me') 127 | ``` 128 | 1. Save with **Ctrl + S** and run the code with **F5**. 129 | 1. Press the button and your text will appear. 130 | 131 | ## Manually controlling the LED 132 | 133 | You can now combine your two programs written so far to control the LED using the button. 134 | 135 | 1. Create a new file by clicking **File > New file**. 136 | 137 | 1. Save the new file by clicking **File > Save**. Save the file as `gpio_control.py`. 138 | 139 | 1. Now write the following code: 140 | 141 | ```python 142 | from gpiozero import LED, Button 143 | from time import sleep 144 | 145 | led = LED(17) 146 | button = Button(2) 147 | 148 | button.wait_for_press() 149 | led.on() 150 | sleep(3) 151 | led.off() 152 | ``` 153 | 154 | 1. Save and run your program. When you push the button the LED should come on for three seconds. 155 | 156 | ## Making a switch 157 | 158 | With a switch, a single press and release on the button would turn the LED on, and another press and release would turn it off again. 159 | 160 | 1. Modify your code so that it looks like this: 161 | 162 | ```python 163 | from gpiozero import LED, Button 164 | from time import sleep 165 | 166 | led = LED(17) 167 | button = Button(2) 168 | 169 | while True: 170 | button.wait_for_press() 171 | led.toggle() 172 | sleep(0.5) 173 | ``` 174 | 175 | `led.toggle()` switches the state of the LED from on to off, or off to on. Since this happens in a loop the LED will turn on and off each time the button is pressed. 176 | 177 | 1. It would be great if you could make the LED switch on only when the button is being held down. With GPIO Zero, that's easy. There are two methods of the `Button` class called `when_pressed` and `when_released`. These don't block the flow of the program, so if they are placed in a loop, the program will continue to cycle indefinitely. 178 | 179 | 1. Modify your code to look like this: 180 | 181 | ```python 182 | from gpiozero import LED, Button 183 | from signal import pause 184 | 185 | led = LED(17) 186 | button = Button(2) 187 | 188 | button.when_pressed = led.on 189 | button.when_released = led.off 190 | 191 | pause() 192 | ``` 193 | 194 | 1. Save and run the program. Now when the button is pressed, the LED will light up. It will turn off again when the button is released. 195 | 196 | ## What next? 197 | 198 | There are lots of other things you can control or monitor with your Raspberry Pi. Have a look at the worksheets below, to see how easily this can be done. 199 | 200 | - [Using an active buzzer](buzzer.md) 201 | - [Making traffic lights](trafficlights.md) 202 | - [Using a light-dependent resistor](ldr.md) 203 | - [Using a PIR Sensor](pir.md) 204 | - [Using an ultrasonic distance sensor](distance.md) 205 | - [Analogue inputs](analogue.md) 206 | - [Using motors](motors.md) 207 | --------------------------------------------------------------------------------