• First Steps
  • General
  • Projects
Facebook Twitter YouTube
Tutorials for Raspberry Pi Tutorials for Raspberry Pi
  • Hardware & GPIO
  • Sensors & Components
  • Scale
  • Cases
  • Fingerprint
  • Gas Sensor
  • Heartbeat
  • German
Tutorials for Raspberry Pi Tutorials for Raspberry Pi
Home»Hardware & GPIO»Expand Raspberry Pi GPIOs with I2C Port Expander

Expand Raspberry Pi GPIOs with I2C Port Expander

Facebook Twitter LinkedIn Tumblr Email Reddit
Expand Raspberry Pi GPIOs with I2C Port Expander
Share
Facebook Twitter LinkedIn Email Tumblr Reddit Telegram WhatsApp

If you have several smaller or one larger project, you will soon discover that the GPIO pins of the Raspberry are fastly becoming too little. For all of you, this tutorial will show you how to use an I2C Port Expander to easily multiply the GPIO pins many times over.

 

In some situations, you may need more GPIO pins than it has outputs and you are at its physical limits. But there is a very useful port expander. On the use of one of these, we will discuss in this post.

 

Required Hardware Parts & General

For this tutorial you need the following hardware parts:

  • MCP23017
  • LEDs (best in different colors)
  • a button
  • Resistors
  • Breadboard
  • Jumper cable

 

First of all, the setup of the microchips:

mcp23017_pinout-300x243

As you can see the differences are minimal, for this tutorial it does not matter which one is used.

 

Preparation

A little explanation of the main pins:

  • GPA0-7 and GPB0-7 are the GPIO pins
  • A0, A1, A2 are connected to + (3.3V) or – (GND) and define the name internally. If several port expanders are connected, each must be clearly identifiable. With the first I²C you would connect all to GND, the next A0 to 3.3V and the other two to GND. At the third a! at 3.3V and the other two at GND etc. So it is possible up to 2³ and to connect an 8 port expander.
  • VDD (Pin 9) gets the input voltage (3.3V)
  • VSS (pin 10) is connected to GND
  • SCL (pin 12) is connected to the GPIO pin 5 of the Pi
  • SDA (pin 13) is connected to the GPIO pin 3 of the Pi

Accordingly, I have built a small circuit with 3 LEDs (as series resistors 330Ω).

i2c_breadboard

(We require the button only in Part 2 of the tutorial.)

The first thing to do is to unlock the I2C in the Pi. The easiest way to do this is by means of

sudo raspi-config

It is activated under “Advanced Options”> “I2C”.
For older versions of Raspbian, you also have to edit a file

sudo nano /etc/modules

and appends these two lines to the end:

i2c-bcm2708
i2c-dev

Save and exit with CTRL + O and CTRL + X.

 

Now the modules have to be removed from the blacklist file, otherwise, they will not work.

sudo nano /etc/modprobe.d/raspi-blacklist.conf

and put a # in front of the two entries.

#blacklist spi-bcm2708
#blacklist i2c-bcm2708

Save again with CTRL + O and CTRL + X and exit.

So that we can address the I2C now, we have to install a few more packages.

sudo apt-get install python-smbus i2c-tools

Then shut down the Pi, wait a few seconds and disconnect from the power.

sudo shutdown now

Testing Hardware

After everything is connected and all connections have been checked again, start the Pi and wait until it has started up.

I use a Raspberry Pi Rev.2, so I test it with:

sudo i2cdetect -y 1

If you have a Pi Rev.1, you must enter 0 instead of 1. The output looks like this:

pi@raspberrypi ~ $ sudo i2cdetect -y 1
     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f
00:          -- -- -- -- -- -- -- -- -- -- -- -- --
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
20: 20 -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
70: -- -- -- -- -- -- -- --

The address 0x20 (hexadecimal) contains the I2C. If A2 were e.g. connected to 3.3V (A1 and A0 to GND), it would be addressable at the address 0x24. This is, as mentioned above, important if you have connected several port expanders in order to be able to address them clearly.

To address the LEDs, the ports must either be declared as input or output (Rev1 please adjust the user again).

sudo i2cset -y 1 0x20 0x01 0x00

Here are some examples that explain how the command works:

