IO Pi Tutorial 1 - The Blinking LED

Created 02/10/2015 | Blinking an LED with the Raspberry Pi

In this tutorial we will start with a blinking LED and then build a binary counter using 8 LEDs.  For this you will need your Raspberry Pi, an IO Pi, 8 red LEDs and 8 200R resistors.

We will use the AB Electronics python library to talk to the IO Pi, you can download the library from github using the following command in a terminal, and this will download the full python library into the currently selected folder.

git clone https://github.com/abelectronicsuk/ABElectronics_Python_Libraries.git

You will need to enable i2c on your Raspberry Pi, see our other tutorial on i2c: I2C, SMBus and Raspbian Linux

The AB Electronics python library uses another library called python-smbus, you can install it using apt-get with the following commands.

sudo apt-get update

sudo apt-get install python-smbus

 

Finally you will want to tell python where you download the AB Electronics python library by adding it into PYTHONPATH.

 

export PYTHONPATH=${PYTHONPATH}:~/Desktop/ABElectronics_Python_Libraries/IOPi/

 

If you downloaded it to somewhere other than your desktop you will need to change the path to match your download destination.

Now all of the libraries are installed and the Raspberry Pi is configured to use i2c we can begin building our first project.

Stage 1 – Blinking an LED

If you haven’t done so install your IO Pi onto the Raspberry Pi by connecting it onto the GPIO header.  Make sure your Raspberry Pi is turned off when you do this to minimise the risk of damaging the Raspberry Pi or the IO Pi.

Next connect the LED and resistor in series between Bus 2 – Pin 1 of the IO Pi and the ground pin as shown on the picture.

The IO Pi contains two MCP23017 I/O controller chips from Microchip.  The MCP23017 is an i2c based controller containing 16 I/O pins which can be configured individually as inputs or outputs.  The two MCP23017 controllers are configured on different I2C addresses so you can control them independently from each other, for more information on setting the I2C addresses see the IO Pi datasheet at http://www.abelectronics.co.uk/docs/stock/raspberrypi/iopi/Datasheet-IOPi.pdf

The maximum current you can draw from any of the pins on the MCP23017 is 25mA so by using the 200R resistor in series with the LED we limit the current to a safe level.

For this tutorial we will start by creating a new python program file called tutorial1.py.  You can use your favourite text editor for writing the program.  You can find a complete example of tutorial1.py in the ABElectronics_Python_Libraries/ABElectronics_IOPi/demos folder.

At the top of your program you will need to import the ABEHelpers library, IOPI library and time library.

#!/usr/bin/python
from ABE_helpers import ABEHelpers
from ABE_IoPi import IoPi
import time

The IOPI library is used for all communication with your IO Pi, it gives you control over almost everything that can be done with the MCP23017 controller.

The ABEHelpers class contains a function called get_smbus() that allows us to find out which I2C bus is being used on the Raspberry Pi.  Create an instance of the ABEHelpers class called i2c_helper and use it to create an i2c_bus object.

i2c_helper = ABEHelpers()

i2c_bus = i2c_helper.get_smbus()

As we are only going to be using one of the MCP23017 controllers we will create an instance of the IOPI class using the i2c_bus object and call it bus.  If you want to use both controller chips you will need to create two separate instances of the IOPI class with the I2C addresses for each chip.

bus = IoPi(i2c_bus, 0x21)

0x21 is the I2C address for the controller chip on bus 2, if you have changed the address selection jumpers on your IO Pi then you will need to change this number to match the new address.

With our new instance of the IOPI class we will be able to access all of the available methods for controlling the IO Pi.  Let’s begin by setting the pins to be outputs.

bus.set_port_direction(0, 0x00)

The 16 channels on each I/O bus are split into two 8 pin ports.  Port 0 controls pins 1 to 8 while port 1 controls pins 9 to 16.  Having two 8 pin ports gives us the ability to change the direction on 8 pins at once by sending an 8 bit byte of information to the IO Pi.  You can also set each pin separately using the set_pin_direction command but for our tutorial today we will stick with using set_port_direction.

set_port_direction takes two variables, the first is the port you want to control, 0 for pins 1 to 8 and 1 for pins 9 to 16.  The second variable is the command byte for setting the individual pin directions.  Setting a pin to 0 makes it an output while setting it to 1 makes it an input, just remember 0 = out, 1 = in. 

As a byte in binary is 8 bits long each bit represents one of the pins on the selected port. The least significant bit or the one nearest the right represents the lowest pin number while the most significant bit or the one nearest the left represents the highest pin number.  If we wanted to set pins 1 to 4 as inputs and 5 to 8 as outputs we could send the binary number 00001111.  If we wanted just pin 7 to be an input and everything else to be an output we could send the binary number 01000000. 

