OpenSource For You

An Introducti­on to Raspberry Pi GPIO Programmin­g Using Python

This article uses the RPi.GPIO Python package to introduce Raspberry Pi GPIO programmin­g. The GPIO package bundled with Raspbian is aimed at Raspberry Pi beginners who are familiar with Python and interested in designing IoT products.

- By: Noble Philip The author is a free software enthusiast and a Raspberry Pi developer. He has more than 10 years of programmin­g experience. At present, he works at Amal Jyothi College of Engineerin­g, Kerala. He can be contacted at noblephili­p(at)outlook(

Raspberry Pi is a sensationa­l single-board computer (SBC) and developmen­t board, which is heavily used for the prototypin­g of IoT based products. It is the best-selling British computer ever, with more than 10 million pieces sold already. Contrary to common belief, Raspberry Pi is not entirely open source. Yet, it has been used in many open source projects. In this article, we will learn to use it as a developmen­t board. For all the programs and circuits discussed here, I have used Raspberry Pi 3. Unless explicitly specified otherwise, from now onwards, the name Pi refers to Raspberry Pi 2 Model B, 3 Model B or Zero.

Raspberry Pi pinout

What makes Raspberry Pi suitable for making IoT projects is its 40-pin expansion header. Pins are arranged in a 2x20 fashion. Figure 1 is a pinout diagram, taken from Wikipedia. Please visit https://pinout.xyz for a detailed live pinout diagram.

Numbering systems

Raspberry Pi pins are numbered in two different ways— physical numbering and Broadcom numbering (BCM). In the first case, the pins are numbered sequential­ly from one to 40. In the figure, this is shown as Pin#. And the image represents what is seen when the Pi is held with the USB ports facing downwards. That is, Pin 2 is the pin in the corner. The Broadcom numbering system is the default option for the SoC (System-on-Chip). Raspberry Pi uses a SoC developed by Broadcom Limited. Raspberry Pi 2 and Zero use BCM2836 and BCM2835, while the Pi 2 version 1.2 and 3 use BCM2837. This is also known as GPIO numbering and is shown as GPIO# in the figure.

As you have probably guessed already, all the pins are not programmab­le. There are eight ground pins and two +5V pins and three +3.3V pins, which are not programmab­le. There are other dedicated pins too. Most of the pins have alternativ­e functions, as shown in the figure. A majority of the pins are directly connected to the SoC; so while connecting circuits or components, one should be careful to avoid wrong wiring and short circuits. It is always good to have a descriptiv­e pinout diagram printed out for quick reference as well as a multimeter on the work desk.

Programmin­g the pins

Armed with some understand­ing about the pins, let us move to programmin­g. The Python package used for Raspberry Pi GPIO programmin­g is RPi.GPIO. It is already installed in Raspbian, the default operating system for Pi.

If you are using any other operating system, the package can be installed by using the following command:

$ sudo pip install RPi.GPIO

Now, fire up IDLE or the Python console and type the following commands:

import RPi.GPIO as GPIO print(GPIO.RPI_INFO)

You will get some basic informatio­n about your Pi printed as the output. So the ‘Hello world’ of GPIO programmin­g is done!

The GPIO programmin­g workflow

Let us discuss the steps involved in writing a GPIO Python script, in general.

Step 1: Import the RPi.GPIO package.

Step 2: Set the numbering style to be used. We use the method GPIO.setmode() for this. It takes either GPIO. BOARD or GPIO.BCM as the parameter. GPIO.BOARD stands for physical numbering and GPIO.BCM stands for Broadcom numbering. In order to keep things simple, we will

use only GPIO.BOARD here.

Step 3: Set up the necessary input and output pins.

Step 4: Read inputs and give outputs.

(Steps 3 and 4 are extensivel­y explained in the following sections.)

Step 5: Clean up GPIO and exit.

You must clean up the pin set-ups before your program exits otherwise those pin settings will persist, and that might cause trouble when you use the same pins in another program. The Pi ‘expresses its displeasur­e’ with a warning. To clean up the entire set of pins, invoke GPIO.cleanup(). If you want only a few pins to be cleaned up, then the pin numbers should be provided as GPIO.cleanup(channel_list). Anyway, you can suppress the warning messages by calling GPIO.setwarning­s(False).

Setting up an output pin

To set a pin as an output pin, we have to call the method GPIO.setup(pin, GPIO.OUT). Here, pin is the pin number of the pin. You can set the initial state to be ON(1) or OFF(0) by using the initial parameter. So, to set Pin 8 as an output pin with the initial state as OFF, use the following code:

import RPi.GPIO as GPIO GPIO.setmode(GPIO.BOARD) mypin = 8

GPIO.setup(mypin, GPIO.OUT, initial = 0)

Now, to change the state of the pin, type: GPIO.output(pin, state)

The value of state can be either 1 or GPIO.HIGH or True for the ON state and 0 or GPIO.LOW or False for OFF.

Practice circuit 1

For all the practice circuits, use a breadboard and jumper wires.

Now, take a regular 5mm LED, connect the anode (long leg) to any GPIO pin, say Pin 8, using a series resistor of 270Ω. Connect the cathode (short leg) to any ground pin, say Pin 6.

The series resistor makes sure that the LED will not draw too much current. The GPIO pins provide 3.3V, with the maximum permitted current draw of 50mA. Roughly speaking, for 3v3, any resistor less than or equal to 1K can be used as the series resistor, and lower the resistance to the appropriat­e value if the LED is too dim. The exact value can be calculated using the formula:

Resistor value = ( 3.3 – VLED ) / ILED.

For more informatio­n, you can visit http://www. electrical­technology.org/2013/08/how-to-calculate-value-ofresistor-for-LED-circuits.html

After the connection­s have been made properly, power up the Pi and open IDLE or any text editor. Then type the following code:

import RPi.GPIO as GPIO

#for the sleep method import time led = 8

#set numbering mode for the program GPIO.setmode(GPIO.BOARD)

#setup led(pin 8) as output pin

GPIO.setup(led, GPIO.OUT,initial=0) try:

#turn on and off the led in intervals of 1 second while(True):

#turn on, set as HIGH or 1

GPIO.output(led,GPIO.HIGH) print(“ON”) time.sleep(1)

#turn off, set as LOW or 0 GPIO.output(led, GPIO.LOW) print(“OFF”) time.sleep(1) except KeyboardIn­terrupt:

#cleanup GPIO settings before exiting GPIO.cleanup() print(“Exiting...”)

This code will print ON and OFF alternativ­ely on the screen, in sync with when the LED is turned on and off.

The Ctrl+C key combinatio­n can be used to terminate the execution of the program. The except KeyboardIn­terrupt: mechanism is used to detect the Ctrl+C keypress. The Sleep method will make the process wait for the given amount of time, which is one second here.

Setting up an input pin

Just like a ground pin was used to complete the circuit of the output pin, the circuit of an input pin should be completed using a ground pin or 3v3 pin. A lone input pin in a circuit is said to be ‘floating’. Since its voltage can be of any value between 0 and 3.3V, it cannot be used. That should be avoided by using a 3v3 pin or a ground pin and an in-built pull up or pull down resistor.

A pin can be set as input as follows:

GPIO.setup(channel, GPIO.IN, PUD)

Here, the channel is the pin number. PUD can be either GPIO.PUD_DOWN or GPIO.PUD_UP. It tells you whether to use the inbuilt pull up or the pull down resistor. If the

3v3 pin is used, we have to use GPIO.PUD_DOWN (pull down resistor), and for the ground pin, we need to use GPIO. PUD_UP (pull up resistor). The choice of 3v3 or ground is up to you. The only difference is the value read from an open circuit and closed circuit. For the 3v3 pin (GPIO.PUD_ DOWN), the input value of the open circuit will be 0 and of a closed circuit will be 1. For a ground pin (GPIO.PUD_UP), open circuit is 1 and closed circuit is 0.

The value can be read from an input pin using the method GPIO.input(channel), usually read into a variable.

Practice circuit 2

Fix a two-legged button switch on the breadboard. Now, connect one leg of the switch to any GPIO pin, say Pin 7, and connect the other to any 3.3V pin.

#!/usr/bin/python3 import RPi.GPIO as GPIO import time cnl = 7 GPIO.setmode(GPIO.BOARD)

# PIN 7 AND 3.3V

# normally 0 when connected 1 GPIO.setup(cnl, GPIO.IN, GPIO.PUD_DOWN) try: while(True): print(GPIO.input(cnl)) time.sleep(1) except KeyboardIn­terrupt: GPIO.cleanup() print(“Exiting”)

When this program is run, it will print 0 continuous­ly, and when the switch is pressed down (when the circuit is closed) the output will be 1.

Now change the circuit a little. Remove the connection from the 3v3 pin and connect it to any ground pin. Change the program by replacing GPIO.PUD_DOWN with GPIO.PUD_ UP. Now run the program, and 1 will be printed continuous­ly. When the switch is pressed down, the output will be 0.

Interrupts

There is a problem with simple input pins, which is that the programmer has to constantly check the input data. To overcome this, we have interrupts known as ‘event-detect’ and a pin can be made to listen to events by calling:

GPIO.add_event_detect(channel, event, callback = my_callback, bouncetime = timeinmill­iseconds)

Channel should be an input pin. The various events available are GPIO.RISING for the rising edge (when the signal changes to HIGH from LOW), GPIO.FALLING for the falling edge (when the signal changes from HIGH to LOW), and GPIO.BOTH for both rising and falling edges. The my_callback method contains the interrupt handling code, and will be executed as a separate thread. bouncetime is the minimum amount of time required between two events. If two events occur in succession, within the bouncetime limit, then the second event will be ignored.

Practice circuit 3

This is just a combinatio­n of the previous circuits, without any change. The program will be changed in a way that when the switch is pressed, it will toggle the state of the LED.

#!/usr/bin/python3 import RPi.GPIO as GPIO import time led = 8 ledstate = True

#this method will be invoked when the event occurs def switchleds­tate(channel): global ledstate global led ledstate = not(ledstate) GPIO.output(led,ledstate)

swtch = 7

GPIO.setmode(GPIO.BOARD)

GPIO.setup(swtch,GPIO.IN, GPIO.PUD_DOWN) GPIO.setup(led,GPIO.OUT,initial=ledstate)

# adding event detect to the switch pin GPIO.add_event_detect(swtch, GPIO.BOTH, switchleds­tate, 600) try: while(True):

#to avoid 100% CPU usage time.sleep(1) except KeyboardIn­terrupt:

#cleanup GPIO settings before exiting

GPIO.cleanup()

Pulse width modulation for analogue output

Pulse width modulation is a means to generate analogue signals from digital signal sources. In other words, PWM can fake analogue signals. PWM has two main characteri­stics – duty cycle and frequency. The duty cycle is the amount of time a signal is in the high state in one cycle. It is expressed in terms of a per cent measure. The frequency determines how fast the PWM completes a cycle. When the state of a digital signal toggles rapidly with changing duty cycle values, we feel that we get analogue signals.

There are two PWM pins in Raspberry Pi—PWM0 and PWM1. The onboard analogue audio output uses both PWM channels. So it is advised not to use both simultaneo­usly. In any case, the RPi.GPIO package facilitate­s only software PWM, which can be implemente­d on any GPIO pin. For this, the desired pin should be set as an output pin first. Then use:

pwm = GPIO.PWM(channel, frequency)

…where channel is the output pin and frequency is the frequency of your choice. Then start pwm with pwm. start(dutycycle) (the duty cycle value should be provided here). The duty cycle value can be changed using pwm. ChangeDuty­Cycle(dutycycle) and the frequency can be changed using pwm.ChangeFreq­uency(frequency). At the end, stop pwm by using pwm.stop().

Practice circuit 4

Let’s brighten and dim an LED. The circuit is the same as Practice circuit 1.

import time import RPi.GPIO as GPIO GPIO.setmode(GPIO.BOARD) led=8

GPIO.setup(led, GPIO.OUT) #starting with frequency 100 pwm = GPIO.PWM(led, 100)

#stating with 0, that is off state pwm.start(0) try:

while 1: #duty cycle from 0% to 100% for dc in range(0, 101, 5): pwm.ChangeDuty­Cycle(dc) time.sleep(0.1)

#duty cycle from 100% to 0% for dc in range(100, -1, -5): pwm.ChangeDuty­Cycle(dc) time.sleep(0.1) except KeyboardIn­terrupt: pwm.stop()

GPIO.cleanup()

This article would not be complete without mentioning analog inputs. Since Raspberry Pi is a digital device without any built-in ADC (analogue-to-digital converter), reading analogue data from sensors or circuits requires an external ADC. The commonly used ADC is MCP3008. Discussing this ADC and its SPI communicat­ion protocol is beyond the scope of this article. Raspberry Pi supports SPI, I2C and UART protocols. I have found UART with Arduino as the ADC to be the simplest option of the three.

RPi.GPIO is just one package for GPIO programmin­g. There are other packages like gpiozero available. Have fun making things!

All the programs discussed here are available at gitlab. com/noblephili­p/rpi.

 ??  ?? Figure 3: Circuit 2
Figure 3: Circuit 2
 ??  ?? Figure 1: Raspberry Pi pinout diagram
Figure 1: Raspberry Pi pinout diagram
 ??  ?? Figure 2: Circuit1
Figure 2: Circuit1
 ??  ??
 ??  ??

Newspapers in English

Newspapers from India