0% found this document useful (0 votes)
29 views12 pages

Micropython Hardware Spi Devices

This guide provides an overview of using the SPI protocol with MicroPython, specifically on the ESP8266, to communicate with devices like the MAX31855 thermocouple sensor. It covers setting up the hardware SPI connection, reading and writing data, and includes example code for implementation. However, the examples are no longer supported and users are encouraged to refer to CircuitPython resources instead.

Uploaded by

Yotuel Motiarty
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
29 views12 pages

Micropython Hardware Spi Devices

This guide provides an overview of using the SPI protocol with MicroPython, specifically on the ESP8266, to communicate with devices like the MAX31855 thermocouple sensor. It covers setting up the hardware SPI connection, reading and writing data, and includes example code for implementation. However, the examples are no longer supported and users are encouraged to refer to CircuitPython resources instead.

Uploaded by

Yotuel Motiarty
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 12

MicroPython Hardware: SPI Devices

Created by Tony DiCola

https://learn.adafruit.com/micropython-hardware-spi-devices

Last updated on 2024-06-03 01:59:46 PM EDT

©Adafruit Industries Page 1 of 12


Table of Contents

Overview 3

SPI Main 4
• Setup Hardware SPI Connection
• Read SPI Data
• Write & Transfer SPI Data

SPI Secondary 12

©Adafruit Industries Page 2 of 12


Overview
The examples in this guide are no longer supported and may not work. We are
only supporting CircuitPython on our boards. For more information about using
CircuitPython, check out the CircuitPython Essentials: https://learn.adafruit.com/
circuitpython-essentials/circuitpython-essentials

Note this guide was written for MicroPython.org firmware and not Adafruit
CircuitPython firmware.

