SPI is less popular than I2C but still you'll see lots of sensors and chips use it. Unlike I2C, you don't have everything share two wires. Instead, there's three shared wires (clock, data in, data out) and then a unique 'chip select' line for each chip.

The nice thing about SPI is you can have as many chips as you like, even the same kind, all share the three SPI wires, as long as each one has a unique chip select pin.

The formal/technical names for the 4 pins used are:

  • SPI clock - called SCLK, SCK or CLK
  • SPI data out - called MOSI for Microcomputer Out Serial In. This is the wire that takes data from the Linux computer to the sensor/chip. Sometimes marked SDI or DI on chips
  • SPI data in - called MISO for Microcomputer In Serial Out. This is the wire that takes data to the Linux computer from the sensor/chip. Sometimes marked SDO or DO on chips
  • SPI chip select - called CS or CE

Remember, connect all SCK, MOSI and MISO pins together (unless there's some specific reason/instruction not to) and a unique CS pin for each device.

WARNING! SPI on Linux/Raspberry PI WARNING!

SPI on microcontrollers is fairly simple, you have an SPI peripheral and you can transfer data on it with some low level command. Its 'your job' as a programmer to control the CS lines with a GPIO. That's how CircuitPython is structured as well. busio does just the SPI transmit/receive part and busdevice handles the chip select pin as well.

Linux, on the other hand, doesn't let you send data to SPI without a CS line, and the CS lines are fixed in hardware as well. For example on the Raspberry Pi, there's only two CS pins available for the hardware SPI pins - CE0 and CE1 - and you have to use them. (In theory there's an ioctl option called no_cs but this does not actually work)

To let you use more than 2 peripherals on SPI, we decided to let you use any CS pins you like, CircuitPython will toggle it the way you expect. But when we transfer SPI data we always tell the kernel to use CE0. CE0 will toggle like a CS pin, but if we leave it disconnected, its no big deal.

The upshot here is basically never connect anything to CE0 (or CE1 for that matter) when using SPI in its default configuration. Use whatever chip select pin you define in CircuitPython and just leave the CE pins alone, it will toggle as if it is the chip select line, completely on its own, so you shouldn't try to use it as a digital input/output/whatever.

Reassigning or Disabling the SPI Chip Enable Lines

There are some add-on boards that use the CE0 and CE1 lines such as the PiTFT, so you don't have much choice in the way it is wired. Fortunately, the Raspberry Pi OS allows you to reassign the Chip Enable lines to some unused pins or even disable them from Operating System usage altogether by loading a Device Tree Overlay, which allows them to be accessible in Python. In order to make this as easy as possible, there's a script to do all the hard work for you.

To run the script, there are a few dependencies that you will need to install first:

cd ~
pip3 install --upgrade adafruit-python-shell click
wget https://raw.githubusercontent.com/adafruit/Raspberry-Pi-Installer-Scripts/main/raspi-spi-reassign.py

If you already know the GPIO lines you would like to use, you can pass them in as parameters to the script. For instance, if you want to assign GPIO 5 to CE0 and GPIO 6 to CE1, you can use the following command:

sudo -E env PATH=$PATH python3 raspi-spi-reassign.py --ce0=5 --ce1=6

Alternatively, you can pass "disabled instead of a number to disable its usage. For instance, to disable the OS from using either Chip enable, you could run the following command:

sudo -E env PATH=$PATH python3 raspi-spi-reassign.py --ce0=disabled --ce1=disabled

For all features or to run the script interactively, you can just use the following command:

sudo -E env PATH=$PATH python3 raspi-spi-reassign.py
If you have installed a PiTFT from another guide, you will need to "uninstall" that before you can use the main spi ports.
While the Chip Enable lines are reassigned or disabled, you likely will not be able to use kernel drivers for the reassigned or disabled lines.

Using the Second SPI Port

The Raspberry Pi has a 'main' SPI port, but not a lot of people know there's a second one too! This is handy if you are using the main SPI port for a PiTFT or other kernel-driven device. You can enable this SPI #1 by adding

dtoverlay=spi1-3cs

to the bottom of /boot/config.txt and rebooting. You'll then see the addition of some /dev/spidev1.x devices.

Here's the wiring for SPI #1:

  • SCK_1 on GPIO #21
  • MOSI_1 on GPIO #20
  • MISO_1 on GPIO #19
  • SPI #1 CS0 on GPIO 18
  • SPI #1 CS1 on GPIO 17
  • SPI #1 CS2 on GPIO 16

like the main SPI, we'll use CE0 as our default but don't connect to it! Use any other pin and leave that one unused. Then update your scripts to use

spi = busio.SPI(board.SCK_1, MOSI=board.MOSI_1, MISO=board.MISO_1)

Parts Used

OK now that we've gone thru the warning, lets wire up an SPI MAX31855 thermocouple sensor, this particular device doesn't have a MOSI pin so we'll not connect it.

Angled shot of a Thermocouple Amplifier breakout board.
Thermocouples are very sensitive, requiring a good amplifier with a cold-compensation reference. The MAX31855K does everything for you, and can be easily interfaced with any...
Angled shot of a Thermocouple Type-K Glass Braid Insulated wire.
Thermocouples are best used for measuring temperatures that can go above 100 °C. This is a bare wires bead-probe which can measure air or surface temperatures. Most inexpensive...

We recommend using a breadboard and some female-male wires.

Angled shot of Premium Female/Male 'Extension' Jumper Wires - 40 x 6 (150mm)
Handy for making wire harnesses or jumpering between headers on PCB's. These premium jumper wires are 6" (150mm) long and come in a 'strip' of 40 (4 pieces of each of...

You can use a Cobbler to make this a little easier, the pins are then labeled!

Angled shot of Assembled Pi T-Cobbler Plus next to GPIO ribbon cable
This is the assembled version of the Pi T-Cobbler Plus.  It only works with the Raspberry Pi Model Zero, A+, B+, Pi 2, Pi 3 & Pi 4! (Any Pi with 2x20...

Wiring

  • Connect the Raspberry Pi 3.3V power pin to Vin
  • Connect the Raspberry Pi GND pin to GND
  • Connect the Pi SCLK pin to the MAX31855 CLK
  • Connect the Pi MISO pin to to the MAX31855 DO
  • Connect the Pi GPIO 5 pin to to the MAX31855 CS

Double-check you have the right wires connected to the right location, it can be tough to keep track of Pi pins as there are forty of them!

Install the CircuitPython MAX31855 Library

OK onto the good stuff, you can now install the Adafruit MAX31855 CircuitPython library.

As of this writing, not all libraries are up on PyPI so you may want to search before trying to install. Look for circuitpython and then the driver you want.

Once you know the name, install it with

pip3 install adafruit-circuitpython-max31855

You'll notice we also installed a few other dependancies called spidev, adafruit-pureio, adafruit-circuitpython-busdevice and more. This is a great thing about pip, if you have other required libraries they'll get installed too!

We also recommend an adafruit-blinka update in case we've fixed bugs:

pip3 install --upgrade adafruit_blinka

Run that code!

The finish line is right up ahead. You can now run one of the (many in some cases) example scripts we've written for you.

Check out the examples for your library by visiting the repository for the library and looking in the example folder. In this case, it would be https://github.com/adafruit/Adafruit_CircuitPython_MAX31855/tree/master/examples

As of this writing there's only one example. But that's cool, here it is:

# SPDX-FileCopyrightText: 2021 ladyada for Adafruit Industries
# SPDX-License-Identifier: MIT

import time
import board
import digitalio
import adafruit_max31855

spi = board.SPI()
cs = digitalio.DigitalInOut(board.D5)

max31855 = adafruit_max31855.MAX31855(spi, cs)
while True:
    tempC = max31855.temperature
    tempF = tempC * 9 / 5 + 32
    print("Temperature: {} C {} F ".format(tempC, tempF))
    time.sleep(2.0)

Save this code to your Pi by copying and pasting it into a text file, downloading it directly from the Pi, etc.

Then in your command line run

python3 max31855_simpletest.py

The code will loop with the sensor data until you quit with a Control-C

Make sure you have a K-type thermocouple installed into the sensor breakout or you will get an error like the one below!

That's it! Now if you want to read the documentation on the library, what each function does in depth, visit our readthedocs documentation at

https://circuitpython.readthedocs.io/projects/max31855/en/latest/

This guide was first published on Jun 30, 2018. It was last updated on Mar 18, 2024.

This page (SPI Sensors & Devices) was last updated on Mar 18, 2024.

Text editor powered by tinymce.