Using Multiple SPI Slave Devices with the Raspberry Pi

Recently I ran into an issue. The Raspberry Pi Kernel allows no more than 2 SPI Slave devices. Or at least, it provides file descriptors for only 2 slaves. My project needed 3 devices however, and I was too late in my schedule to get a different control board. Turns out there is an easy way to step around the problem. In this post, I will demonstrate the solution using WirirngPi and Python.

How SPI slave devices work
Most control boards capable of acting as an SPI Master Device have the following structure
SPI_three_slaves.svg
Typical SPI bus: master and three independent slaves
Image Attribution:  By en:User:Cburnett [GFDL (http://www.gnu.org/copyleft/fdl.html) or CC-BY-SA-3.0 (http://creativecommons.org/licenses/by-sa/3.0/)%5D, via Wikimedia Commons
 The master device usually sends a logic low signal to the slave channel it wants to communicate with, and a logic high to the others. This instructs the device receiving logic low signals to start reading data from MOSI and start writing to MISO, while the others are instructed to ignore the MOSI and stop writing to MISO.
In the Raspberry Pi Model 3, pins 7 and 8 (Broadcom numbering) are dedicated to slave select 1 and 0 for SPI. Our solution will require that we use other GPIO pins as slave selects. First let us look at example code to communicate with slaves 0 and 1 via WiringPi in Python assuming regular 2 slave behavior . It assumes that two slave devices are connected to the appropriate pins (7 and 8).

import wiringpi
wiringpi.wiringPiSetupGpio()

wiringpi.wiringPiSPISetup(0, 1000) #Setup SPI file descriptor communicate with slave 0 at 1000 Hz
wiringpi.wiringPiSPISetup(1, 1000) #Setup SPI file descriptor communicate with slave 1 at 1000 Hz

data = 'This is for slave 0'
recv = wiringpi.wiringPiSPIDataRW(0, data) #simultaneously read and write from and to slave 0
print(recv.decode())

data = 'This is for slave 1'
recv = wiringpi.wiringPiSPIDataRW(1, data) #simultaneously read and write from and to slave 1
print(recv.decode())
This code sets up WiringPi to work with Broadcom pin numbering. Then it sets up communication with slave select channels 0 and 1 at 1000 Hz. It then proceeds to read and write data to and from both slaves by setting the first argument of the function ‘wiringpi.wiringPiSPIDataRW()’.
To use 3 salves, we will connect our slaves to pins 6, 12 and 17 and only activate  one file descriptor (either 0 or 1) at the desired frequency. We will start with all the pins set to high, and when we want to communicate with a particular slave, we will set that pin to low, execute the communication and then set it back to high.
import wiringpi
wiringpi.wiringPiSetupGpio()
#start with all slaves disables
wiringpi.digitalWrite(6,1)
wiringpi.digitalWrite(12,1)
wiringpi.digitalWrite(17,1)

wiringpi.wiringPiSPISetup(0, 1000) #Setup SPI file discriptor communocate with slave 0 at 1000 Hz
data = 'This is for slave 0'
wiringpi.digitalWrite(6,0)
recv = wiringpi.wiringPiSPIDataRW(0, data) #simultaneouly read and write from and to slave 0
wiringpi.digitalWrite(6,1)
print(recv.decode())

wiringpi.digitalWrite(12,0)
data = 'This is for slave 1'
recv = wiringpi.wiringPiSPIDataRW(0, data) #simultaneouly read and write from and to slave 1
wiringpi.digitalWrite(12,1)
print(recv.decode())

wiringpi.digitalWrite(17,0)
data = 'This is for slave 2'
recv = wiringpi.wiringPiSPIDataRW(0, data) #simultaneouly read and write from and to slave 2
wiringpi.digitalWrite(17,1)
print(recv.decode())
Notice that the slave 0 descriptor was activated and the 1st argument to the function  wiringpi.wiringPiSPIDataRW() is always 0. Nothing is ever connected to that pin. We use it simply to keep SPI communication active. Since MOSI and MISO pins are common, simply sending logic signals to slave devices works just fine to indicate which device you want to communicate to.
I was able to solve my problem using this method. I hope this works for your purposes too. If you have any concerns or run into an issue, please leave a comment and we can try to solve it together. Thanks for reading!

One thought on “Using Multiple SPI Slave Devices with the Raspberry Pi

  1. Hi! Great Workaround! I am having the same problem using 3 RFID-Sensors! Unfortunately, there is a problem with the voltage levels. On the original SPI-Slave-Select-Outputs, HIGH means 3,3V and LOW means 1,6V. When setting an normal GPIO-Port to LOW, it provides 0V instead of 1,6V and my RFID-Sensor won’t do anything. Any ideas about that?

    Like

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s