element14 Community
element14 Community
    Register Log In
  • Site
  • Search
  • Log In Register
  • Community Hub
    Community Hub
    • What's New on element14
    • Feedback and Support
    • Benefits of Membership
    • Personal Blogs
    • Members Area
    • Achievement Levels
  • Learn
    Learn
    • Ask an Expert
    • eBooks
    • element14 presents
    • Learning Center
    • Tech Spotlight
    • STEM Academy
    • Webinars, Training and Events
    • Learning Groups
  • Technologies
    Technologies
    • 3D Printing
    • FPGA
    • Industrial Automation
    • Internet of Things
    • Power & Energy
    • Sensors
    • Technology Groups
  • Challenges & Projects
    Challenges & Projects
    • Design Challenges
    • element14 presents Projects
    • Project14
    • Arduino Projects
    • Raspberry Pi Projects
    • Project Groups
  • Products
    Products
    • Arduino
    • Avnet & Tria Boards Community
    • Dev Tools
    • Manufacturers
    • Multicomp Pro
    • Product Groups
    • Raspberry Pi
    • RoadTests & Reviews
  • About Us
    About the element14 Community
  • Store
    Store
    • Visit Your Store
    • Choose another store...
      • Europe
      •  Austria (German)
      •  Belgium (Dutch, French)
      •  Bulgaria (Bulgarian)
      •  Czech Republic (Czech)
      •  Denmark (Danish)
      •  Estonia (Estonian)
      •  Finland (Finnish)
      •  France (French)
      •  Germany (German)
      •  Hungary (Hungarian)
      •  Ireland
      •  Israel
      •  Italy (Italian)
      •  Latvia (Latvian)
      •  
      •  Lithuania (Lithuanian)
      •  Netherlands (Dutch)
      •  Norway (Norwegian)
      •  Poland (Polish)
      •  Portugal (Portuguese)
      •  Romania (Romanian)
      •  Russia (Russian)
      •  Slovakia (Slovak)
      •  Slovenia (Slovenian)
      •  Spain (Spanish)
      •  Sweden (Swedish)
      •  Switzerland(German, French)
      •  Turkey (Turkish)
      •  United Kingdom
      • Asia Pacific
      •  Australia
      •  China
      •  Hong Kong
      •  India
      •  Japan
      •  Korea (Korean)
      •  Malaysia
      •  New Zealand
      •  Philippines
      •  Singapore
      •  Taiwan
      •  Thailand (Thai)
      •  Vietnam
      • Americas
      •  Brazil (Portuguese)
      •  Canada
      •  Mexico (Spanish)
      •  United States
      Can't find the country/region you're looking for? Visit our export site or find a local distributor.
  • Translate
  • Profile
  • Settings
Raspberry Pi Projects
  • Products
  • Raspberry Pi
  • Raspberry Pi Projects
  • More
  • Cancel
Raspberry Pi Projects
Documents Raspberry Pi GPIO Explained
  • Blog
  • Documents
  • Events
  • Polls
  • Members
  • Mentions
  • Sub-Groups
  • Tags
  • More
  • Cancel
  • New
Join Raspberry Pi Projects to participate - click to join for free!
Actions
  • Share
  • More
  • Cancel
Engagement
  • Author Author: shabaz
  • Date Created: 6 Sep 2015 1:36 PM Date Created
  • Last Updated Last Updated: 10 May 2021 6:52 PM
  • Views 13560 views
  • Likes 20 likes
  • Comments 41 comments
Related
Recommended

Raspberry Pi GPIO Explained

Contents

image

Introduction

The Raspberry Pi is a computer, and from a connections point of view it doesn’t look much different to a normal desktop computer. It has USB ports for connecting a keyboard and mouse, and a video output port for connecting up a display.

 

Because it is more compact and lower cost than a large desktop PC, it becomes possible to use the Raspberry Pi or other small single board computers (SBCs) as they are known, for many scenarios where a desktop or laptop PC would not be feasible.

 

Often you may want to connect up other ‘things’ to a computer. For example you may wish to use a computer to measure the brightness level and automatically control lights, or to sound an alarm if an intruder is detected.

 

Broken down to more general terms, there is a desire to be able to use a computer to control (also known as to ‘output’) to electronic circuits, and to gain useful information (aka obtain ‘input’) from circuits.

 

This is where the Raspberry Pi and other single board computers excel because one key difference between SBCs and desktop or laptop PCs is that SBCs usually have general purpose input/output (GPIO) capability. This is lacking on larger PCs.

image

 

By making connections to those pins (they are also known as header pins) the Raspberry Pi can interface to the electronic world which consists (amongst other things) of sensors and indicators and actuators.

 

This blog post will provide example circuits that can be used as-is (or can be modified and extended) along with code examples in several programming languages. The information is split up into:

  • Connections Overview
  • Understanding Inputs (Use the tabs to work through this section)
  • Understanding Outputs (Use the tabs to work through this section)
  • Some Optional (advanced) topics (namely Speed and Jitter; again, use the tabs to work through this section)

 

To prevent too much scrolling, some of the sections are tabbed at the top, so click on the tabs to see more content. Also, click on the photos to zoom in to see wiring detail.

 

There is also a short video that contains some extra detail as well as demonstrations of the circuits and code. The video will be available in about a weeks time (bookmark this post if you wish to be notified).

 

