In our previous tutorial, we saw how you can set up a Raspberry Pi and access its GUI using VNC and HDMI or use it Headlessly using SSH. Personally, I prefer using VNC as it does not require additional peripherals like keyboard and mouse. So for this tutorial as well as other tutorials, I’ll be using VNC to access my Raspberry Pi. In this article, we will look at GPIO and PWM in Raspberry Pi.

But before move forward, lets us look at some of the important sudo(superuser) commands which you should execute occasionally to keep your Raspberry Pi up to date. You need root access to execute such commands.

Open Your Raspberry Pi terminal and type, <span style="color: #000000;">'sudo apt-get update'</span>. This will update all the existing Packages on your Raspberry Pi. If there are any new updates available, the system will prompt you for confirmation [y/n]. Type y and hit enter to continue. Next, you need to upgrade and install newer packages that have just been updated using the previous command. Type <span style="color: #000000;">'sudo apt-get dist-upgrade'</span>. This command may also remove some of the unwanted packages.

Now that you’ve updated you RPi, lets us move forward with the task in our hand.

GPIO in Raspberry Pi

GPIO and PWM in Raspberry Pi

Raspberry Pi

Every pin in the Raspberry Pi apart from the power and ground pins have been assigned as GPIO. You can find the GPIO pin mapping by typing ‘pinout’ in your Raspberry pi terminal. The Raspberry Pi Model 3B+ comes with 26 programmable GPIO pins, two 5V and 3.3V pins each, 8 ground pins, and 2 Pin reserved for interfacing external EEPROM, making a total of 40 pins.

The Raspberry Pi GPIO pins are 3.3V tolerant. When you set a pin high, the output voltage across that pin is 3.3V. So a 5V device should not be connected directly to the pin. The same applies when you define a GPIO pin as an input, care must be taken that the input voltage must not exceed 3.3V as it may damage your Pi.

Each of the Raspberry Pi’s GPIO pin individually can source 16mA. All the GPIO pins as a whole can safely withdraw a maximum of 54mA. When you’re using multiple GPIO pins, make sure that the total current being sourced out of the RPi must not exceed 54mA. Exceeding these limits can eventually cause damage to your Raspberry Pi.

GPIO pins in Raspberry Pi can also be set as a source of interrupt. It supports interrupt on change, i.e. a high to low transition or vice versa on its GPIO pin as well as a level sensitive interrupt. These can be configured in the software.

Blinking a LED using GPIO

Let us first create a new python file(.py) where we can write our code. To do so, open the applications menu –> programming and click on IDLE. IDLE is a built-in IDE for python which is one of the many application that comes preinstalled with raspbian.

When you click on IDLE, a shell window will be opened. You can use IDLE’s python shell to view your output. It will also allow you to execute your python scripts without actually opening them.

Now click on ‘File’ and create a new file. Once you do so, IDLE’s Editor window will be opened. You will then need to save this file with a .py extension.

Now let us begin writing our code in python.

import RPi.GPIO as GPIO
import time
LED = 17

First, we import the Raspberry Pi’s GPIO and time Library. You can assign a reference to RPi.GPIO library using the ‘as’ clause. Here we give ‘GPIO’ as a reference to the RPi.GPIO library and Initialize variable LED as 17

GPIO.setmode(GPIO.BCM)
GPIO.setup(LED, GPIO.OUT)

Setting the GPIO mode as GPIO.BCM will map your raspberry Pi Pins to BCM pin numbering system. Alternately GPIO.BOARD can also be used which will essentially assign pin numbers based on the GPIO header connected on your PI. GPIO.setup is used to define the direction of the GPIO pin, i.e. either input or output.

try:
    while 1:
        GPIO.output(LED, GPIO.HIGH)
        print("LED turned on")
        time.sleep(1)
        GPIO.output(LED, GPIO.LOW)

        print("LED turned OFF")
        time.sleep(1)
except KeyboardInterrupt:

    GPIO.cleanup()

The ‘try’ and ‘except’ block are used to handle exceptions. The code written in the ‘try’ block will begin its execution. If the except block condition holds true, the control will directly go to execute the except block. Here we are using keyboard interrupt as an except block condition which is raised when you hit ‘Control+c’ on the keyboard. Inside the except block, the cleanup function of the GPIO library is used which will clean all the assigned functions to the GPIO pins. In the ‘try’ block, inside the While loop, pin no 17 is turned on and off using GPIO.HIGH and GPIO.LOW with a delay of 1 Second.

