8000 docs: More revisions I2C & SPI. · boneskull/circuitpython@4032812 · GitHub
[go: up one dir, main page]

Skip to content

Commit 4032812

Browse files
committed
docs: More revisions I2C & SPI.
1 parent c3dda4b commit 4032812

File tree

1 file changed

+195
-24
lines changed

1 file changed

+195
-24
lines changed

docs/programming_guide/03_i2c_spi.rst

Lines changed: 195 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,9 @@ very common serial protocols, I2C and SPI.
1313
I2C Devices
1414
-----------
1515

16+
I2C Protocol
17+
^^^^^^^^^^^^
18+
1619
The I2C, or `inter-integrated circuit <https://en.wikipedia.org/wiki/I²C>`_,
1720
protocol is one example of a serial protocol for devices to communicate with one
1821
another. I2C is a serial protocol because it has a clock line and single data
@@ -22,7 +25,7 @@ serial protocols I2C has some interesting properties:
2225
- The I2C protocol only uses 2 wires to send and receive data. One line is a clock, called SCL, which pulses high and low to drive the sending and receiving of bits. The other line is the data line, called SDA, which contains the value of a sent or received bit during clock line transitions.
2326
- Multiple I2C devices can be connected to the same clock and data lines. This means you can have many different sensors and devices all connected to the same couple pins from your development board. The I2C protocol uses a 7-bit address assigned to each device as a way for the development board to talk to a specific device. As a result of using 7-bit addresses the I2C protocol is limited to 127 unique devices connected to one bus (or pair of data and clock lines).
2427
- The speed of the I2C bus is fixed, typically to 100khz, 400khz, or 1mhz. This means I2C is a good protocol for talking to devices that don't send a lot of data or need very fast responses. A TFT display which receives hundreds of kilobytes and even megabytes of image data wouldn't make sense as an I2C device because sending so much data over a 100khz bus would be quite slow. However a small sensor like a temperature or light sensor that sends a small 16 or 32-bit value typically doesn't need a fast bus.
25-
- The I2C clock and data lines need pull-up resistors to prevent from floating to random values. Since many different devices can share these lines the I2C protocol requires that each device 'give up' or stop driving the lines when not in use. If no device is driving the lines then the pull-up resistors ensure they go up to a high logic level instead of floating at random values. Most I2C device boards (in particular the boards Adafruit creates) have these pull-up resistors built-in, but if you're talking to a chip or building a board yourself you might need to add ~10 kilo-ohm resistors connected from both data and clock lines up to high logic level.
28+
- The I2C clock and data lines need pull-up resistors to prevent from floating to random values. Since many different devices can share these lines the I2C protocol requires that each device 'give up' or stop driving the lines when not in use. If no device is driving the lines then the pull-up resistors ensure they go up to a high logic level instead of floating at random values. Most I2C device boards (in particular the boards Adafruit creates) have these pull-up resistors built-in, but if you're talking to a chip or building a board yourself you might need to add ~2.2-10 kilo-ohm resistors connected from both data and clock lines up to high logic level.
2629
- The I2C protocol includes a simple guarantee that data has been transferred between devices. When one I2C device receives data from another device it uses a special acknowledgement bit to tell the sending device that data has been received. There's no error correction, parity checks, etc.--just a simple yes/no that data has been successfully sent and received.
2730
- Typically one device on an I2C bus is the 'master' which controls the clock line and sends requests to other connected devices. In most cases your development board is the master device that drives the I2C bus clock. Sensors and other I2C devices connected to the bus listen for requests from the master and respond appropriately. This guide covers this most common scenario where your development board is the I2C master and is talking to connected devices.
2831
- Many I2C devices expose data through a simple register table. This means to query data from the device you need to know both the address of the device and the address of the register you wish to query. Check your device's datasheet for the exact device and register address values. Typically registers are 8-bit values (0 to 255) but devices are free to use larger or smaller sizes--always check your device's datasheet to be sure how it exposes data!
@@ -33,6 +36,9 @@ can all be connected to the same I2C clock and data lines. By giving each
3336
sensor a unique 7-bit address your development board and code can query each one
3437
for their current value.
3538

39+
MCP9808 I2C Temperature Sensor
40+
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
41+
3642
To demonstrate interacting with an I2C device this guide will show you how to
3743
query the temperature from a MCP9808 high precision temperature sensor. This
3844
sensor is a good example of an I2C device because it has a very simple register
@@ -56,7 +62,7 @@ Remember the I2C protocol requires pull-up resistors to be on the clock and data
5662
lines. If you're using an Adafruit breakout board like the MCP9808 sensor
5763
linked above then these pull-ups are built-in and nothing else is necessary.
5864
However if you're wiring a chip directly to your board or using a differnet
59-
breakout you might need to add pull-up resistors. Typically these are 4.7k -
65+
breakout you might need to add pull-up resistors. Typically these are 2.2k -
6066
10k ohm resistors that connect both clock and data up to high logic / 3.3V.
6167