Connections Overview

The diagram below lists the header pins available on the Raspberry Pi. Pin 1 on circuit boards can typically be identified by looking for the square-shaped pad on the underside of the board. The Raspberry Pi has digital inputs/outputs on its 40-pin connector that comply with 3.3V logic levels. The photo here shows an older Pi 2, but the same connection detail applies for the more recent Pi 3. Notice from the diagram that the pin numbering is in a zig-zag pattern, where pin 1 is lower right, pin 2 is lower left, and then the numbers increase the higher up you go in the zig-zag fashion. Another way of looking at it is to notice that the odd numbered pins are on the right side, and the even numbered pins are on the left side.

image

 

The term '3.3V logic levels' means that the Raspberry Pi will interpret anything very close to zero volts (it doesn't have to be precisely 0V) as a logic ‘0’ and anything higher than around 2V as a logic ‘1’. Inputs beyond 3.3V will damage the board. Similarly, when GPIO pins are configured to become outputs, the Raspberry Pi will set the pin to either a voltage close to 0V or a voltage close to 3.3V. Everything in electronics has a tolerance, so (say) measuring 3.21V (as an example) instead of precisely 3.30V is considered acceptable.

 

For this blog post's input/output exercises, the pink, white, red and orange pins on the diagram will be used. The remainder pins are for serial interfacing use which is addressed in other blog posts.

 

If you are not using the two 5V pins (bottom-left side, pin numbers 2 and 4) then you could prevent accidental shorts to surrounding pins by placing some plastic sleeving/insulation over them.

 

 

Understanding Raspberry Pi Outputs

Work through the three tabs below to get a full understanding of the output functions of your Raspberry Pi.

{tabbedtable} Tab LabelTab Content
1) Digital Outputs: LEDs

Getting Started with Digital Outputs: Lighting LEDs

 

A typical use for output pins is to control an indicator such as an LED or light bulb, or some actuator or motor. Usually an electronic circuit is needed to transform the Raspberry Pi output into something that will control the desired device. For a small LED all that is needed is a series resistor; its purpose is to reduce the current that will flow through the LED in order to protect both the LED and the Raspberry Pi. Not a lot of current can be supplied by the output pins, and LEDs will be damaged by too high current. Furthermore LEDs are non-linear and will not light at all if too low a voltage is applied across them. Small LEDs (particularly red, yellow and green ones) will work fine with the Raspberry Pi outputs provided a resistor is attached in series. The exact resistance doesn’t matter; anything between 100 ohms and 1kohm should allow for sufficient output brightness when the output is set to logic ‘1’.

 

As a quick exercise the photo here (click on it to zoom in) shows the Raspberry Pi connected up to an LED using jumper wiresjumper wires. To prevent accidental shorts and for convenience the Raspberry Pi was bolted onto a piece of wood (2mm or 2.5mm diameter bolts; 3mm will not fit) and a bread board glued next to it.

image

 

A bread board, a single resistor and an LED were connected up to the Raspberry Pi. The GND (also known as 0V) connection was taken from pin 6 on the Raspberry Pi header, and the GPIO pin used was GPIO22 (see the diagram earlier) which is pin 15. Any GPIO pin could be used; they are marked in pink on the earlier diagram. Another way of representing this is shown in the schematic below.

image

Once you’ve connected up the LED, a program or script can be written to control it. The choice of language is up to you. One (popular) example is Python; here is some code that will light up the LED.

 

# Connect LED to GPIO22 (pin 15)
import time
import RPi.GPIO as GPIO
GPIO.setmode(GPIO.BCM)
GPIO.setup(22, GPIO.OUT)
GPIO.output(22, True)
time.sleep(3)
GPIO.cleanup()

     

 

Save the code to a file called led-test.py and then to run it, type

sudo python led-test.py

 

Here is another example in Python. It flashes the LED 10 times (Note: if you're new to Python, unlike other programming languages the line indentations in the code are important):

 

# connect LED to GPIO22 (pin 15)
import time
import RPi.GPIO as GPIO
GPIO.setmode(GPIO.BCM)
for x in range(0,10):
  GPIO.setup(22, GPIO.OUT)
  GPIO.output(22, True)
  time.sleep(0.05)
  GPIO.output(22, False)
  time.sleep(0.45)

GPIO.cleanup()
     

 

Another way to control the output pins is to use a shell script. This appears slightly more complex (unless you enjoy writing shell scripts) but is a good thing just for reference because often other programming languages allow you to run shell scripts, and therefore if needed this can be a quick approach to using GPIO with other languages. Furthermore the method described here is standard across different platforms so your code can be ported to boards other than the Raspberry Pi too. If you're a beginner to programming, stick with Python for now and move on to the next example; shell scripts can be revisited at a much later stage.

 

#!/bin/sh
GPIO_PATH=/sys/class/gpio
LED_PIN=22 #GPIO 22 is pin 15
echo "$LED_PIN" > $GPIO_PATH/export
echo "out" > $GPIO_PATH/gpio$LED_PIN/direction
echo "1" > $GPIO_PATH/gpio$LED_PIN/value
sleep 1
echo "$LED_PIN" > $GPIO_PATH/unexport
     

 

The first line of the shell script looks like a comment line, but is needed to make it easy for the Linux shell to know what to do with the script upon execution, so don’t modify that. The remainder script lines are used to take control of a GPIO pin, set it to become an output, set it to a logic high value, and then wait for 1 second. Finally control of the GPIO pin is released so other programs can make use of it if desired.

 

Another programming language that may be encountered is C or its (far) bigger brother C++. An example using C or C++ is given further below in the ‘Voltmeter’ section where the code is used for input from a circuit, and output to an LED.

2) Output Example: Tone Generator

