A GPIO Guide for Beginners

A GPIO Guide for Beginners Title Image

In this blog post you will learn everything about the GPIO pins of the Raspberry Pi. This post is especially for newbies in electronics.

First of all, a warning:

The Raspberry Pi can be irreparably damaged if the pins are used incorrectly. So always make sure your circuit is correct and that you use enough resistors.

What are GPIO pins

The GPIO pins are the 40 small metal pins on the top of the Raspberry Pi. The abbreviation GPIO stands for general purpose input output. This means that the GPIO pins can be used as an interface for almost any electronic device.

Due to the large number of ways to (mis)use the pins, getting started can be a bit confusing. Therefore, this blog post provides some examples on how to control the pins using Bash, C, and Python. So a little experience in programming is an advantage.

Although the 40 pins look identical, they have different functions. 26 pins can be used for GPIO and some have additional functions. Another 4 pins are used as power source (POWER, two times 3V3 and two times 5V) and 8 as negative pole (also ground or GROUND). The two remaining pins are the I2C interface for ID EEPROM.

Pinout

The graphic below shows the most important information, among other things the pinout. The pinout is identical for most Raspberry Pi models, but there are differences. Always check the exact pinout of your model before connecting a device. For this you just have to open a terminal on your Raspberry Pi (Ctrl+Alt+t) and execute the following command.

pinout

You will see a graphic of all connections and the exact pinout of your Raspberry Pi.

Raspberry Pi Pinout

You may have noticed that the GPIO numbers appear randomly and do not match the pin numbering. To avoid confusion, I refer to the numbering from 1 to 40 as the BOARD number and the number from 1 to 26 as the BCM or GPIO number.

So BOARD pin 1 is the 3V3 POWER connector and GPIO pin 2 is the pin next to it with BOARD number 3.

How to connect a device to the pins

There are several alternatives to connect a device to the GPIO pins. Some devices have a GPIO header so that the device can be plugged directly into the GPIO pins. Generally, however, this is not the case, which is why jumper wires or GPIO extension cables are used.

Watch our Video about GPIO Pins!

In the following example, an LED is connected to the Raspberry Pi using jumper cables.

The circuit

The Female to Male Jumper Wires connects the GPIO pin to a header or a breadboard. The pin must then be programmed to operate the device. The device can be a button, an LED, a sensor, a motor or a display. It is only important that the device can be operated with 5 volts or less and that it is compatible with the interfaces I2C, SPI or UART

For the construction we need the following equipment.

  • Raspberry Pi with Raspberry Pi OS
  • Two Male to Female Jumper Wires
  • One Male to Male Jumper Wire
  • 10 kilo Ohm resistor
  • LED
  • Solderless breadboard

Connect GPIO pin 13 (BOARD number 33) to the + strip and the GROUND pin next to it (BOARD number 34) to the – strip of the breadboard. Then plug one end of the 10 kilo Ohm resistor (any resistor) into the + strip and the other end into one of the cross strips. For the LED, the orientation is crucial. The anode is the longer of the two arms and often bent, the cathode is the shorter arm. The anode must always point in the + direction, i.e. towards the power source, and the cathode in the direction, i.e. towards GROUND. So put the longer arm in the same cross strip as the resistor, so that the shorter arm is in the adjacent cross strip. Finally, use the male to male jumper cable to connect the cross strip of the cathode (shorter arm of the LED) to the – strip.

The following diagram shows the assembly, make sure that everything is correct and that the components are inserted into the board as far as they will go, otherwise there will be loose contacts.

Aufbau des Schaltkreises

The following three code examples in Bash, Python and C are based on this structure. If you use other pins, you must modify the code accordingly.

Bash

Controlling the GPIO pins via Bash is very easy. In Linux, the GPIO pins are controlled by the files in the /sys/class/gpio folder. To use a GPIO pin, it must first be exported. As an example I use GPIO pin 13. In the following the filnames are bold and italic.

Open a terminal and list the contents of the gpio folder.

cd /sys/class/gpio
ls

The folder contains the files export and unexport as well as subfolders for each exported GPIO pin.

We export the pin by writing the GPIO number into the /sys/class/gpio/export file. Execute this command in the terminal.

echo 13 > /sys/class/gpio/export
ls

Now a folder with the corresponding pin number gpio13 has been created. This folder contains other folders and files. For the time being, only the direction and value files are important for us.

The direction file saves the mode of the pin:

in -> Pin is in read or input mode

out -> Pin is in write or output mode

The value file stores the voltage state of the pin:

0 -> pin is in LOW mode -> no voltage is applied to the pin

1 -> Pin is in HIGH mode -> Voltage is applied to the pin

The following commands set the mode to out and the value to 1.

echo out > /sys/class/gpio/gpio13/direction
echo 1 > /sys/class/gpio/gpio13/value

The LED is now lit. It is important to reset the pin values after use. The following commands should be executed after each use.

echo 0 > /sys/class/gpio/gpio13/value
echo in > /sys/class/gpio/gpio13/direction
echo 13 > /sys/class/gpio/unexport

Python program

Now we abstract and automate these Bash commands in Python.

The following Python script provides a simple GPIO_Pin class. This makes it extremely easy to use. The os module allows us to execute the same bash commands as above from Python. also, by using the __del__ method, we no longer need to manually reset and unexport the pins.