i2cset -y 1 0x20 0x01 0x00   #all pins of GPB are output
i2cset -y 1 0x20 0x01 0x04   #GPB2 is input, the rest of GPB output (since 0x04 in binary 00000100)
i2cset -y 1 0x20 0x00 0x80   #GPA7 is input, the rest of GPA output

First of all the address addressed by i2cdetect is addressed. The second value is in this table (from the datasheet):

register

So after we have specified the direction (IODIRB) (0 = Output, 1 = Input), we want to let the three LEDs light up (Binary 00000111 = 0x07):

sudo i2cset -y 1 0x20 0x15 0x07

If we were to use the GPA pins, instead of 0x15, it would be 0x14.
For the LEDs to stop lighting, we need to reset the level of the pins to 0:

sudo i2cset -y 1 0x20 0x15 0x00

 

Raspberry Pi MCP23017 Python Script for Input and Output

So we create a script

sudo nano i2c_input_output.py

with the following content:

Python
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
import smbus
import time
 
#bus = smbus.SMBus(0) # Rev 1 Pi
bus = smbus.SMBus(1) # Rev 2 Pi
 
DEVICE = 0x20 # Device Adresse (A0-A2)
IODIRA = 0x00 # Pin Register fuer die Richtung
IODIRB = 0x01 # Pin Register fuer die Richtung
OLATB = 0x15 # Register fuer Ausgabe (GPB)
GPIOA = 0x12 # Register fuer Eingabe (GPA)
 
# Define GPA pin 7 as input (10000000 = 0x80)
# Binary: 0 means output, 1 means input
bus.write_byte_data(DEVICE,IODIRA,0x80)
 
# Define all GPB pins as output (00000000 = 0x00)
bus.write_byte_data(DEVICE,IODIRB,0x00)
 
# Set all 7 output bits to 0
bus.write_byte_data(DEVICE,OLATB,0)
 
# Function that makes all LEDs light up.
def aufleuchten():
    for MyData in range(1,8):
        # Count from 1 to 8, which is binary
        # from 001 to 111.
        bus.write_byte_data(DEVICE,OLATB,MyData)
        print "Zahl:", MyData, "Binaer:", '{0:08b}'.format(MyData)
        time.sleep(1)
        # Reset all pins to 0 again
        bus.write_byte_data(DEVICE,OLATB,0)
 
# Endless loop waiting at the push of a button
while True:
    # Read status of GPIOA register
    Taster = bus.read_byte_data(DEVICE,GPIOA)
 
    if Taster & 0b10000000 == 0b10000000:
        print "Taster gedrueckt"
        aufleuchten()

Save and exit with CTRL + O and CTRL + X.

To start the script now, we enter

sudo python i2c_input_output.py

As soon as you press the button, the LEDs light up. By pressing CTRL + C you can cancel the script and return to the console.

As you can see, using it is pretty easy and you have created another 16 GPIO pins.

GPIO Erweiterung i²c i2c MCP23017 more GPIO pins port expander port extender python
Share. Facebook Twitter Pinterest LinkedIn Tumblr Email
Previous ArticleRaspberry Pi Kompass selber bauen (HMC5883L)
Next Article Raspberry Pi RetroPie Guide – SNES Classic Spielekonsole selber bauen

Related Posts

Control all GPIOs with the Raspberry Pi REST API via Python

How to build a ESP8266 Scale (with Weight Sensor HX711)

Using TensorFlow Lite with Google Coral TPU on Raspberry Pi 4

How-To: Bluetooth Connection between ESP32’s and Raspberry Pi’s

1 Comment

  1. Frank on 14. August 2021 16:57

    Hello,

    Does this also works for Pi Rev. 3 B+?

    Kind regards

    Reply

Leave A Reply Cancel Reply

Raspberry Pi Autostart: Start the Program automatically

How to let an Arduino and Raspberry Pi communicate with each other

Measuring Temperature with a Raspberry Pi Temperature Sensor (1-Wire)

8×8 LED Dot Matrix – Assembly and Installation (Raspberry Pi)

Raspberry Pi Remote Access by using SSH and Putty

PiCar-X: Build a smart, self-driving robot car with the Raspberry Pi

Subscribe to Blog
Subscribe to Raspberry Pi Tutorials and don't miss any new Tutorial!
Subscribe

Thank you!

We will contact you soon.

Tutorials for Raspberry Pi
Facebook Twitter YouTube
  • Contact & Disclaimer

Type above and press Enter to search. Press Esc to cancel.