In Part 1 I showed you how I set up my Raspberry Pi and Ciseco Slice of Pi/O board, ready to continue my Hockey Scoreboard project.
Here in Part 2, I will show you a very simple script that I used to test one of the MCP23017 pins as an output, simply powering an LED. It should give you a little bit more confidence to proceed on to more complex code, it certainly confirmed a few things for me.
I’m deviating away from my Scoreboard project slightly, but it only seems fair to share the knowledge I have gained from others.
What you will need: (on top of the Pi and Slice of PiO)
- An LED
- A resistor to match the LED, considering we are using 3.3v in this example
- A small breadboard
- A couple of male to male jumper cables
- LED: CPC Farnell LED
- Resistor: CPC Farnell Resistor
- Breadboard: CPC Farnell Mini Breadboard
- Jumper Cables: ‘have a look on eBay’

You’ll need these basics for the project
Before we start
Firstly, turn off your Pi (you can use sudo halt from Terminal, or just do it the GUI way)
Secondly, let’s take a peep at the Slice of Pi/O from the top:

The Ciseco Slice of PiO
These are the 16 additional pins I talked about in Part 1 for input/output, of which one of these we will be using for the test. Just think of these as extra GPIO pins, although the code is different later on. (I’ll cover that in a bit)
Also notice hiding in the middle of the 2 Banks are the words ‘GND’ and ‘I/O’. This is telling you that the header sockets to the left are Ground, and the headers to the right are the I/O or ‘live’. The I/O is our GPIO input/output equivalent.
(NOTE: If your numbering looks different to mine, you may have an early board that had a print error)Now that you know what we will be playing with, let’s get going.
Wiring up the LED

Make sure you use the right lane

Long leg goes to the right

Either way round is fine

Attach the jumper to the opposite GND lane
Understanding MCP23017 pin mapping
Let’s not get ahead of ourselves – we need to understand what we’re playing with here. This is where I got caught out when trying to learn how to use this chip.
The guide over at BobRathbone (website now closed) showed Bob addressing pins 1, 2 (seemed fine)…then 32…64…what?!
This is where understanding GPIO does you no favours. You get used to an almost logical sequence of pin numbering. With the I2C MCP23017, numbering is set out in a way that allows you to combine pin numbers to control more than one input/output pin at once, yet always totals to a different number to any other combination. (I’ll show you why this is important later)
Confused? You bet – so was I.
Luckily, Bob is a top chap and quickly replied to my email begging for help. Let’s start by looking at the table Bob sent me via email:
On the left we have the I/O column. 1-16 aka 16 pins. That bit is easy.
Then look at the Ciseco board column, again, easy as we covered this already in this blog – these are the pin numbers on the Slice of Pi/O.
The Bank column tells us that the ‘A’ pins belong to bank 0, and the ‘B’ pins are part of bank 1. Still with me?
Ok now look at the Decimal column. Numbering starts at 1, and continues to double until it hits 128 on pin 8. It then starts at 1 again and does the same for pins 9-16. These are the values you will use in your Python code to ‘turn on’ each pin – and the odd numbering just means you can turn on any combination with a unique value. For example:
To turn on I/O pin 1, I would use ‘1’ in my code (more on how that works later)
To turn on I/O pin 4, I would use ‘8’ in my code
Now, to turn on pins 1 and 4 simultaneously…you guessed it, we use ‘9’ i.e. 1 + 8. I’ll bet a cheese sandwich that you can’t get ‘9’ with any other combination…make sense?
You might be wondering how the two different banks can have the same numbering sequence. Won’t they clash? No. When you look at my test code later on, you will see that to turn on a pin, you need both the bank number (0 or 1) AND the pin number. This way, it knows which bank to address, then the pin number to turn on.
Any issues with that, just leave a comment below and I’ll answer any specific questions.
Test Python code
LCDTest.py
However, it’s worth going through the major parts of this file to help you understand what we have done. You will be amazed how much you go back and copy code from old projects.
I have added comments to the Python file to help you understand the structure, and tried the best I can below (in average man speak) to explain what each part does:
- Imports – import various modules to drive the things we want to do
- Set up SMBus – not sure just yet, but hey…you need this in there!
- Set the I2C address – this is the address that we soldered in (0x20)
- Set both banks to outputs – as we want to send power to the LED
- LED pin mapping – defines ‘led1’ as I/O 1 on the MCP23017, to use later
- Bank mapping – again, defines ‘bank0’ as 0, and ‘bank1’ as 1 – again, to use later
- Define bank addresses – so ‘bank1’ is 0x12 and ‘bank2’ is 0x13. Refer to the table below
- Lastly, the part that lights the LED – “turn on LED 1 in bank 0 (0x12), pin 1 (B0)”
#Imports
import smbus
import sys
import getopt
import time
import RPi.GPIO as GPIO
#Set up SMBus
bus = smbus.SMBus(0) #for revision 2 board...use 1
#Set the I2C address
address = 0x20
# Set both banks to outputs
bus.write_byte_data(address,0x00,0x00) # Set all of bank A to outputs
bus.write_byte_data(address,0x01,0x00) # Set all of bank B to outputs
#LED pin mapping
led1 = 1
#Bank mapping
bank0 = 0
bank1 = 1
#This section defines how we put the 'bank' and output numbers together to allow us to turn on specific outputs
#print "set_led bank=" + str(bank) + " data=" + str(data)
def set_led(data,bank):
if bank == 1: #If bank number = 1, write to bank 1. if not, write to bank 2
bus.write_byte_data(address,0x12,data)
else:
bus.write_byte_data(address,0x13,data)
return
def main():
set_led(led1,bank0) #sends power to B0 - aka bank 0 pin 1
if __name__ == "__main__":
main()
Run the Code
Once you have moved test Python file to your Pi, run the script in Terminal and you should see your LED light up like this:
Part 2 complete!
That’s the testing complete, which means we’re ready to move back to the scoreboard project and start working out how to use all of these pins to our advantage.
In Part 3 I will create a prototype scoreboard using all 16 pins and some buttons. We’re short by about 24 pins still (if we don’t use the GPIO), so future blogs will cover how to daisy-chain additional MCP23017 chips.
This is so helpful. I have a 30-40 year old manually driven sail boat display used for starting pursuit races. It is driven from a rotary 24 pole wafer switch and an additional toggle. I have no drawing for the logic. The display is a solenoid driven dual 7-segment thing. It does H, P, 1,2,3…20 and then 21…39 via the toggle. But the club needs to automate it so it runs through the sequence on time. I now have a pi, one slice board and your LED alight. Now I need to piggy back on the rotary switch via GPI’s. I am novice with Python – so the code will be a fun challenge.
Hi Robin
Glad this helped. Interestingly it was one of the first things I tried with the Pi, and as I look back now, I don’t know why I attempted such a potentially confusing project to start off with!?
I love hearing about ‘real’ projects, yours sounds like a really good use for the Pi.
Good luck!