SPI Sensors & Devices

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 Master Out Slave 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 Master In Slave 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/DragonBoard 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 DragonBoard 410c, there's only one CS pin available for the hardware SPI pins - SPI_CS - and you have to use it. (In theory there's an ioctl option called no_cs but this does not actually work)

The upshot here is - to let you use more than 1 peripheral 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 SPI_CSSPI_CS 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 SPI_CS. Use whatever chip select pin you define in CircuitPython and just leave the CS pin 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.

Don't forget you have to enable SPI first!

Parts Used

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

Thermocouple Amplifier MAX31855 breakout board (MAX6675 upgrade)

PRODUCT ID: 269
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...
$14.95
IN STOCK

Thermocouple Type-K Glass Braid Insulated

PRODUCT ID: 270
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...
OUT OF STOCK

Because the DragonBoard 410c uses 1.8V logic levels, you will need a logic level converter to interface with most peripherals.

4-channel I2C-safe Bi-directional Logic Level Converter

PRODUCT ID: 757
Because the Arduino (and Basic Stamp) are 5V devices, and most modern sensors, displays, flash cards and modes are 3.3V-only, many makers find that they need to perform level...
$3.95
IN STOCK

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

Premium Male/Male Jumper Wires - 40 x 6" (150mm)

PRODUCT ID: 758
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...
$3.95
IN STOCK

Half-size breadboard

PRODUCT ID: 64
This is a cute half size breadboard, good for small projects. It's 2.2" x 3.4" (5.5 cm x 8.5 cm) with a standard double-strip in the middle and two power rails on both...
$5.00
IN STOCK

Wiring

  • Connect the DragonBoard Ground pin to the blue ground rail on the breadboard
  • Connect the DragonBoard +5V pin to the red 5V rail on the breadboard.
  • Connect the DragonBoard +1.8V pin to the LV pin on the Logic Level Converter
  • Connect the HV pin on the Logic Level Converter to the MAX3185 3Vo
  • Connect the Ground pin on the Logic Level Converter to the blue ground rail on the breadboard 
  • Connect the Vin pin on the MAX31855 to the red 5V rail on the breadboard 
  • Connect the Ground pin on the MAX31855 to the blue ground rail on the breadboard 
  • Connect the B1 pin on the Logic Level Converter to the MAX31855 DO
  • Connect the B2 pin on the Logic Level Converter to the MAX31855 CS
  • Connect the B3 pin on the Logic Level Converter to the MAX31855 CLK
  • Connect the DragonBoard SPI MISO to the A1 pin on the Logic Level Converter
  • Connect the DragonBoard GPIO 12 to the A2 pin on the Logic Level Converter
  • Connect the DragonBoard SPI CLK to the A3 pin on the Logic Level Converter
The DragonBoard 410c pin layout is different than Raspberry Pi and uses 1.8 Volt Logic Levels. Running with anything high could destroy your board.

Double-check you have the right wires connected to the right location, it can be tough to keep track of Header 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

sudo 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:

sudo 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:

import time
import board
import busio
import digitalio
import adafruit_max31855

spi = busio.SPI(board.SCK, MOSI=board.MOSI, MISO=board.MISO)
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 DragonBoard by copying and pasting it into a text file, downloading it directly from the Pi, etc.

Change the line that says

cs = digitalio.DigitalInOut(board.D5)

to

cs = digitalio.DigitalInOut(board.GPIO_12)

Then in your command line run

sudo 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 28, 2019. It was last updated on Jun 28, 2019. This page (SPI Sensors & Devices) was last updated on Oct 10, 2019.