6268
Once the device is wired up you're ready to start interacting with it from
@@ -208,6 +214,91 @@ transactions of almost unlimited complexity. Most devices will use the basic
208214
write register, read bytes flow you saw here, but be sure to check your device's
209215
datasheet in case it has different I2C protocol requirements.
210216

217+
I2CDevice Library
218+
^^^^^^^^^^^^^^^^^
219+
220+
You saw above how to interact with an I2C device using the API built-in to
221+
CircuitPython. Remember using the built-in API requires careful management of
222+
the lock and unlock functions to access the I2C bus. If you're writing code to
223+
talk to an I2C device you might find using the `CircuitPython bus device library
224+
<https://github.com/adafruit/Adafruit_CircuitPython_BusDevice>`_ a bit easier to
225+
manage as it controls locking and unlocking automatically (using Python's
226+
context manager with statement).
227+
228+
To use the bus device library you'll first need to install the library on your
229+
board. If you're using a board with external flash, like the Circuit Playground
230+
Express or Feather/Metro M0 Express, you can install the CircuitPython bundle
231+
which includes the bus device and other useful libraries. You can install this
232+
bundle by following the `instructions on the release page
233+
<https://github.com/adafruit/Adafruit_CircuitPython_Bundle/releases>`_. Just
234+
unzip the bundle release .zip and drag the lib folder onto your board's
235+
CIRCUITPY drive.
236+
237+
For boards without external flash, like the Trinket M0 and Gemma M0, you'll need
238+
to manually install the bus device library. Like the `Trinket M0 guide mentions
239+
<https://learn.adafruit.com/adafruit-trinket-m0-circuitpython-arduino/installing-libraries>`_,
240+
to install libraries on these boards you have to pick and choose which libraries
241+
to copy into the lib folder. This is because these smaller boards don't have
242+
enough storage space to copy over the entire bundle. Make sure to copy over the
243+
**adafruit_bus_device** folder from inside lib to the lib folder of your board's
244+
CIRCUITPY drive.
245+
246+
Once you have the bus device library installed you can use the `I2CDevice class
247+
<http://circuitpython.readthedocs.io/projects/bus_device/en/latest/adafruit_bus_device/#adafruit_bus_device.i2c_device.I2CDevice>`_
248+
to simplify access to a device on the I2C device bus. First setup the I2C bus
249+
exactly as you did before:
250+
251+
>>> import board
252+
>>> import busio
253+
>>> i2c = busio.I2C(board.SCL, board.SDA)
254+
255+
Now import the bus device module and create an instance of the I2CDevice class.
256+
Notice the I2CDevice class needs to be told both the I2C bus object, and the
257+
address of the I2C device to talk to (0x18 for the MCP9808 sensor here):
258+
259+
>>> from adafruit_bus_device.i2c_device import I2CDevice
260+
>>> device = I2CDevice(i2c, 0x18)
261+
262+
At this point you can use similar functions to read and write data on the I2C
263+
bus to interact with the I2CDevice. The important difference here is that the
264+
read and write functions on the I2CDevice object will remember and automatically
265+
send the right device address. In addition you can use Python's with statement
266+
as a context manager to automatically lock and unlock the I2C bus.
267+
268+
Here's how to read the temperature register using the I2CDevice:
269+
270+
>>> with device:
271+
... device.write(bytes([0x05]), stop=False)
272+
... result = bytearray(2)
273+
... device.read_into(result)
274+
...
275+
>>> result
276+
bytearray(b'\xc1s')
277+
>>> temp_c(result)
278+
23.1875
279+
280+
Notice you no longer need to specify the address of the device (0x18) when
281+
reading and writing. The with statement is also automatically locking and
282+
unlocking the I2C bus so you don't need to manage the locking yourself either.
283+
284+
The only limitation of the I2CDevice class is that it needs to talk to a single
285+
device and can't scan the entire bus or interact with multiple devices (instead
286+
create multiple I2CDevice instances!). If you're writing code to interact with
287+
an I2C device it's highly recommended to use the I2CDevice class!
288+
289+
Also for interacting with most sensors and devices you typically don't need to
290+
write these low-level direct I2C bus manipulation requests (with either the
291+
built-in APIs or I2CDevice class). Instead look for a higher level library to
292+
interact with the device, like the `CircuitPython MCP9808 library
293+
<https://github.com/adafruit/Adafruit_CircuitPython_MCP9808>`_. Using a library
294+
saves you the work of writing this low-level I2C code and instead you can
295+
interact with simple temperature and other device properties. However it is
296+
handy to know how to write low-level I2C transactions in case you're dealing
297+
with devices that don't yet have a driver available!
298+
299+
Scan All Registers
300+
^^^^^^^^^^^^^^^^^^
301+
211302
An interesting property of most I2C devices is that they expose data with simple
212303
registers. Like you saw above with the MCP9808 sensor the register 0x05 held
213304
the temperature as 2 bytes of data. It's sometimes handy to scan all of the
@@ -266,18 +357,12 @@ For example with the MCP9808 you might see output like::
266357
Address 0xb: 0x25 0x88
267358
Address 0xc: 0x0 0x1
268359