Another Output Example: Tone Generator

 

A more interesting example than an LED is to use a couple of GPIO pins to control a tone generator circuit. The Raspberry Pi has a headphone connector for audio but sometimes just a simple tone or alarm is needed to signal events (such as for an alarm clock project).

 

The photo below shows a very simple single integrated circuit (IC) project that can generate various sounds. By adjusting resistor and capacitor values, different tones and sounds could be created.

image

 

The circuit connects to two outputs from the Raspberry Pi. One output is used to switch the tone on or off, and the other is used to alternate between two tones. One of the capacitors in the circuit is used to create a sweeping tone transition when tones are alternated. The circuit diagram is shown below; it uses an ICM7555 timer integrated circuitICM7555 timer integrated circuit. GPIO22 was used to switch the tone on and off, and GPIO27 modifies the tone. C1, R1 and R2 can be adjusted to select the desired tones.

image

The Python code below plays some alarm tone effects. To use the code, save the code to a file called tone-test.py and then type

sudo python tone-test.py

 

import time
import RPi.GPIO as GPIO
GPIO.setmode(GPIO.BCM)
GPIO.setup(22, GPIO.OUT)  # TONE_ENABLE
GPIO.setup(27, GPIO.OUT)  # TONE_CHANGE


GPIO.output(22, True)
for x in range(0,5):
  GPIO.output(27, True)
  time.sleep(0.1)
  GPIO.output(27, False)
  time.sleep(0.2)
GPIO.output(22, False)
time.sleep(0.5)


for x in range(0,5):
  GPIO.output(22, True)
  time.sleep(0.1)
  GPIO.output(22, False)
  time.sleep(0.2)
GPIO.output(27, True)
time.sleep(0.2)


for x in range(0,5):
  GPIO.output(22, True)
  time.sleep(0.05)
  GPIO.output(22, False)
  time.sleep(0.05)


for x in range(0,10):
  GPIO.output(22, True)
  time.sleep(0.1)
  GPIO.output(22, False)
  time.sleep(0.1)
time.sleep(1)


GPIO.cleanup()
     

 

Note that the circuit uses the 3.3V supply (pin 1) available from the Raspberry Pi. Only use this supply if you know your circuit doesn’t consume much power. More than a few tens of milliamps of current consumption would require your own external power supply. Another approach would be to build a 5V to 3.3V regulator circuit and connect it to the 5V supply available on pin 2 from the Raspberry Pi.

3) Output Design Tips

Output Design Tips

 

All the circuits described so far have involved low current and low voltage but sometimes higher power devices need to be controlled or monitored. There are some typical methods to achieve this, and they are described here.

 

Connecting to 5V Logic

When the Raspberry Pi is used to output a signal to 5V devices, usually (not always) no additional circuit is needed; many 5V logic device inputs will function just fine with the 3.3V logic output signals from the Raspberry Pi. You can confirm by checking the datasheet for the 5V device.

 

Low Power, Low Voltage LEDs (red, yellow, green)

A single LED can be controlled using a series resistor between around 100 ohms and 1kohm. No other considerations are required.

 

Any Color Low Power LED

Blue and white LEDs may require a voltage higher than 3.3V. The easiest way to control a single LED is to use a transistor circuit to switch the 5V supply rail. The value of R1 should be increased if using an LED of any color other than blue or white. In general consult the LED data sheet. Any NPN transistor should work for this circuit.

 

image

 

Higher Power AC or DC Devices (but not mains!)

A relay is useful for this scenario. Virtually any NPN transistor can be used. Popular devices include BC547BBC547B, 2N39042N3904 and BC549BC549. If the connected device can function from 5V DC then the Raspberry Pi's 5V connection on pin 2 of the 40-pin header could be connected to the relay switch as long as the required current is not too high (use 100mA as a very conservative guideline) otherwise the relay switch can be connected to an external supply (take care it doesn't accidentally short to the 5V supply or any other connection on the Raspberry Pi - keep it totally isolated). Check the relay datasheet to confirm that it is suitable for your needs.

 

A small relay with pins convenient for breadboard layout is Finder 32.21.7.005.200032.21.7.005.2000 and it can switch up to 6A. Note that just because a relay is rated for (say) 250V does not mean it can be used for this. Breadboards and stripboards are designed for far lower voltages. Even with a custom PCB the project should not be used at mains voltages because there are legal requirements for conductor spacing, temperature, types of enclosure material, connection type, conductor clamping method and so on. It is easy to create a product that will fail and cause personal injury or an electrical fire or harm others at some point in time.

image

 

Mains Powered Devices

