Knowledge Base

The AB Electronics UK Knowledge Base provides support solutions, tutorials and troubleshooting guides.

Knowledge Base

IO Zero 32 Tutorial 1 - The Blinking LED

Blinking an LED with the Raspberry Pi

This tutorial will start with a blinking LED and build a binary counter using 8 LEDs. You will need your Raspberry Pi, an IO Zero 32, 8 red LEDs, and 8 500R resistors.

We will use the AB Electronics UK Python library to talk to the IO Zero 32. To download the library, visit our Python Library and Demos knowledge base article.

You must enable I2C on your Raspberry Pi; see our other tutorial, I2C Part 2 - Enabling I²C on the Raspberry Pi.

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

sudo apt-get update
sudo apt-get install python3-smbus

We can begin building our first project with the libraries installed and the Raspberry Pi configured to use I2C.

Stage 1 – Blinking an LED

If you haven’t done so, install your IO Zero 32 onto the Raspberry Pi by connecting it to 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 Zero 32.

Next, connect the LED and resistor in series between Bus 1 – Pin 1 of the IO Zero 32 and the ground pin, as shown in the picture.

The IO Zero 32 contains two PCA9535 I/O controller chips from NXP. The PCA9535 is an I2C-based controller having 16 I/O pins, which can be configured individually as inputs or outputs. The two PCA9535 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 Zero 32 datasheet.

The maximum current you can draw from any of the pins on the PCA9535 is 50mA, so by using the 500R resistor in series with the LED, we limit the current to a safe level of 10mA at 5V.  

We will start by creating a new Python program file called tutorial1.py for this tutorial. You can use your favourite text editor to write the program. You can find a complete example of tutorial1.py in the ABElectronics_Python_Libraries/IOZero32/demos folder.

At the top of your program, you must import the IOZero32 library and time library.

#!/usr/bin/env python
from IOZero32 import IOZero32
import time

The IOZero32 library is used for all communication with your IO Zero 32; it gives you control over almost everything that can be done with the PCA9535 controller.

As we will only use one of the PCA9535 controllers, we will create an instance of the IOZero32 class and call it bus. To use both controller chips, you must create two separate instances of the IOZero32 class with the I2C addresses for each chip.

bus = IOZero32(0x20)

0x20 is the I2C address for the controller chip on bus 1; if you have changed the address selection jumpers on your IO Zero 32, you must change this number to match the new address.

With our new instance of the IOZero32 class, we can access all available methods for controlling the IO Zero 32. Let’s begin by setting the pins as 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 allows us to change the direction on 8 pins at once by sending an 8-bit byte of information to the IO Zero 32. You can also set each pin separately using the set_pin_direction() command or set the whole bus using set_bus_direction(), 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; 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 to set pin 7 as an input and everything else as an output, we could send the binary number 01000000.

When working in Python or most other languages, it’s the standard 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 binary and hexadecimal in your head, we have an online converter available on our website.

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

Next, we will turn off all 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 port to write to 0 or 1 and the value to send to the port. Sending a 0 turns a pin off while sending a 1 turns the pin on.

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

We will first need a loop so that the same commands can run repeatedly. This can be done with a simple while loop.

while True:

As True is always true, the while loop will continue 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 also affect them. We need a way to write to just one pin at a time and do that with the write_pin method.

bus.write_pin(1, 1)

write_pin takes two variables: the first is the pin you want to talk to, 1 to 16, and 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 that you will see a glowing LED. We need a short delay between turning the pin on and off; we can use the time.sleep method.

time.sleep(1)

time.sleep takes one variable, a number representing 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/env python
from IOZero32 import IOZero32
import time

bus = IOZero32(0x20)
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

python3 tutorial1.py

If everything goes as planned, your LED should turn on and off every second.

Stage 2 – Making a binary counter

Now we have one LED that blinks. Let us 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 until the while loop can stay as it was; we still need to set all the pins to outputs and turn them off. Remove all of the commands after while True:

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

for x in range(0,255):

The for loop will loop through the numbers from 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 as a binary number on the LEDs. We want to make the program sleep for half a second between each count so we can see the numbers increase.

time.sleep(0.5)

Once the for loop has finished counting to 255, it will jump onto the following command in the program. We will send a final write_port command to turn all the LEDs off before the while loop starts the counter again.

bus.write_port(0, 0x00)

That is everything. Your program should now look like this.

#!/usr/bin/env python
from IOZero32 import IOZero32
import time

bus = IOZero32(0x20)
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.

python3 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.


(images created with Fritzing)


Was this article helpful? Yes No

Please tell us how we can improve this article:

Submit
Created 28/05/2022 | Last Updated: 11/11/2023

Related Expansion Boards

Order a IO Zero 32 Photo of IO Zero 32
IO Zero 32

32 channel digital I/O expander for the Raspberry Pi

£13.19 Ex VAT: £10.99
Add to Basket

Related Articles

IO Zero 32 with Raspberry Pi Pico
Using the IO Zero 32 with Raspberry Pi Pico and MicroPython
IO Zero 32 Tutorial 1 - The Blinking LED
Blinking an LED with the Raspberry Pi
IO Zero 32 Tutorial 2 - Push the Button
Reading a button input using a Raspberry Pi and IO Zero 32