269-
Also for interacting with most sensors and devices you typically don't need to
270-
write these low-level direct I2C bus manipulation requests. Instead look for a
271-
higher level library to interact with the device, like the `CircuitPython
272-
MCP9808 library <https://github.com/adafruit/Adafruit_CircuitPython_MCP9808>`_.
273-
Using a library saves you the work of writing this low-level I2C code and
274-
instead you can interact with simple temperature and other device properties.
275-
However it is handy to know how to write low-level I2C transactions in case
276-
you're dealing with devices that don't yet have a driver available!
277-
278360
SPI Devices
279361
-----------
280362

363+
SPI Protocol
364+
^^^^^^^^^^^^
365+
281366
The SPI protocol, or `serial peripheral interface
282367
<https://en.wikipedia.org/wiki/Serial_Peripheral_Interface_Bus>`_, is another
283368
example of a serial protocol for two devices to send and receive data. The big
@@ -297,6 +382,9 @@ Compared to I2C the SPI protocol has some interesting properties:
297382
- SPI devices have different requirements for speed (sometimes called baudrate), polarity, and phase. The `SPI page on Wikipedia <https://en.wikipedia.org/wiki/Serial_Peripheral_Interface_Bus>`_ has a good description of what polarity and phase mean--they control how the data is sent and received over the MISO and MOSI lines. Different polarity values control if a digital high or low logic level means a bit is a one or zero. Similarly different phase values control when data is read and written by devices--either with the rising or falling edge of the clock line. The important thing to know about phase and polarity is that each device has its own requirement for setting them so be sure to check your device's datasheet. Many devices are 'mode 0' which means a polarity and phase of 0 but watch out because some devices use different modes.
298383
- Like with I2C the basic operations are reading and writing bits and bytes of data over the data lines. However unlike SPI there is no guarantee or check that a connected device received or sent data successfully. Sometimes chips have extra lines to watch for an acknowledgment, but sometimes they don't and the SPI requests are 'fire and forget' with no guarantee they were received.
299384

385+
MAX31855 SPI Thermocouple Temperature Sensor
386+
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
387+
300388
To demonstrate interacting with a SPI device this guide will show you how to
301389
query the temperature from a MAX31855 thermocouple temperature sensor. This
302390
sensor is a good example of an SPI device because it has a very simple
@@ -441,14 +529,95 @@ example of a complete sensor read with the try-finally syntax:
441529
bytearray(b'\x01\xa8\x1a\xf0')
442530

