I SPI with Raspberry Pi

Updated 22 April 2022

SPI connection

I SPI with my Raspberry Pi, something beginning with…S! Serial-Peripheral-Interface (SPI)! Welcome to our Raspberry Pi SPI communication tutorial. Today we’re going to look at how to use the SPI bus on our Raspberry Pi to communicate with SPI enabled devices.

SPI?

SPI is a synchronous serial communication protocol developed by Motorola for communication in embedded systems over a short distance between a single master device, and multiple slave devices. SPI is a cousin of the I2C communication protocol (check out our I2C with Raspberry Pi tutorial), however it is a faster method of communication than I2C, with the drawback of needing a Chip Select wire for every slave device on the bus.

Like in our I2C tutorial, take a look at the SPI and the Arduino tutorial which covers the ins and outs of SPI communication in a general sense, before moving into Arduino specific content.

As fun and all as today’s High Defintion displays and graphical displays are, it can often by quite useful to display information or graphics on a dot matrix display. You could make a snake game, a simple side scroller, tetris, and many other applications.

Today, we’re going to be looking at using the Sparkfun SPI 8x8 Red/Green LED Matrix which uses SPI to interface with a controller device. This gives us a 64 LED grid to use with 4 different colour options per LED: off, Red, Green, and Yellow (Red Green).

The Gear

To follow this tutorial you will require the following components:

Along with this things, you will need everything required to use the Pi 3 board such as a power supply, display etc… for more info on this, check out our Getting Started with Raspberry Pitutorial. As always, we strongly recommend using the Pimoroni Pibow Coupe case. The hardware access and pin labelling will change your life

The Goal

We’re going to use the SPI bus on the Raspberry Pi to create an LED sequence on the LED matrix. Once you understand how to control the LEDs on the matrix, you can write a program to do whatever you want it to do.

Even though another SPI device might operate differently and require different data to be sent to it, it still remains within the structure of SPI communication, which means once you understand how to send/receive data on the SPI bus, you can control any device as per its datasheet. The datasheet for the Sparkfun LED matrix can be found here.

Raspberry Pi Board Setup

Before we do anything though, we need to do a few things to setup our Raspberry Pi board to work with the SPI interface. The first thing to do is make sure that Raspbian is updated to the latest version. To do this, open a new Terminal window and type:

sudo apt-get update

And after the update is completed:

sudo apt-get upgrade

Awesome, now you Raspberry Pi will have all of the latest packages available to use. Now we need to enable the SPI interface on our board. To do this, go to the Menu -> Preferences -> Raspberry Pi Configuration, then under the ‘Interfaces’ tab, select SPI as ‘enabled’, and then reboot.

All the tools and python libraries required to use the SPI bus are now included in the latest build of Raspbian, so we don’t need to worry about downloading any external packages.

Your Pi should now be setup to use the SPI interface in Python.

Communicating with the LED Matrix Backpack

By reading through the datasheet for the backpack (backpack is the term for the controller board built on the back of the LED grid), we can see that controlling the LEDs is quite simple.

Each LED can be controlled by sending a byte to the backpack sequentially (one after the other) along the MOSI line on the SPI bus. It maintains a 64 byte buffer which means that the last 64 bytes to be sent to it are stored in the buffer. The backpack will accept the input when the chip select is asserted (held low for the device). In this time, the first byte you send to it will control the first LED, the second byte will control the second LED and so on. As per SPI protocol, the backpack will send the old buffer data back to the master device via the MISO line on the SPI bus.

Therefore if we want to control all 64 LEDs at once, we need to send a packet of 64 bytes sequentially to the backpack board, with the value of each byte determining the colour of the corresponding LED.

As specified in the datasheet, the colour for each LED can be set as follows:

  • Off: 0x00
  • Green: 0x01
  • Red: 0x02
  • Green Red (Yellow): 0x03

*Note that the SPI dev module is taking care of all the timing and nitty-gritty details required to send data on an SPI bus, this allows us to only focus on the data we’re sending*

CircuitThe Circuit

As always, make sure that you’re Raspberry Pi is unplugged from power before connecting anything up to the GPIO pins, this reduces the risk of accidentally shorting something and potentially damaging a pin, or the whole board.

The only issue with our board (they might have fixed it in a later revision, however this backpack is at the end of its life cycle, so maybe not) is that the connectors on either side seem to be counter intuitively named. One set of headers is marked as SPI Output, and the other as SPI Input, however the MOSI pin which is the Master Output, is on the input side. 

Backpack highlights