Serial peripheral interface (https://adafru.it/qhB), or SPI, is a protocol for two devices


to send and receive data. For example a LCD display might use a SPI interface to
receive pixel data, or a temperature sensor might use SPI to send readings to a
microcontroller. With MicroPython you can use the SPI protocol to talk to devices and
write scripts that interface with interesting hardware!

This guide will explore how to use SPI with MicroPython. In particular MicroPython on
the ESP8266 will be used to talk to a simple SPI device, the MAX31855 thermocouple
temperature sensor (http://adafru.it/269). You'll learn how to create a SPI
interface, and send and receive data over that interface. With just the basics of
sending and receiving SPI data you can start to write your own MicroPython code that
interacts with other interesting SPI devices!

©Adafruit Industries Page 3 of 12


Before you get started you'll want to be familiar with the basics of using MicroPython
by reading these guides:

• MicroPython Basics: What is MicroPython? (https://adafru.it/pMb)


• MicroPython Basics: How to Load MicroPython on a Board (https://adafru.it/pNB)
• MicroPython Basics: Blink a LED (https://adafru.it/q2d)
• MicroPython Basics: Load Files & Run Code (https://adafru.it/r2B)

SPI Main
The examples in this guide are no longer supported and may not work. We are
only supporting CircuitPython on our boards. For more information about using
CircuitPython, check out the CircuitPython Essentials: https://learn.adafruit.com/
circuitpython-essentials/circuitpython-essentials

With the SPI protocol there's an important distinction between the 'main' device which
controls the communication and 'secondary' devices that send and receive data with
the main. In almost all cases the microcontroller is the main device that controls the
SPI communication. In this example we'll look at SPI main mode where a MicroPython
board acts as the main to control the SPI communication with other devices.

In most cases a SPI connection is made using at least four wires:

• Clock, the SPI main device toggles this line high and low to tell connected
devices when they should send and receive bits of data.
• MOSI (main output, secondary input), this line sends bits of data from the main
device to other connected devices. Think of this as the data output from the
main device.
• MISO (main input, secondary output), this line sends bits of data from
connected devices to the main device. Think of this as the data output from the
connected devices.
• Chip select, although not required most connected devices have a chip select,
or CS, line. This line is driven high or low by the SPI main to tell the connected
device that it should listen for SPI commands. As long as each device has a
separate chip select line you can usually share the clock, MOSI, and MISO lines
of a SPI connection between multiple devices.

©Adafruit Industries Page 4 of 12


Be aware with MicroPython there are some differences in how each board
implements the API for SPI main mode. As always consult each board's
documentation:

• MicroPython ESP8266 SPI documentation (https://adafru.it/r9b)


• MicroPython pyboard SPI documentation (https://adafru.it/pXb)

◦ The pyboard currently uses an older pyb module instead of the machine
module for the SPI interface. You also need to explicitly tell the SPI API
that you're creating a SPI main device connection. The functions for
sending and receiving data have slightly different names like recv instead
of read and send instead of write.

• MicroPython WiPy SPI documentation (https://adafru.it/reG)

◦ The WiPy SPI API also requires you tell it you're creating a SPI main device
connection.

• MicroPython micro:bit SPI documentation (https://adafru.it/qhD)

◦ The micro:bit uses a SPI mode parameter to set polarity and clock phase
instead of explicit parameters for each value. Use the table shown in the
documentation (https://adafru.it/qhD) to understand which mode is
necessary for the appropriate polarity and clock phase of your connection.

Note SPI protocol support across MicroPython boards is under development and
might change over time. Be sure to check your board's documentation to find
the latest information on SPI usage!

For this example we'll look at how to read data from a MAX31855 thermocouple
sensor connected to an ESP8266 running MicroPython. The MAX31855 sensor has a
very simple SPI interface that's easy to read temperature data with a few commands.

To follow this example you'll need the following parts:

• ESP8266 board running MicroPython, for example the Feather HUZZAH


ESP8266 (http://adafru.it/2821).
• MAX31855 thermocouple sensor breakout (http://adafru.it/269) and a compatibl
e thermocouple (http://adafru.it/270).
• Breadboard (http://adafru.it/64) & jumper wires (http://adafru.it/153).

Connect the components as follows:

©Adafruit Industries Page 5 of 12


• Board ground to MAX31855 ground.
• Board 3.3V output to MAX31855 Vin (voltage input).
• Board SCK (serial clock, ESP8266 GPIO14) to MAX31855 CLK (clock).
• Board MI (main input, ESP8266 GPIO12) to MAX31855 DO (data output).
• Board pin 15 to MAX31855 CS (chip select).

You'll also want to make sure a thermocouple is connected to the MAX31855


breakout's terminal block. Make sure to use an appropriate thermocouple like a
simple K-type thermocouple. Check out this handy thermocouple guide (https://
adafru.it/qhE) if you're unfamliar with their usage.

©Adafruit Industries Page 6 of 12


Although it's not necessary with the MAX31855, if you're using a SPI device that
should receive data from the ESP8266 you should connect the board MOSI/MO (main
output, ESP8266 GPIO13) to the MOSI or data input line of your device.

Note the above connections will use the hardware SPI interface on the ESP8266 to
talk to the MAX31855 sensor. Hardware SPI uses hardware built in to the
microcontroller to talk the SPI protocol. This is useful because the microcontroller
can handle all of the SPI communication even at very high speeds (multiple
megahertz). However when using hardware SPI you have to use specific clock, MOSI,
and MISO pins on the board as shown.

An alternative to hardware SPI is 'software SPI' which uses any GPIO pins for the
clock, MOSI, and MISO lines. This is more flexible than hardware SPI, but it's slower
because the SPI protocol is implemented in code instead of special hardware. Most
MicroPython boards don't yet support software SPI so it won't be shown in this guide,
however be aware the MicroPython ESP8266 port does support a software SPI
interface (https://adafru.it/r9b) if you need it.

Setup Hardware SPI Connection


To setup the SPI connection connect to the board's serial or other REPL and run the
following commands to import the machine module:

import machine

pyboard note: The pyboard SPI interface is currently using the older pyb module.
Check the pyboard documentation (https://adafru.it/pXb) for more details on its usage.

Next create a SPI interface by running the following command:

spi = machine.SPI(1, baudrate=5000000, polarity=0, phase=0)

Note this command might fail if you're running a slightly older version of
MicroPython ESP8266 firmware! In particular if you see the following error:

ValueError: no such SPI peripheral

Then instead run the command as:

spi = machine.SPI(0, baudrate=5000000, polarity=0, phase=0)

©Adafruit Industries Page 7 of 12


The reason for this difference is that the first parameter of the SPI class initializer
specifies which SPI interface on the board to use. Older versions of MicroPython
ESP8266 used interface 0 for the hardware SPI interface, however later versions
(after ~September 2016) used interface 1 for the hardware SPI interface.

pyboard & WiPy note: For the pyboard & WiPy their SPI class currently requires an
explicit SPI.MASTER parameter in addition to the other parameters above. Check
their documentation for more details on the usage.

micro:bit note: The micro:bit doesn't use polarity and phase parameters, instead it
uses a single mode parameter that implies both polarity and phase. Check the
micro:bit documentation (https://adafru.it/qhD) for more details.

The other parameters to the initializer control how the SPI interface is configured:

• baudrate controls the speed of the clock line in hertz.


• polarity controls the polarity of the clock line, i.e. if it's idle at a low or high level.

• phase controls the phase of the clock line, i.e. when data is read and written
during a clock cycle.

You'll need to look at your device's datasheet to see what clock speed/baudrate it
supports, and what polarity & phase values to specify too. Check out this description
of SPI polarity and phase (https://adafru.it/qhB) for more details on what they mean,
and how to convert from SPI modes (a common way to describe polarity & phase with
one number) to explicit polarity & phase values.

For the MAX31855 thermocouple sensor a polarity & phase of 0 (i.e. SPI mode 0) are
necessary to talk to the device, and a baudrate of 5mhz is supported for quickly
reading data.

After initializing the SPI interface you'll need to also setup the chip select line as a
standard digital output (https://adafru.it/qhF). Run the following command to make a
digital output for the chip select line and set it to a high value:

cs = machine.Pin(15, machine.Pin.OUT)
cs.high()

©Adafruit Industries Page 8 of 12


For the MAX31855 it will send data only when the chip select line is low. Check your
device's datasheet to see if it has a chip select line and how it expects the line to be
driven.

Read SPI Data


You can read SPI data using the read or readinto functions on the SPI interface
object.

For the MAX31855 sensor it has a very simple interface where you read 4 bytes of
data (32 bits total) to get the current temperature reading and other sensor state.
Remember before the chip will respond it needs to have the chip select line driven
low. Run the following commands to toggle chip select low, read 4 bytes, and then
set chip select back to a high level:

cs.low()
data = spi.read(4)
cs.high()

pyboard note: On the pyboard the SPI interface currently uses the recv function name
instead of read.

The read function takes one parameter which is the total number of bytes to read
from the SPI interface. The board will drive the clock line appropriately and listen for
incoming data on the MISO line, then return a byte array with the received data.

An alternate way to read data is with the readinto function. This function takes in a
buffer of bytes you create ahead of time and will fill the buffer with received data.
Using a buffer you create can help save memory and increase performance because
MicroPython doesn't have to dynamically create a result buffer like with the read
function above.

For example to use readinto to read the sensor you would run:

data = bytearray(4)
cs.low()
spi.readinto(data)
cs.high()

©Adafruit Industries Page 9 of 12


micro:bit note: The micro:bit doesn't currently support the readinto function, instead
you'll have to use read.

If you're reading SPI data continually in a loop consider using readinto instead of
read. By creating and managing the buffer of received data yourself it can speed up
the program and reduce memory usage.

Now that the data is received you can run the following commands to print out its
value in hexadecimal:

import ubinascii
ubinascii.hexlify(data)

This will print the 4 received bytes as a hex string, like:

b'016c17e0'

If you only see zeros make sure the MAX31855 is connected exactly as shown above.
Most likely the MISO line is not connected, or the MAX31855 isn't powered up.

The read and readinto functions are all you really need to read SPI data with
MicroPython. After reading the raw data it's up to you to interpret it appropriately.

For the MAX31855 its datasheet (https://adafru.it/rfU) specifies the format of the
received 32 bits and how to get the thermocouple temperature out of them. You can
actually make a helper function to do this conversion from the raw data:

def temp_c(data):
temp = data[0] << 8 | data[1]
if temp & 0x0001:
return float('NaN') # Fault reading data.
temp >>= 2
if temp & 0x2000:
temp -= 16384 # Sign bit set, take 2's compliment.
return temp * 0.25

©Adafruit Industries Page 10 of 12


This function just pulls out the 14 bits of signed temperature data from the received
bytes. It also checks if a fault bit is set and returns a 'not a number' result to indicate
a problem.

Now try calling the temp_c function on the previously received data:

temp_c(data)

You should see a temperature in degrees Celsius printed!

Try holding the thermocouple tip with your hand and taking another reading
(remember toggle the CS line low, then read 4 bytes, and toggle CS back high), then
print the result with the temp_c function again. You should see a higher temperature
from your hand heating the thermocouple!

Write & Transfer SPI Data


You can write SPI data using the write and write_readinto functions on the SPI
interface object. The MAX31855 doesn't actually read any data written over SPI (it
has no data input line!), but for completeness you can see how to write SPI data
below.

To simply write out an array of bytes send them to the write function on the SPI
interface:

spi.write(b'1234')

pyboard note: On the pyboard the SPI interface currently uses the send function
name instead of write.

This will write the 4 byte string '1234' (actually the ASCII byte values of each
character) out the MOSI line of the board (GPIO13 on the ESP8266).

©Adafruit Industries Page 11 of 12


You can also write data while at the same time reading data from the MISO line. This
operation is sometimes called a 'transfer' in the SPI protocol and MicroPython
implements it with the write_readinto function. For example to write a 4 byte string
and read 4 bytes at the same time you can call:

data = bytearray(4)
spi.write_readinto(b'1234', data)

pyboard note: On the pyboard the SPI interface uses the send_recv function which
returns data like the read/recv function instead of populating a buffer.

This will write the same 4 byte string '1234' out the MOSI line, while at the same time
reading data on the MISO line and saving it into the provided buffer.

That's all there is to writing SPI data with MicroPython!

SPI Secondary
The examples in this guide are no longer supported and may not work. We are
only supporting CircuitPython on our boards. For more information about using
CircuitPython, check out the CircuitPython Essentials: https://learn.adafruit.com/
circuitpython-essentials/circuitpython-essentials

SPI secondary device support allows a board to act as a device that's controlled by a
SPI main. This is handy if you need a device to look like a SPI peripheral, or if you
want to control multiple devices from one main device. Each device can act as a SPI
secondary and the main can send and receive data with them as necessary.

In MicroPython SPI secondary support is still in development for some boards. The
ESP8266 port in particular does not currently support SPI secondary mode. This
guide won't go into detail about SPI secondary support, instead check your board's
documentation (https://adafru.it/pXc) to see if it has SPI secondary support and learn
about its usage.

©Adafruit Industries Page 12 of 12

You might also like