Treat any circuit or product that directly controls mains devices from a Raspberry Pi with extreme suspicion. Most do not meet safety standards (even though some firms self-certify that they do meet safety standards when clearly their products do not). Instead, a reasonably safe method is to find a reputable remote control product from a reputable manufacturer and a reputable supplier that uses infra-red or wireless (radio) technology to control the mains device. In the UK, the Energenie RF controlled mains socketsEnergenie RF controlled mains sockets appear suitable and they provide a small radio transmitter board that directly plugs onto the Raspberry Pi 40-pin connector and they also supply example Python code for it. For an examination of the hardware and software click to see Energenie Experiments - Remote Power Control for the Home.

 

Some products for non-UK regions are mentioned at that link too.

 

Multiple Relays, LEDs or Devices that require less than 200mA Current at 12V

The ancient (>25 years in production!) yet useful ULN2803AULN2803A integrated circuit can be employed for this scenario. Several hundred milliamps can be supplied by each output pin (there are 8 of them).

image

Driving small DC Motors (the most common motors, also known as ‘Brushed DC’ Motors) and Stepper Motors

For small motors consider the Gertbot motor control boardGertbot motor control board. It can drive several brushed DC motors if needed, and can also be used for stepper motors.

 

Driving Brushed DC Motors (Medium to High Power) in either Direction

Use the  Infineon Motor Control board  Infineon Motor Control board. It can control one motor in both directions, or two motors in one direction. If more motors are needed, add more of the boards.

 

Understanding Raspberry Pi Inputs

Work through the three tabs below to get a full understanding of the input functions of your Raspberry Pi.

{tabbedtable} Tab LabelTab Content
1) Push Button Switch Input

Push Button Switch Input

 

The connections on the Raspberry Pi can be converted into inputs under software control. The example here is about the simplest; a push button switch is wired up to the 40-pin connector:

image

 

The circuit diagram is shown below. Note that the LED circuit from the exercises before is still left wired up but is not shown in the diagram below.

image

 

As can be seen from the circuit diagram, when the switch is not pressed the input pin is connected to +3.3V through a resistor. The input pin has a high resistance inside the Raspberry Pi, and so the voltage at the input pin is close to the 3.3V that the resistor is connected to. This means that the Raspberry Pi will detect a logic ‘1’ condition when the switch is not pressed.

 

When the switch is pressed, there is a direct path between the input pin and 0V and so the voltage at the input pin becomes 0V which is a logic ‘0’ condition.

 

For this simple switch circuit, the value of resistor R1 is not critical and can be any resistance from around 1k to 47k, but avoid low values since that increases current consumption when the switch is pressed.

 

Here is some example Python code that can detect the push button switch status. To use the code, save the code in a file called button-test.py and then to run it type:

sudo python button-test.py

 

# Connections:
# GPIO5 (pin 29) is button input
# GPIO22 (pin 15) is LED


import time
import curses
import sys
import RPi.GPIO as GPIO
GPIO.setmode(GPIO.BCM)
GPIO.setup(5, GPIO.IN)
GPIO.setup(22, GPIO.OUT)
tc=curses.initscr()
tc.nodelay(1)
old_button_status=GPIO.input(5)
count=0


tc.addstr(1, 0, "Press SPACE to quit:\n")
tc.addstr(2, 0, str(count))


while 1:
  button_status=GPIO.input(5)
  kbval=tc.getch()
  GPIO.output(22, button_status)
  if old_button_status != button_status:
    if button_status == True:
      tc.addstr(2, 10, "-") # pin is high, button unpressed
      count=count+1
    else:
      tc.addstr(2, 10, "_") # pin is low, button pressed
    old_button_status=button_status
    tc.addstr(2, 0, str(count))
  if kbval==0x20:
    break


time.sleep(1)
GPIO.cleanup()
curses.endwin()
print "Goodbye"

     

 

The code displays the button status on the screen, along with a count of how many times the button was pressed. You’ll notice that occasionally the count increases more than the number of times the button was thought to be pressed and this happens because of ‘contact bounce’; as the switch is pressed, the contacts connect together and release many times rapidly before finally making contact. A similar thing happens when the switch is released. The solution is to have ‘debouncing’ functionality. It can be implemented in hardware or in software (the software method is very common). The code below implements debouncing and will more accurately register the correct number of button presses. The only difference with the earlier code is that this time the input status is checked a second time delayed by about 20msec – this provides time for contact bounce to have completed.

 

# Connections:
# GPIO5 (pin 29) is button input
# GPIO22 (pin 15) is LED


import time
import curses
import sys
import RPi.GPIO as GPIO
GPIO.setmode(GPIO.BCM)
GPIO.setup(5, GPIO.IN)
GPIO.setup(22, GPIO.OUT)
tc=curses.initscr()
tc.nodelay(1)
old_button_status=GPIO.input(5)
count=0


tc.addstr(1, 0, "Press SPACE to quit:\n")
tc.addstr(2, 0, str(count))


while 1:
  button_status=GPIO.input(5)
  kbval=tc.getch()
  GPIO.output(22, button_status)
  if old_button_status != button_status:
    time.sleep(0.02) # debounce period
    button_status=GPIO.input(5) # re-read the input
    if old_button_status != button_status:


      if button_status == True:
        tc.addstr(2, 10, "-") # pin is high, button unpressed
        count=count+1
      else:
        tc.addstr(2, 10, "_") # pin is low, button pressed
      old_button_status=button_status
      tc.addstr(2, 0, str(count))


  if kbval==0x20:
    break