We confirmed the MOSI and MISO pins to be labelled correctly, so just be aware that the SPI Output headers are where you’ll actually plug all the input wires into. Logic huh? This kind of makes sense when you are daisy chaining multiple backpacks, however as long as you match up the colours of the wires as per our diagram, everything should be fine.

The issue with this backpack is that it operates at 5V which makes it troublesome to connect up to our Raspberry Pi, which operates all its GPIO pins including the SPI bus at 3.3V. Never fear though, that’s why we’ve got the logic level converter on there. It is bi-directional which means we could also use it to step down 5V logic signals to 3.3V, very handy to have in your inventor’s tool kit.

The Code

The code below is designed to light the LEDs up sequentially, then turn them all off in the same order. This is accomplished by creating a list and populating it/wiping it then sending that list on the SPI bus each time we make a change. The beauty of the 64 byte buffer on the backpack is that if we only send one byte to it in a block, it will only write to the first LED and will not change the rest of the LED bytes. Thus we can create our sequence by adding a new colour byte to the list, sending it, and repeat. At the end of each cycle, we change the colour.

Write it into your Python3 editor and go Run -> Run Module to run the program inside the Python shell. Make sure that you use Python3 as there might be unexpected results in the older environment due to structural changes.

#import modules
import spidev
import time

#initialise SPIDev
spi=spidev.SpiDev()
spi.open(0,0)
spi.max_speed_hz = 125000
time.sleep(0.0005)

#create our list to send on the SPI bus
to_send = []

#initialise variables
colour = 0x01
delay = 0.05

#set all LEDs to off
for i in range (0, 64):
    to_send.append(0x00)
    spi.xfer(to_send)

time.sleep(0.0005)  #delay for stability

#main loop
try:
    while 1:
        
        #if to_send list contains less than 64 values, add another byte to the list
        if to_send.count(colour) < 64:
            del to_send[:]
            for i in range(0,64):
                to_send.append(colour)
                spi.xfer(to_send)
                time.sleep(delay)
                
        #if the list is full (64 items), reset the list and replace each value with 0x00
        if to_send.count(colour) == 64:
            del to_send[:]
            for i in range(0, 64):
                to_send.append(0x00)
                spi.xfer(to_send)
                time.sleep(delay)
                
        colour = colour   0x01  #cycle through the available colours

        if colour == 0x04:  #when the last colour is reached, reset to 0x01
            colour = 0x01
        
except KeyboardInterrupt:   #if Ctrl   C is pressed, cleanly exit our program
    for i in range (0, 64):
        to_send.append(0x00)
    spi.xfer(to_send)   
    spi.close()
    print("Program Exited")

The key to the way this program operates is the two different methods of data transfer that can be used with the SPI dev module.

Xfer2 will send data on the MOSI line, and keep the CS active between blocks, however the Xfer function will send data on the MOSI line and reset the CS line between each block. This means that when we are sending less than 64 bytes, it still counts as a complete transfer and only writes as many LEDs as bytes that we transferred.

Something to bear in mind is that the SPI protocol dictates that for as many bytes as you send from the master, the slave will output that many bytes back on the MISO line. The backpack datasheet states that it outputs the previous contents of the buffer each time it is refreshed. If we wanted to get feedback from the matrix, we could use the read function to read this data, but for this simple application, it isn’t needed, so we ignore it. For all of the available functions in the SPI dev module, check out the documentation here.

What Now?

Whilst we focused on working specifically with the Sparkfun LED matrix backpack, the functions and tools that we learnt about in the SPI dev module can be used to control any SPI device. The datasheet for each device should specify how it should be controlled within the SPI framework, and you can adapt your program accordingly. Check out our other tutorials and projects for inspiration for your next project, and feel free to let us know if you have any trouble.

Have a question? Ask the Author of this guide today!

Please enter minimum 20 characters

Your comment will be posted (automatically) on our Support Forum which is publicly accessible. Don't enter private information, such as your phone number.

Expect a quick reply during business hours, many of us check-in over the weekend as well.

Comments


Loading...
Feedback

Please continue if you would like to leave feedback for any of these topics:

  • Website features/issues
  • Content errors/improvements
  • Missing products/categories
  • Product assignments to categories
  • Search results relevance

For all other inquiries (orders status, stock levels, etc), please contact our support team for quick assistance.

Note: click continue and a draft email will be opened to edit. If you don't have an email client on your device, then send a message via the chat icon on the bottom left of our website.

Makers love reviews as much as you do, please follow this link to review the products you have purchased.