443531
That's all there is to the basics of reading and writing data with the SPI
444-
protocol! Just like with I2C you typically don't need to go straight to these
445-
low-level SPI protocol requests, instead look for a library to interface with
446-
your hardware. In this case the `CircuitPython MAX31855 library
447-
<https://github.com/adafruit/Adafruit_CircuitPython_MAX31855>`_ is exactly what
448-
you want to use to talk to this thermocouple sensor. Using a library simplifies
449-
access to the sensor data and saves you from writing all the complex SPI
450-
transaction code. However if your device doesn't have a library you might need
451-
to interface with it directly using code like the above!
532+
protocol and the built-in SPI APIs of CircuitPython. However just like with I2C
533+
there's a handy SPIDevice library that can simplify talking to SPI devices.
534+
535+
SPIDevice Library
536+
^^^^^^^^^^^^^^^^^
537+
538+
You saw above how to interact with a SPI device using the API built-in to
539+
CircuitPython. Remember using the built-in API requires careful management of
540+
the lock and unlock functions to access the SPI bus, and explicit manipulation
541+
of the chip select line for a device. If you're writing code to talk to a SPI
542+
device you might find using the `CircuitPython bus device library
543+
<https://github.com/adafruit/Adafruit_CircuitPython_BusDevice>`_ a bit easier to
544+
manage as it controls locking & unlocking, and the chip select line
545+
automatically (using Python's context manager with statement).
546+
547+
To use the bus device library you'll first need to install the library on your
548+
board. If you're using a board with external flash, like the Circuit Playground
549+
Express or Feather/Metro M0 Express, you can install the CircuitPython bundle
550+
which includes the bus device and other useful libraries. You can install this
551+
bundle by following the `instructions on the release page
552+
<https://github.com/adafruit/Adafruit_CircuitPython_Bundle/releases>`_. Just
553+
unzip the bundle release .zip and drag the lib folder onto your board's
554+
CIRCUITPY drive.
555+
556+
For boards without external flash, like the Trinket M0 and Gemma M0, you'll need
557+
to manually install the bus device library. Like the `Trinket M0 guide mentions
558+
<https://learn.adafruit.com/adafruit-trinket-m0-circuitpython-arduino/installing-libraries>`_,
559+
to install libraries on these boards you have to pick and choose which libraries
560+
to copy into the lib folder. This is because these smaller boards don't have
561+
enough storage space to copy over the entire bundle. Make sure to copy over the
562+
**adafruit_bus_device** folder from inside lib to the lib folder of your board's
563+
CIRCUITPY drive.
564+
565+
Once you have the bus device library installed you can use the `SPIDevice class
566+
<http://circuitpython.readthedocs.io/projects/bus_device/en/latest/adafruit_bus_device/#adafruit_bus_device.spi_device.SPIDevice>`_
567+
to simplify access to a device on the SPI bus. First setup the SPI bus and CS
568+
line exactly as you did before:
569+
570+
>>> import board
571+
>>> import busio
572+
>>> import digitalio
573+
>>> spi = busio.SPI(board.SCK, MISO=board.MISO)
574+
>>> cs = digitalio.DigitalInOut(board.D2)
575+
576+
Now import the bus device module and create an instance of the SPIDevice class.
577+
Notice the SPIDevice class needs to be told the SPI bus, chip select line,
578+
baudrate, polarity, and phase of the SPI connection. These details will be
579+
remembered by the SPIDevice class so it can automatically lock and configure the
580+
bus appropriately (again using Python's with statement and a context manager):
581+
582+
>>> from adafruit_bus_device.spi_device import SPIDevice
583+
>>> device = SPIDevice(spi, cs, baudrate=5000000, polarity=0, phase=0)
584+
585+
At this point you're ready to interact with the SPI device instance using the
586+
same read and write functions as before. However this time you'll put your code
587+
in a with statement context manager and it will automatically lock the bus,
588+
assert the CS line, configure the SPI bus, run your commands, deassert the CS
589+
line, and unlock the bus when done:
590+
591+
>>> with device:
592+
... result = bytearray(4)
593+
... spi.readinto(result)
594+
...
595+
>>> result
596+
bytearray(b'\x01\xa8\x1a\xf0')
597+
>>> temp_c(result)
598+
26.5
599+
600+
Notice you didn't need to call configure or even change the CS line from high to
601+
low and back. The SPIDevice class takes care of all these details for you
602+
automatically! You can even call the write function just like on the SPI bus
603+
directly and data will be written out the MOSI line.
604+
605+
One important thing to note is that the CS line is asserted for the *entire*
606+
with statement block, so if you need to make two different transactions be sure
607+
to put them in their own with statement blocks. Another thing to note with the
608+
SPI device class is that it currently only supports devices with a chip select
609+
(it is not optional) and whose chip select is asserted with a low logic signal.
610+
Devices asserted with a high logic level are rare and uncommon so the SPI device
611+
class should cover most needs.
612+
613+
Just like with I2C you typically don't need to go straight to these low-level
614+
SPI protocol requests (using built-in APIs or the SPIDevice class), instead look
615+
for a library to interface with your hardware. In this case the `CircuitPython
616+
MAX31855 library <https://github.com/adafruit/Adafruit_CircuitPython_MAX31855>`_
617+
is exactly what you want to use to talk to this thermocouple sensor. Using a
618+
library simplifies access to the sensor data and saves you from writing all the
619+
complex SPI transaction code. However if your device doesn't have a library you
620+
might need to interface with it directly using code like the above!
452621

453622
Software SPI & I2C
454623
^^^^^^^^^^^^^^^^^^
@@ -527,11 +696,13 @@ SPI bus!
527696

528697
>>> spi.unlock()
529698

530-
You can do the exact same software 'bit-bang' trick with the I2C protocol too.
531-
Use the :py:class:`bitbangio.I2C` class from the :py:mod:`bitbangio` module in
532-
place of the :py:class:`busio.I2C` class. The interface between the two classes
533-
is the same so you just change how you import and create the I2C interface, for
534-
example:
699+
Don't forget you can even use the SPIDevice library with the bit-bang I2C bus!
700+
701+
You can do the exact same software 'bit-bang' trick with the I2C protocol too
702+
(even using the I2CDevice class). Use the :py:class:`bitbangio.I2C` class from
703+
the :py:mod:`bitbangio` module in place of the :py:class:`busio.I2C` class. The
704+
interface between the two classes is the same so you just change how you import
705+
and create the I2C interface, for example:
535706

536707
>>> import board
537708
>>> import bitbangio

0 commit comments

Comments
 (0)
0