time.sleep(1)
GPIO.cleanup()
curses.endwin()
print "Goodbye"

     

2) Input Example: Voltmeter

Another Input Example: A Voltmeter

 

The Raspberry Pi has digital inputs and outputs but the real world has analog quantities that may need to be measured or controlled. The example here converts analog values into a digital signal that can be read using a Raspberry Pi input connection.

 

The example is an extremely simple voltmeter; it can measure voltages between 0 and 1V with good precision. Note that this won’t replace a handheld multimeter! It doesn’t have the requisite safety protection and could damage itself or persons or property if used for anything beyond the scope of the examples described here.

image

 

This is the circuit diagram:

image

 

The circuit uses an AD654 integrated circuitAD654 integrated circuit which generates a square wave with frequency dependant on an input voltage. The square wave output is connected to a Raspberry Pi input (GPIO5 in this example). The square wave has a frequency of up to 10kHz and so some accurate timing is needed to determine the voltmeter input. The code here uses the C programming language and a library called wiringpi written by Gordon Henderson. First off, install the wiringpi library:

 

mkdir development
cd development
git clone git://git.drogon.net/wiringPi
cd wiringPi
./build
     

 

Next, save the following code into a file called voltmeter.c

// AD654 Voltmeter
// Ver 1.0 Shabaz August 2015
// GPIO5 (pin 29) connects to AD654
// GPIO22 (pin 15) connects to LED


#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <wiringPi.h>

#define INREF 5
#define LEDREF 22
#define INVAL (digitalRead(INREF))
#define INVAL_IS_HIGH (digitalRead(INREF)==1)
#define INVAL_IS_LOW (digitalRead(INREF)==0)
#define LED_ON digitalWrite(LEDREF, 1)
#define LED_OFF digitalWrite(LEDREF, 0)


struct timespec ts_zero;


void
get_tzero(void)
{
  clock_gettime(CLOCK_MONOTONIC, &ts_zero);
}


long
get_time(void)
{
  long nsec, sec;
  struct timespec tts;
  clock_gettime(CLOCK_MONOTONIC, &tts);
  sec=tts.tv_sec-ts_zero.tv_sec;
  nsec=tts.tv_nsec-ts_zero.tv_nsec;
  if (sec>0)
  {
    nsec=nsec+1E9; // we don't expect times greater than 1 sec
  }
  ts_zero=tts;
  return(nsec);
}


int
main(int argc, char *argv[])
{
  int i;
  long avg;
  double mv, v;
  long nsec[65];
  wiringPiSetupGpio();
  pinMode(INREF, INPUT);
  pinMode(LEDREF, OUTPUT);


  while(1)
  {
    LED_ON;
    while(INVAL_IS_LOW);
    get_tzero();
    for (i=0; i<64; i++)
    {
      while(INVAL_IS_HIGH);
      nsec[i]=get_time();
      while(INVAL_IS_LOW);
    }
    avg=0;
    for(i=1; i<65; i++)
    {
      avg=avg+nsec[i];
    }
    avg=avg/64;
    v=1.0E5/((double)avg);
    mv=v*1000;
    printf("Voltage is %fV\n", v);
    LED_OFF;
    sleep(1);
  }


  return(0);
}
     

 

The code can be compiled by typing:

gcc -o voltmeter -lrt -lwiringPi voltmeter.c

 

To run the code, type:

sudo ./voltmeter

 

The code uses an averaging method to get high precision. It rapidly measures the width of the incoming square wave 64 times, and then sums the values and divides by 64 to get the average value. Then it sleeps for a second to allow other processes to do their thing, and then repeats.

 

The circuit also needs a few things for high precision. The 10nF timing capacitor10nF timing capacitor for the AD564 is selected to be a polypropylene part for better accuracy. The 1k timing resistor1k timing resistor can be a 1% part or alternatively a variable trimming resistor can be used. The circuit runs from the 5V supply from the Raspberry Pi 40-pin connector but this is only approximately 5V and so the circuit would benefit from a dedicated and more accurate 5V supply circuit.

 

As a quick check, the circuit shown above had the voltmeter input subjected to a potential divider circuit consisting of two resistors. The calculated voltage (if the resistors were precisely the correct values and the supply was exactly 5V) out of the potential divider is 0.04950V. When the software was run, it reported measurements of 0.04991V in the short test. Not bad for such a simple project!

 

Diodes D1 and D2 in the circuit above are optional but highly recommended because they will provide some protection to the integrated circuit if the input is accidentally subjected to a voltage outside the 0-1V range.

3) Input Design Tips

Input Design Tips

Protected Inputs

The Raspberry Pi can be protected from accidental connections to higher than expected voltages by adding an additional circuit to the inputs in use. A very good option in some situations is to use an optocoupler alternatively a low-cost method such as the circuit below will tolerate voltages as high as 60V without damaging the Raspberry Pi, and will cope with reversed connections too. The BC547BBC547B transistor in the circuit can be replaced with another type such as 2N39042N3904 or BC549BC549 if more convenient to obtain. R1 can be a (normal) 0.25W resistor for inputs up to around 50V, and will need to be a 0.5W part otherwise.

 

