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

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!
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?
LikeLike