import os
from time import sleep

class GPIO_Pin:
    def __init__(self, num, mode):
        if 0 <= num or num <= 40:
            self.num = num
        else:
            print('Invalid Pin Number -> Enter a number from 0 - 40')
        if mode == 'out' or mode == 'write':
            self.mode = 'out'
        elif mode == 'in' or mode == 'read':
            self.mode = 'in'
        else:
            print('Invalid Pin Mode -> Enter "out" or "write" for output, "in" or "read" for input')
        if self.num and self.mode:
            os.system(f'echo {str(self.num)} > /sys/class/gpio/export')
            sleep(0.05)
            os.system(f'echo {self.mode} > /sys/class/gpio/gpio{str(self.num)}/direction')

    def reset(self):
        os.system(f'echo 0 > /sys/class/gpio/gpio{str(self.num)}/value')
        os.system(f'echo in > /sys/class/gpio/gpio{str(self.num)}/direction')

    def write(self, value):
        if value == 0 or value == 'LOW':
            os.system(f'echo 0 > /sys/class/gpio/gpio{str(self.num)}/value')
        elif value == 1 or value == 'HIGH':
            os.system(f'echo 1 > /sys/class/gpio/gpio{str(self.num)}/value')
        else:
            print('Invalid value -> Enter 1 or "HIGH" for HIGH, 0 or "LOW" for LOW')

    def __del__(self):
        self.reset()
        os.system(f'echo {str(self.num)} > /sys/class/gpio/unexport')

    def set_mode(self, mode):
        self.mode = mode
        os.system(f'echo {str(self.mode)} > /sys/class/gpio/gpio{str(self.num)}/direction')

def main():
    pin = GPIO_Pin(13, 'out')
    number_of_blinks = 10
    for i in range(number_of_blinks):
        pin.write('HIGH')
        sleep(0.5)
        pin.write('LOW')
        sleep(0.5)

if __name__ == '__main__':
    main()

With the time module we can even make the LED blink without any problem. The whole script can be extended to a Python module for GPIO control.

C Program

Also in C we can easily edit the content of the gpio folder. Using the standard library stdlib we can open files and change the contents.
The following C program must be compiled before it can be executed. Create a file gpio.c and copy the program into it.
Then open a terminal and navigate to the folder where the gpio.c file is located. Use the following commands to compile and execute the program.

gcc -o gpio gpio.c
./gpio

Here is the program.

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

#define GPIO_ROOT "/sys/class/gpio"
#define EXPORT "/sys/class/gpio/export"
#define UNEXPORT "/sys/class/gpio/export"

#define LOW 0
#define HIGH 1

int export_pin(int num) {
    FILE* export = fopen(EXPORT, "w");
    if (export == NULL) {
        printf("Failed to open the export file\n");
        exit(-1);
    }
    fprintf(export, "%d", num);
    fclose(export);
    return 0;
}

int unexport_pin(int num) {
    FILE* unexport = fopen(UNEXPORT, "w");
    if (unexport == NULL) {
        printf("Failed to open the unexport file\n");
        exit(-1);
    }
    fprintf(unexport, "%d", num);
    fclose(unexport);
    return 0;
}

int set_direction(char *mode, int num) {
    char direction_file_path[1024];
    snprintf(direction_file_path, sizeof(direction_file_path), "/sys/class/gpio/gpio%d/direction", num);
    FILE* direction = fopen(direction_file_path, "w");
    if (direction == NULL) {
        printf("Failed to open the direction file\n");
        exit(-1);
    }
    fputs(mode, direction);
    fclose(direction);
    return 0;
}

int set_value(int val, int num) {
    char value_file_path[1024];
    snprintf(value_file_path, sizeof(value_file_path), "/sys/class/gpio/gpio%d/value", num);
    FILE* value = fopen(value_file_path, "w");
    if (value == NULL) {
        printf("Failed to open the value file\n");
        exit(-1);
    }
    fprintf(value, "%d", val);
    fclose(value);
    return 0;
}

int main() {

    int rslt;
    int num;
    int num_blinks;

    num = 13;
    num_blinks = 10;

    rslt = export_pin(num);
    rslt = set_direction("out", num);
    for (int i = 0; i < num_blinks; i++) {
        rslt = set_value(HIGH, num);
        sleep(1);
        rslt = set_value(LOW, num);
        sleep(1);
    }

    rslt = set_value(LOW, num);
    rslt = set_direction("in", num);
    rslt = unexport_pin(num);

    return EXIT_SUCCESS;
}

PiCockpit – GPIO App

The easiest way to control the GPIO pins is with the help of the GPIO App. The PiCockpit web interface is free for up to 5 Raspberry Pi. It offers two big advantages: You don’t need to know programming to control your GPIO pins and you can do this from anywhere.

Just install the PiCockpit client on your Raspberry Pi and connect to your PiCockpit account. After that you can easily control the GPIO pins via the web interface.

Next Steps

Now you know how to use the GPIO pins with the help of jumper wires. Of course there are also external Python modules and C libraries to control the GPIO pins. A good next step would be to extend one of the code examples. For example by using additional LEDs or a button.


Have fun experimenting!

Leave a Comment