The output of this circuit is inverted, and an input voltage higher than about 2V will pull the output low.

image

 

Connecting to 5V Logic

A direct connection of a 5V logic output to a Raspberry Pi input could cause damage. Different approaches can be taken depending on the specific need.

 

If the 5V logic output changes slowly then you could consider using a potential divider circuit (i.e. two resistors) but it is not a great method (it doesn’t work for fast circuits). A far better method is to use a 5V tolerant buffer integrated circuit. A mid-way approach adequate for up to 100kHz switching speed is shown below, using a ZVN2110AZVN2110A N-channel MOSFET. The output is inverted.

image

 

Alternative MOSFETs that are suitable include ZVNL120AZVNL120A and VN10LPVN10LP.

 

MOSFETs are easy to damage when unsoldered in a circuit due to a very delicate gate structure (it is made of a thin layer internally that can be destroyed with high voltage). Take electrostatic precautions and another good practice is to first connect R3 into your circuit (either on a circuit board or breadboard) and then remove the MOSFET from its safe packaging and connect it into the circuit. The resistor R3 will provide some protection.

Additional Raspberry Pi Input & Output Info

Check out the three tabs below for a more advanced exercise using the input and output functions, and to see where you can go next with your Raspberry Pi.

 

{tabbedtable} Tab LabelTab Content
Advanced: Speed and Jitter

Advanced Topic: Speed and Jitter

 

Beginners: Skip to the next section! Advanced users, read on.

 

Button-presses and LED outputs are slow events measured in tens or hundreds of milliseconds. Sometimes much higher speed signals are encountered. For example, a TV remote emits infra-red light pulses around 40k times per second. Although the core CPU in the Raspberry Pi runs at speeds approaching 1GHz, input and output signals at that rate are not supported for several reasons that are hardware, electrical and software related. We will consider some of the software factors for the scope of this blog post.

 

The Raspberry Pi runs Linux which is a multi-tasking OS. It can (at any time) pre-emptively take control away from your software program in order to service other tasks. It all happens relatively quickly, so it looks like the mouse still works while your program is running, but really the Linux OS is providing short time-slices to your program and to the mouse driver code.

 

Ordinarily this doesn’t matter, but when you need short or high precision events this can become an issue revealed (for example) as jitter.

 

Furthermore choice of programming language has an effect too, because some libraries are more suitable than others. Interpreted code may run at a different speed compared to compiled code. In short if very precise timing is needed then either a Linux driver needs to be written or external hardware (such as another microcontroller, or logic circuits and clock) may be needed.

 

One good question for more advanced use of the Raspberry Pi capabilities is approximately how fast can output signals be toggled using the Python and C libraries and the script method described earlier?

 

To find out, code was written to repeatedly toggle an output pin and an oscilloscope was connected up. The results are shown below.

image

However, it is always important to remember there is jitter that will be present due to the use of the Linux OS. This is not an issue for general LED toggling of course. The oscilloscope capture below shows part of the nature of the jitter by overlaying multiple traces triggered at the same time. Notice that the jitter can take on many values, although they are all discretely spaced 4nsec apart (250MHz) which is due to internal hardware inside the Raspberry Pi.

image

Summary

Summary

 

If you've read this far then by now it should be clear that the 40-pin connector on the Raspberry Pi can be used for many diverse projects from driving LEDs and relays to creating voltmeters or generating alarms. With little circuitry the 3.3V logic compatible Raspberry Pi connections can interface to circuits. Using Python it is very easy to control outputs, and reading inputs is not too difficult either. For C programmers the wiringpi library makes control easy.

Next Steps

Next Steps

If you have a few basic components (an LED, some resistors and a breadboard and jumper wires) you can begin exploring.

 

Rather than just buy a single resistor or capacitor as you need it, consider purchasing a small pack of resistors, capacitors and a few transistors (bipolar and MOSFET), diodes, and a multimeter.

 

As you dive into deeper projects you'll also be interested in learning about the serial interface connections available on the 40-pin connector. The serial interfaces are used to send and receive multiple bits of data in a standard method between the Raspberry Pi and other integrated circuits. However there are also many integrated circuits that are very easy to connect to the GPIO connections and several were covered in this blog post. Consider obtaining a few ICM7555 devices - there are a lot of fun and interesting experiments possible with them.

  • gpio
  • rpibeginner
  • raspberry_pi
  • raspberry_pi_2
  • raspberry_pi_projects
  • guide
  • rpi_2
  • Share
  • History
  • More
  • Cancel
  • Sign in to reply

Top Comments

  • johnbeetem
    johnbeetem over 10 years ago +6
    From a quick skim, this looks great. I'd add two things. 1. "Be very careful about the +5V power pins on the GPIO connector. If you accidentally short one of them to +3.3V or to an I/O, you can permanently…
  • Workshopshed
    Workshopshed over 8 years ago in reply to Jan Cumps +3
    There are plenty of I/O expander chips and boards if you need more pins.
  • shabaz
    shabaz over 10 years ago +2
    Hi John, Very cool tip regarding the insulation, what an excellent idea! I've added it to the text. Thank you for the review. Hi DAB, Thanks for the comments! The balance between KISS for complete newcomers…