When working in python or most other languages it it’s the normal convention when dealing with bytes to use hexadecimal rather than binary numbers so 00001111 would become 0x0F while 01000000 becomes 0x40.  If you are not very good at converting between binary and hexadecimal in your head there are plenty of online converters available.

As we want all of the pins to be outputs we will send the binary number 00000000 which converted to hexadecimal is 0x00.

Next we will turn off all of the pins on port 0 with the write_port method.

bus.write_port(0, 0x00)

As with set_port_direction, write_port takes two variables, the first is the port to write to 0 or 1 and the second is the value to send to the port.  Sending a 0 turns a pin off while sending a 1 turns the pin on.

The IO Pi is now set up for blinking our led with all of the pins on port 0 set as outputs and switched off.  So how do we make an LED blink?

The first thing we are going to need is a loop so that the same commands can run over and over.  This can be done with a simple while loop.

while True:

As True is always true the while loop will keep running until you exit the program with a Ctrl-C.

We have an LED connected to pin 1 so we only need to talk to pin 1.  We could use the write_port command but that would update every pin on the port so if we have anything else connected to the other pins it would affect them as well.  What we need is a way to write to just one pin at a time and we do that with the write_pin method.

     bus.write_pin(1, 1)

write_pin take two variables, the first is the pin you want to talk to, 1 to 16, the second variable controls the state of that pin.  1 will turn the pin on and 0 will turn the pin off.

We could now use another write_pin command to turn the led off but the program will switch the led on and off so fast you will just see a glowing LED.  What we need is a short delay between turning the pin on and off, for that we use the time.sleep method.

     time.sleep(1)

time.sleep takes one variable, a number which represents the number of seconds to wait.  1 will make the program sleep for 1 second while 0.1 would wait for 100ms.

Next we add another write_pin command to turn the LED off and another sleep command to wait another second.

     bus.write_pin(1, 0)
     time.sleep(1)

That is everything we need to make an LED blink, your program should now look like this.

#!/usr/bin/python
from ABE_helpers import ABEHelpers
from ABE_IoPi import IoPi
import time

i2c_helper = ABEHelpers()
i2c_bus = i2c_helper.get_smbus()

bus = IoPi(i2c_bus, 0x21)

bus.set_port_direction(0, 0x00)
bus.write_port(0, 0x00)

while True:
    bus.write_pin(1, 1)
    time.sleep(1)
    bus.write_pin(1, 0)
    time.sleep(1)

Save your program and run it in a command terminal using

python tutorial1.py

If everything goes as planned your LED should now be turning on and off every second.

 

Stage 2 – Making a binary counter

Now we have one LED that blinks lets expand on that and make an LED counter that counts from 1 to 255 in binary.

Connect your remaining 7 LEDs and resistors to pins 2 to 8 as shown in the picture.

We will modify the previous program to make it display numbers on the LEDs, first save your program to a new file called tutorial1a.py.

Everything up until the while loop can stay as it was, we still need to set all of the pins to outputs and turn them off.  Remove all of the commands after while True:

We want to make a counter that counts from 0 to 255, the easiest way to do that is with a for loop.

   for x in range(1,255):

The for loop will loop through the numbers in the range of 0 to 255 and store the current number in the variable x.

Next we will write out the current number to port 0 using the write_port command.

   bus.write_port(0, x)

This will send the variable x to the port and display it on the LEDs as a binary number.  Now we want to make the program sleep for half a second between each count so we get a chance to see the numbers increase.

   time.sleep(0.5)

Once the for loop has finished counting to 255 it will jump onto the next command in the program.  We will finish off by sending a final write_port command to turn all of the LEDs off before the while loop starts the counter again.

   bus.write_port(0, 0x00)

That is everything, you program should now look like this.

#!/usr/bin/python
from ABE_helpers import ABEHelpers
from ABE_IoPi import IoPi
import time

i2c_helper = ABEHelpers()
i2c_bus = i2c_helper.get_smbus()

bus = IoPi(i2c_bus, 0x21)

bus.set_port_direction(0, 0x00)
bus.write_port(0, 0x00)

while True:

   for x in range(0,255):
      bus.write_port(0, x)
      time.sleep(0.5)          

   bus.write_port(0, 0x00)

Save the program and run it at the command prompt with.

python tutorial1a.py

You should see the leds change counting from 1 to 255 in binary.  It will take about 2 minutes to count to 255, if you want it to go faster change the time.sleep with a smaller number.

Shop

Support

Click to contact us.
X

Have any Questions?

Send us any questions about this page or product and we will reply within 24 hours.

Submit your Message

X

Have any Questions?

Thank you for contacting us.

We will respond to your enquiry in the next 24 hours.

You can find answers to many questions and additional product support in our Knowledge Base and the Community Forum.