RPi Tutorial EGHS:Switch Input
- GPIO Protection Circuits
- Basic Circuits: LED output - DC motor - Switch Input - Analogue Sensor
- Intermediate Circuits: Shift Registers - Analogue to Digital - Driving Circuit - Alpha-Numeric Display
- Advanced Circuits: Control Hardware Over The Internet
This page is part of a work in progress.
While most of these circuits may interface directly to the RPi, the use of a buffered interface (such as the one supplied by the Gertboard) is recommended which will help protect against damage. Alternatively, experiment with one of the Alternative Test Platforms.
Extreme caution should be exercised when interfacing hardware at a low level, you may damage your RPi, your equipment and potentially yourself and others. Doing so is at your own risk!
Note: Until RPi devices are available, I can not confirm this will work on a real RPi. For now, I shall be using the TI LaunchPad (see Alternative Test Platforms for details) to test the hardware on (as it is cheap and the logic levels similar).
Work in progess...
The GPIO pin on the RPi when defined as an Input allows the state of the pin to be read as with HIGH or LOW. This allows us to use a simple switch to set the state of the pin and the software can read this and respond to the change (i.e. change the audio volume output or light an LED wired to another pin).
For additional theory see 
For the GPIO pin to determine if an input level is HIGH or LOW it has to detect that the voltage on the pin is above or below a set level, you should aim to set the pin to 10% of the logic voltage (HIGH for the RPi this is 3.3V - so 2.97V to 3.3V, LOW is 0V to 0.33V).
If the pin voltage is somewhere between 2.97V and 0.33V then the system may not reliably determine if a HIGH or LOW value is set (particularly as you get closer to 1.65V (halfway)).
If you drive voltages over 3.3V or negative voltages then you will risk damaging the internal GPIO circuits and perhaps even killing the RPi (which is why using extra components to protect and buffer inputs is recommended).
When a GPIO pin is disconnected and set as an input, the voltage is considered floating since there is no defined voltage level being applied to the pin. Therefore a good input circuit needs to apply either a HIGH voltage or a LOW voltage.
The top circuit with Switch 1 (Double-poll switch) is fine, however, when using other types of switches, such as Switch 2 (i.e. Single-poll switch) you will create a short-circuit when the switch is pressed!
However, by simply using a resistor in-between the short-circuit can be avoided. The value of the resistor is determined by the leakage current of the GPIO pin (the current used by the circuit to read the pin) (although this is not specified for the RPi, it is expected to be in the range of 1uA) and the amount of voltage drop it creates as a result.
If we set R1 to 10kohms, and max drop from Vcc is 10% (0.33V). Max leakage current = Vdrop/R1 = 0.33/10000 = 33uA
By picking a large resistor it ensures less current is drawn by the circuit, when the switch is active (this is why a large value of 10Kohms is usually used).
Current drawn = Vcc/R1 = 3.3/10000 = 0.33mA
The above circuit shows Switch 1 which when pressed will provide a LOW signal to the GPIO pin (otherwise the resistor pulls the circuit UP HIGH), and Switch 2 which when pressed will provide a HIGH signal to the GPIO pin (otherwise the resistor pulls the circuit DOWN LOW).
This is covered in a lot more detail here (although note the logic level here is 5V!) .
One additional thing to note is that the RPi GPIO has internal Pull-Up and Pull-Down resistors which can be enabled through software registers.
This means that you can avoid the extra circuit above and simply place a switching between Vcc or GND, but you have to set the Pull-Up/Pull-Down registers for it to function correctly. To keep the software simple and to avoid any damage, it is recommended you start with using external Pull-Ups and Pull-Downs until you are confident setting these registers correctly.
An extra consideration for safer input design, is to consider the case when the software incorrectly drives the GPIO pin as an output rather than using as an input.
Now, in the second circuit, when Switch 2 is activated, the GPIO pin is connected directly to Vcc (3.3V), if the software is trying to drive this pin LOW (similarly when the opposite is happening switch connects to GND and the software is driving the pin HIGH). This could damage the circuit by drawing/supplying more current through the GPIO pin than it can handle.
By putting another resistor on the GPIO pin, any short-circuit HIGH or LOW will have the current limited.
By picking 1Kohmn resistor for R2, the maximum current will be:
Imax = V/R = 3.3/1000 = 3.3mA (which should be within safe limits)
A little more detail is given here (again note, logic level and supply are 5V!) 
De-bouncing Hardware verses Software
The last consideration is whether hardware de-bouncing is required. Basically any manual switch will not cleanly make or break a connection when you switch it, and is likely to trigger any input value multiple times (as the contacts move momentarily from one state to another).
This can be dealt with by applying a simple filter in the circuit (achieved by putting a capacitor in parallel with the switch). The capacitor acts like a smoothing filter (energy from fast transitions of voltage is temporarily stored and released by the capacitor), this slows the change from LOW to HIGH and vice-a-versa.
A good explanation (with graphs) is shown here (see Hardware Interfacing section at the bottom) 
While hardware de-bouncing or smoothing of this input is often quite helpful, the problem occurs if you require very fast switching or response times, since the capacitor now delays any possible detection of the switch. However, if de-bouncing is handled within the software (simplest method is to re-read the state after a short delay) it can be fine tuned to meet your needs.
A little more detail is given here (in Brooklyn Debounce section) 
Basic Switchx8 Test Module
The Basic Switchx8 Test Module Test module has been built to allow easy testing of GPIO inputs by connecting up to 8 switches, in a number of configurations.
Resistor values: R1 = 11Kohms (Green) R2 = 1Kohms (Blue)
The slightly unusual layout is down to using up some spare veroboard, so it could probably be designed better (but it works well enough for my needs).
Also, to allow flexibility, removable connections are put in between R1 and the switches.
The module allows a number of circuit configurations if required:
- The protection resistors (R2) can be removed by connecting the GPIO directly to the middle pins.
- The pull up/down resistors (R1) can be removed (so internal pull up/downs can be used on their own).
- The circuit can be switched from active HIGH to active LOW by swapping the power connections (by connecting Vcc to the pins near the switch bank and Gnd to the right-side pins, the switch ON = HIGH output. Alternatively the other way around, with Gnd by the switch bank and Vcc on the right, the switch ON = LOW output).
- A second bank of pins could be added in the middle, to allow the protection resistors (R2) to be removed while still using the Pull Up/Down resistors (R1), if required.
Basic Switchx8 Test Module (Control pins at top, GND/PWR connection at bottom-right and middle-right, removable connections in the middle for connecting pull up/down resistors).
While the RPi is not available, I can only confirm the TI LaunchPad code works for me.
The specifics and background behind the code is detailed very well on the following sites:
Sample test code for single switch input (tested on TI MSP430G2553 device). Reads in switch input from Port 1.3, and lights LED output on Port 1.0 (can be used with or without external circuit connected - uses default pins for SW2 and LED1).
- main.c - Main calling functions (includes pin setup and switch between POLLING/INTERRUPT)
No input test code available yet.
- Introduction To Embedded Programming - GPIO Input
- Arduino inputs
- BCM2835 ARM Peripherals Datasheet
- Arduino Tutorial - Arduino inputs
- MSP430 LaunchPad PushButton
- Arduino Tutorial - Arduino inputs