Parents
  • screamingtiger
    screamingtiger over 10 years ago

    The speed increase of C is astronomical.    Did you compile it with the -O option?  It shows the rest of the languages are just toys and any real work needs to be done in C or C++.  Just my opinion.

    • Cancel
    • Vote Up 0 Vote Down
    • Sign in to reply
    • More
    • Cancel
  • shabaz
    shabaz over 10 years ago in reply to screamingtiger

    Hi Joey!

     

    I didn't do any optimisations, just the defaults, and the wiringpi library linked in as usual, so room for more improvement too if needed.

    However, because Linux can context-switch whenever it likes, the speed cannot be guaranteed, hence the huge jitter, but this is an expected thing

    and to reduce that would need an off-board microcontroller or a driver for the specific application (which is beyond the scope of this post), in

    which case the speed of C may not be as important.

    I like C/C++ but everything can't be done (easily or in a reasonable time) with it, for example in practice we have to resort to (say) Javascript to get things

    like web pages to interact although of course being much lower-level C could in theory be used too, but in practice quite hard unless there is no limit

    to time spent developing!

    • Cancel
    • Vote Up 0 Vote Down
    • Sign in to reply
    • More
    • Cancel
  • screamingtiger
    screamingtiger over 10 years ago in reply to shabaz

    I agree for high level items such as a web interface, you don't want to use C, though you could like back in the CGI days.

    There are people using the Pi to control servos with good results.  I am shocked.  I believe a real time component is needed for servos or other types of PWM/PCM/PPM.

     

    They do have a real time version of Raspbian now which is interesting.

     

    The speed increase of the C language is not just on the GPIO, but all around.  IMO, all the extra power in the Pi 2 over the Pi 1 is wasted by using scripting languages.  I know that for some things this is ok, but I am seeing people network Pis together and then use python for the tasks which is a sad waste.

     

    The results you show here may say that you can network 4 or 5 Pis together and use Python, or get the same performance out of 1 Pi using C.

     

    If people want to make things easier I understand, but I don't consider C to be that hard. Besides, you have to use it for Arduino then why not Pi?  image

    • Cancel
    • Vote Up +2 Vote Down
    • Sign in to reply
    • More
    • Cancel
Comment
  • screamingtiger
    screamingtiger over 10 years ago in reply to shabaz

    I agree for high level items such as a web interface, you don't want to use C, though you could like back in the CGI days.

    There are people using the Pi to control servos with good results.  I am shocked.  I believe a real time component is needed for servos or other types of PWM/PCM/PPM.

     

    They do have a real time version of Raspbian now which is interesting.

     

    The speed increase of the C language is not just on the GPIO, but all around.  IMO, all the extra power in the Pi 2 over the Pi 1 is wasted by using scripting languages.  I know that for some things this is ok, but I am seeing people network Pis together and then use python for the tasks which is a sad waste.

     

    The results you show here may say that you can network 4 or 5 Pis together and use Python, or get the same performance out of 1 Pi using C.

     

    If people want to make things easier I understand, but I don't consider C to be that hard. Besides, you have to use it for Arduino then why not Pi?  image

    • Cancel
    • Vote Up +2 Vote Down
    • Sign in to reply
    • More
    • Cancel