GPIO pin as an INPUT

Now let us set up a GPIO pin as an input. We will use a push button as a source of input for the PI. when the button is pressed, LED on pin 17 will go high and when the button is released LED will turn off.

import RPi.GPIO as GPIO
import time

LED = 17
Button = 27

GPIO.setmode(GPIO.BCM)
GPIO.setup(LED, GPIO.OUT)
GPIO.setup(Button, GPIO.IN, pull_up_down = GPIO.PUD_UP)

Pin number 27 has been set up as an input pin and has been internally pulled up using GPIO.PUD_UP

try:
    while 1:
        if GPIO.input(Button): 
            GPIO.output(LED, GPIO.LOW)
        else:
            GPIO.output(LED, GPIO.HIGH)
except KeyboardInterrupt:
    GPIO.cleanup()

PWM in Raspberry Pi

PWM is a technique of controlling the output voltage by varying the Duty Cycle of a stable DC voltage signal at fixed or varying frequency thereby allowing you to obtain an average output voltage level anywhere between the minimum and maximum signal level. The two main PWM parameters are Period and Duty cycle. A period is the amount of time taken to complete a cycle. A PWM signal with a period of 10ms implies a 100Hz signal frequency. Duty cycle, on the other hand, describes the amount of time the signal remains high in percentage with respect to the total time (Ton+Toff).
Duty cycle = (Ton/(Ton+Toff))*100

Back to the PI! The Raspberry Pi supports software configurable PWM on all its GPIO pins. You can essentially program a GPIO to output a PWM pulse of a varying duty cycle. Apart from software PWM, it also provides hardware PWM on GPIO12, 13, 18 and 19. It has 2 separate channels for hardware PWM. Channel zero i.e. PWM0 consisting of GPIO12 and GPIO18 and PWM1 with GPIO13 and GPIO19. These channels are also shared with the A/V circuitry on raspberry pi. So you won’t be able to simultaneously use A/V jack and hardware PWM.

Controlling LED brightness using PWM

import RPi.GPIO as GPIO
import time

LED = 17
Button = 27
duty = 0

GPIO.setmode(GPIO.BCM)
GPIO.setup(LED, GPIO.OUT)
GPIO.setup(Button, GPIO.IN, pull_up_down = GPIO.PUD_UP)

p = GPIO.PWM(LED, 100)

Here we create a PWM instance ‘p’ and pass the pin number and frequency as parameters.

try:
    while 1:
        if GPIO.input(BUTTON) == 0:
            p.start(duty)
            for change_duty in range(0,101,5):
                p.ChangeDutyCycle(change_duty)
                time.sleep(0.1)
            for change_duty in range(100, -1, -5):
                p.ChangeDutyCycle(change_duty)
                time.sleep(0.1)
        p.stop()

Inside the While loop, the push button is being scanned. If the pushbutton is pressed, PWM is initiated by passing the duty cycle inside p.start() A couple of ‘for loop’ statements are used to iterate over the python collection type Range.

In ‘range’, the first parameter indicates the start value, the next is the stop value and last is the step size. The duty cycle of the PWM pulse is being changed using p.ChangeDutyCycle(), with the value passed in it being 0, 5, 10 and so on.
Finally, if the pushbutton is released, the PWM is stopped using p.stop()

except KeyboardInterrupt: 
    print("Program stopped via keyboard interrupt")
    p.stop()
    GPIO.cleanup() 

Here the except block condition is the same as before.

So this was all about PWM and GPIO in RPi. Let us know if you have any query regarding the same.


Moiz

Electronics engineer graduated from M.H. Saboo Siddik college of engineering. Currently working as Jr. Innovative engineer. Skilled in 8051, PIC and ARM microcontrollers. Circuit analyzation and Debugging. Constantly looking to acquire more skills which would help myself to become more proficient in embedded domain. Founder and blogger at techetrx.com LinkedIn profile: https://www.linkedin.com/in/moiz-shaikh-305294137

1 Comment

Firoz Ansari · June 30, 2019 at 1:25 pm

Nicely documented and implemented. Thanks!

Leave a Reply

Your email address will not be published. Required fields are marked *