Children
  • shabaz
    shabaz over 10 years ago in reply to screamingtiger

    A good point you bring up is PWM. Multi-channel PWM (needed for driving servos, LED dimming, etc) is super-easy on the Arduino as you know, because there is dedicated hardware inside the chip to handle this, whereas there is little dedicated hardware for this in the RPI, so software techniques or DMA techniques are used by people to try to achieve this for multiple channels on the Raspberry Pi. But, if hardware can be thrown at the Raspberry Pi, then it is possible to have excellent off-board PWM capability while retaining Linux capabilities.

    There are some nice ICs from Texas Instruments that can do this, and they interface using the serial bus capability on the 40-pin connector, or any microcontroller (such as Arduino) can be interfaced to the Raspberry Pi using the connector too. Basically as long as the 3.3V logic is observed, a lot can be done! (I know you know this - just for any newcomers to the subject).

    • Cancel
    • Vote Up 0 Vote Down
    • Sign in to reply
    • More
    • Cancel
  • Workshopshed
    Workshopshed over 10 years ago in reply to shabaz

    I'm wondering if there's a gap in the market for a digital servo that has a simple serial input rather than a PWM input, you could even feedback the position which would be great for robotics.

    • Cancel
    • Vote Up +1 Vote Down
    • Sign in to reply
    • More
    • Cancel
  • screamingtiger
    screamingtiger over 10 years ago in reply to shabaz

    One correction, the Arduino does have hardware based PWM, BUT, it cannot be used to drive servos.  Its an 8 bit value which is not enough resolution to drive a servo through its motion.

     

    Arduino uses software based (ISR) PWM to drive servos, as do most MCUs I have seen.  The ChipKit Pi I used on my project also uses software based PWM.  The CKP is an excellent real time device for the Pi once you get past the learning curve.  Im not found of it using the GPIO connectors, its really not necessary.  An external power and I2c is all that is needed, otherwise it just clogs up the GPIO and makes them inaccessible.

     

     

    Sorry off topic but you brought up the speed comparison!

    • Cancel
    • Vote Up +1 Vote Down
    • Sign in to reply
    • More
    • Cancel
  • screamingtiger
    screamingtiger over 10 years ago in reply to Workshopshed

    or an I2C servo.  I mean that would be overkill, just a servo board would be suffice that can control multiple PWM servos and you talk to the board via serial or I2C.

     

    The problem with serial is how will you control 10 servos?  I guess there could be a protocol of some sort.

     

     

    There are robotic servos that provide feedback.

    • Cancel
    • Vote Up +1 Vote Down
    • Sign in to reply
    • More
    • Cancel
  • shabaz
    shabaz over 10 years ago in reply to screamingtiger

    Ah, I see your point. I've only used a few ATmega variants so couldn't recall : ( The ISR method works as you say.

    ISR is still closely hardware-based in comparison to a user application on Linux, because the ISR can still be deterministic,

    since it is closely based on a hardware clock, and so you can virtually eliminate jitter - with Linux, the decision would rest with the Linux scheduler

    choosing when to allocate time to your process to run, so you are a lot more removed from the hardware clock through that layer of software

    [the scheduler] and higher-priority stuff will take over, or may even allow same-pri or lower-pri stuff to run to slightly more toward completion

    before it gives your process time, these tricks are sometimes used in operating systems to improve efficiency).

    • Cancel
    • Vote Up 0 Vote Down
    • Sign in to reply
    • More
    • Cancel
  • Workshopshed
    Workshopshed over 10 years ago in reply to screamingtiger

    You can make the Arduino do 16bit PWM but not with AnalogWrite.

    http://maxembedded.com/2011/08/avr-timers-pwm-mode-part-i/

    https://sites.google.com/site/qeewiki/books/avr-guide/pwm-on-the-atmega328

    http://www.embedds.com/programming-16-bit-timer-on-atmega328/

    http://extremeelectronics.co.in/avr-tutorials/servo-motor-control-by-using-avr-atmega32-microcontroller/

     

    Having a look at the Servo library it does use the 16bit timers so it should be accurate enough.

     

    http://makezine.com/2014/04/23/arduinos-servo-library-angles-microseconds-and-optional-command-parameters/

    • Cancel
    • Vote Up 0 Vote Down
    • Sign in to reply
    • More
    • Cancel
  • screamingtiger
    screamingtiger over 10 years ago in reply to Workshopshed

    But its not hardware based PWM though, that's what we were comparing.  A hardware based servo driver would be cool but haven't seen any. 

    • Cancel
    • Vote Up 0 Vote Down
    • Sign in to reply
    • More
    • Cancel
  • shabaz
    shabaz over 10 years ago in reply to screamingtiger

    I think anything directly hinged off the timer (even if it is not a dedicated PWM module) can be considered hardware-based (or close-enough), since we can definitely know how long in clock cycles it will take.

    I agree it's not the best, since (by definition) it interrupts your main applicaton, but you can guarantee the PWM quality with an ISR. Full PWM module is the best where you need it, I agree, since the rest of your app will continue to function at speed too.

    EDIT: perhaps 'hardware-based' is the wrong wording, not sure of the wording here, but it can be deterministic at the expense of the main code. I take your point it is not truly hardware PWM unless a hardware PWM capability exists in the physical chip (and I don't know the ATmega chips well enough to recall that).

    • Cancel
    • Vote Up 0 Vote Down
    • Sign in to reply
    • More
    • Cancel
  • screamingtiger
    screamingtiger over 10 years ago in reply to shabaz

    The ChipKit Pi is pretty good at running servos.  The PIC32 is very strong, and the task schedule (Pic's version of ISR) functions well with other tasks such as I2C.  So a chipkit pi, which would be software based PWM, is a good servo driver that can be controlled via I2C.

     

    However, it would be nice to have a very lower power option that is hardware based and controlled by I2C.

     

    As you can tell I am not a fan of Serial since it limits how many devices you can talk to, which is really just 1.  It is possible to multiplex serial using a protocol of some sort but I am unaware of any protocol for serial that would be like I2C.

     

    I2c Is a lot like serial, just has a built in protocol that on some devices is hardware based.

     

    Perhaps we can make one?  image

    • Cancel
    • Vote Up 0 Vote Down
    • Sign in to reply
    • More
    • Cancel
  • shabaz
    shabaz over 10 years ago in reply to screamingtiger

    TLC5940 would be an interesting device, it has is a chainable interface, and is true hardware PWM on lots of channels (not all need to be used of course). Or a small PIC as you say, probably similar cost!

    • Cancel
    • Vote Up 0 Vote Down
    • Sign in to reply
    • More
    • Cancel
element14 Community

element14 is the first online community specifically for engineers. Connect with your peers and get expert answers to your questions.

  • Members
  • Learn
  • Technologies
  • Challenges & Projects
  • Products
  • Store
  • About Us
  • Feedback & Support
  • FAQs
  • Terms of Use
  • Privacy Policy
  • Legal and Copyright Notices
  • Sitemap
  • Cookies

An Avnet Company © 2026 Premier Farnell Limited. All Rights Reserved.

Premier Farnell Ltd, registered in England and Wales (no 00876412), registered office: Farnell House, Forge Lane, Leeds LS12 2NE.

ICP 备案号 10220084.

Follow element14

  • X
  • Facebook
  • linkedin
  • YouTube