Coverage for /usr/lib/python3/dist-packages/gpiozero/spi_devices.py: 34%
161 statements
« prev ^ index » next coverage.py v7.2.7, created at 2024-02-10 12:38 +0000
« prev ^ index » next coverage.py v7.2.7, created at 2024-02-10 12:38 +0000
1# vim: set fileencoding=utf-8:
2#
3# GPIO Zero: a library for controlling the Raspberry Pi's GPIO pins
4#
5# Copyright (c) 2016-2021 Dave Jones <dave@waveform.org.uk>
6# Copyright (c) 2020 Grzegorz Szymaszek <gszymaszek@short.pl>
7# Copyright (c) 2016-2019 Andrew Scheller <github@loowis.durge.org>
8# Copyright (c) 2016-2018 Ben Nuttall <ben@bennuttall.com>
9#
10# SPDX-License-Identifier: BSD-3-Clause
12from __future__ import (
13 unicode_literals,
14 print_function,
15 absolute_import,
16 division,
17 )
18str = type('')
21from math import log, ceil
22from operator import or_
23try:
24 from functools import reduce
25except ImportError:
26 pass # py2's reduce is built-in
28from .exc import DeviceClosed, SPIBadChannel, InputDeviceError
29from .devices import Device
32class SPIDevice(Device):
33 """
34 Extends :class:`Device`. Represents a device that communicates via the SPI
35 protocol.
37 See :ref:`spi_args` for information on the keyword arguments that can be
38 specified with the constructor.
39 """
40 def __init__(self, **spi_args):
41 self._spi = None
42 super(SPIDevice, self).__init__(
43 pin_factory=spi_args.pop('pin_factory', None)
44 )
45 self._spi = self.pin_factory.spi(**spi_args)
47 def close(self):
48 if getattr(self, '_spi', None):
49 self._spi.close()
50 self._spi = None
51 super(SPIDevice, self).close()
53 @property
54 def closed(self):
55 return self._spi is None
57 def _int_to_words(self, pattern):
58 """
59 Given a bit-pattern expressed an integer number, return a sequence of
60 the individual words that make up the pattern. The number of bits per
61 word will be obtained from the internal SPI interface.
62 """
63 try:
64 bits_required = int(ceil(log(pattern, 2))) + 1
65 except ValueError:
66 # pattern == 0 (technically speaking, no bits are required to
67 # transmit the value zero ;)
68 bits_required = 1
69 shifts = range(0, bits_required, self._spi.bits_per_word)[::-1]
70 mask = 2 ** self._spi.bits_per_word - 1
71 return [(pattern >> shift) & mask for shift in shifts]
73 def _words_to_int(self, words, expected_bits=None):
74 """
75 Given a sequence of words which each fit in the internal SPI
76 interface's number of bits per word, returns the value obtained by
77 concatenating each word into a single bit-string.
79 If *expected_bits* is specified, it limits the size of the output to
80 the specified number of bits (by masking off bits above the expected
81 number). If unspecified, no limit will be applied.
82 """
83 if expected_bits is None:
84 expected_bits = len(words) * self._spi.bits_per_word
85 shifts = range(0, expected_bits, self._spi.bits_per_word)[::-1]
86 mask = 2 ** expected_bits - 1
87 return reduce(or_, (word << shift for word, shift in zip(words, shifts))) & mask
89 def __repr__(self):
90 try:
91 self._check_open()
92 return "<gpiozero.%s object using %r>" % (self.__class__.__name__, self._spi)
93 except DeviceClosed:
94 return "<gpiozero.%s object closed>" % self.__class__.__name__
97class AnalogInputDevice(SPIDevice):
98 """
99 Represents an analog input device connected to SPI (serial interface).
101 Typical analog input devices are `analog to digital converters`_ (ADCs).
102 Several classes are provided for specific ADC chips, including
103 :class:`MCP3004`, :class:`MCP3008`, :class:`MCP3204`, and :class:`MCP3208`.
105 The following code demonstrates reading the first channel of an MCP3008
106 chip attached to the Pi's SPI pins::
108 from gpiozero import MCP3008
110 pot = MCP3008(0)
111 print(pot.value)
113 The :attr:`value` attribute is normalized such that its value is always
114 between 0.0 and 1.0 (or in special cases, such as differential sampling,
115 -1 to +1). Hence, you can use an analog input to control the brightness of
116 a :class:`PWMLED` like so::
118 from gpiozero import MCP3008, PWMLED
120 pot = MCP3008(0)
121 led = PWMLED(17)
122 led.source = pot
124 The :attr:`voltage` attribute reports values between 0.0 and *max_voltage*
125 (which defaults to 3.3, the logic level of the GPIO pins).
127 .. _analog to digital converters: https://en.wikipedia.org/wiki/Analog-to-digital_converter
128 """
130 def __init__(self, bits, max_voltage=3.3, **spi_args):
131 if bits is None:
132 raise InputDeviceError('you must specify the bit resolution of the device')
133 self._bits = bits
134 self._min_value = -(2 ** bits)
135 self._range = 2 ** (bits + 1) - 1
136 if max_voltage <= 0:
137 raise InputDeviceError('max_voltage must be positive')
138 self._max_voltage = float(max_voltage)
139 super(AnalogInputDevice, self).__init__(shared=True, **spi_args)
141 @property
142 def bits(self):
143 """
144 The bit-resolution of the device/channel.
145 """
146 return self._bits
148 def _read(self):
149 raise NotImplementedError
151 @property
152 def value(self):
153 """
154 The current value read from the device, scaled to a value between 0 and
155 1 (or -1 to +1 for certain devices operating in differential mode).
156 """
157 return (2 * (self._read() - self._min_value) / self._range) - 1
159 @property
160 def raw_value(self):
161 """
162 The raw value as read from the device.
163 """
164 return self._read()
166 @property
167 def max_voltage(self):
168 """
169 The voltage required to set the device's value to 1.
170 """
171 return self._max_voltage
173 @property
174 def voltage(self):
175 """
176 The current voltage read from the device. This will be a value between
177 0 and the *max_voltage* parameter specified in the constructor.
178 """
179 return self.value * self._max_voltage
182class MCP3xxx(AnalogInputDevice):
183 """
184 Extends :class:`AnalogInputDevice` to implement an interface for all ADC
185 chips with a protocol similar to the Microchip MCP3xxx series of devices.
186 """
188 def __init__(self, channel=0, bits=10, differential=False, max_voltage=3.3,
189 **spi_args):
190 self._channel = channel
191 self._differential = bool(differential)
192 super(MCP3xxx, self).__init__(bits, max_voltage, **spi_args)
194 @property
195 def channel(self):
196 """
197 The channel to read data from. The MCP3008/3208/3304 have 8 channels
198 (0-7), while the MCP3004/3204/3302 have 4 channels (0-3), the
199 MCP3002/3202 have 2 channels (0-1), and the MCP3001/3201/3301 only
200 have 1 channel.
201 """
202 return self._channel
204 @property
205 def differential(self):
206 """
207 If ``True``, the device is operated in differential mode. In this mode
208 one channel (specified by the channel attribute) is read relative to
209 the value of a second channel (implied by the chip's design).
211 Please refer to the device data-sheet to determine which channel is
212 used as the relative base value (for example, when using an
213 :class:`MCP3008` in differential mode, channel 0 is read relative to
214 channel 1).
215 """
216 return self._differential
218 def _read(self):
219 return self._words_to_int(
220 self._spi.transfer(self._send())[-2:], self.bits
221 )
223 def _send(self):
224 # MCP3004/08 protocol looks like the following:
225 #
226 # Byte 0 1 2
227 # ==== ======== ======== ========
228 # Tx 00000001 MCCCxxxx xxxxxxxx
229 # Rx xxxxxxxx xxxxx0RR RRRRRRRR
230 #
231 # MCP3204/08 protocol looks like the following:
232 #
233 # Byte 0 1 2
234 # ==== ======== ======== ========
235 # Tx 000001MC CCxxxxxx xxxxxxxx
236 # Rx xxxxxxxx xxx0RRRR RRRRRRRR
237 #
238 # The transmit bits start with several preamble "0" bits, the number
239 # of which is determined by the amount required to align the last byte
240 # of the result with the final byte of output. A start "1" bit is then
241 # transmitted, followed by the single/differential bit (M); 1 for
242 # single-ended read, 0 for differential read. Next comes three bits for
243 # channel (C).
244 #
245 # Read-out begins with a don't care bit (x), then a null bit (0)
246 # followed by the result bits (R). All other bits are don't care (x).
247 #
248 # The 3x01 variant of the chips always operates in differential mode
249 # and effectively only has one channel (composed of an IN+ and IN-). As
250 # such it requires no input, just output.
251 return self._int_to_words(
252 (0b10000 | (not self.differential) << 3 | self.channel) << (self.bits + 2)
253 )
256class MCP3xx2(MCP3xxx):
257 def _send(self):
258 # MCP3002 protocol looks like the following:
259 #
260 # Byte 0 1
261 # ==== ======== ========
262 # Tx 01MCLxxx xxxxxxxx
263 # Rx xxxxx0RR RRRRRRRR for the 3002
264 #
265 # MCP3202 protocol looks like the following:
266 #
267 # Byte 0 1 2
268 # ==== ======== ======== ========
269 # Tx 00000001 MCLxxxxx xxxxxxxx
270 # Rx xxxxxxxx xxx0RRRR RRRRRRRR
271 #
272 # The transmit bits start with several preamble "0" bits, the number of
273 # which is determined by the amount required to align the last byte of
274 # the result with the final byte of output. A start "1" bit is then
275 # transmitted, followed by the single/differential bit (M); 1 for
276 # single-ended read, 0 for differential read. Next comes a single bit
277 # for channel (C) then the MSBF bit (L) which selects whether the data
278 # will be read out in MSB form only (1) or whether LSB read-out will
279 # occur after MSB read-out (0).
280 #
281 # Read-out begins with a null bit (0) followed by the result bits (R).
282 # All other bits are don't care (x).
283 return self._int_to_words(
284 (0b1001 | (not self.differential) << 2 | self.channel << 1) << (self.bits + 1)
285 )
288class MCP30xx(MCP3xxx):
289 """
290 Extends :class:`MCP3xxx` to implement an interface for all ADC
291 chips with a protocol similar to the Microchip MCP30xx series of devices.
292 """
294 def __init__(self, channel=0, differential=False, max_voltage=3.3,
295 **spi_args):
296 super(MCP30xx, self).__init__(channel, 10, differential, max_voltage,
297 **spi_args)
300class MCP32xx(MCP3xxx):
301 """
302 Extends :class:`MCP3xxx` to implement an interface for all ADC
303 chips with a protocol similar to the Microchip MCP32xx series of devices.
304 """
306 def __init__(self, channel=0, differential=False, max_voltage=3.3, **spi_args):
307 super(MCP32xx, self).__init__(channel, 12, differential, max_voltage,
308 **spi_args)
311class MCP33xx(MCP3xxx):
312 """
313 Extends :class:`MCP3xxx` with functionality specific to the MCP33xx family
314 of ADCs; specifically this handles the full differential capability of
315 these chips supporting the full 13-bit signed range of output values.
316 """
318 def __init__(self, channel=0, differential=False, max_voltage=3.3, **spi_args):
319 super(MCP33xx, self).__init__(channel, 12, differential, max_voltage,
320 **spi_args)
322 def _read(self):
323 if self.differential:
324 result = self._words_to_int(
325 self._spi.transfer(self._send())[-2:], self.bits + 1)
326 # Account for the sign bit
327 if result > 4095:
328 return -(8192 - result)
329 else:
330 return result
331 else:
332 return super(MCP33xx, self)._read()
334 def _send(self):
335 # MCP3302/04 protocol looks like the following:
336 #
337 # Byte 0 1 2
338 # ==== ======== ======== ========
339 # Tx 00001MCC Cxxxxxxx xxxxxxxx
340 # Rx xxxxxxxx xx0SRRRR RRRRRRRR
341 #
342 # The transmit bits start with 4 preamble bits "0000", a start bit "1"
343 # followed by the single/differential bit (M) which is 1 for
344 # single-ended read, and 0 for differential read, followed by 3-bits
345 # for the channel (C). The remainder of the transmission are "don't
346 # care" bits (x).
347 #
348 # The first byte received and the top 2 bits of the second byte are
349 # don't care bits (x). These are followed by a null bit (0), then the
350 # sign bit (S), and then the 12 result bits (R).
351 #
352 # In single read mode (the default) the sign bit is always zero and the
353 # result is effectively 12-bits. In differential mode, the sign bit is
354 # significant and the result is a two's-complement 13-bit value.
355 #
356 # The MCP3301 variant operates similarly to the other MCP3x01 variants;
357 # no input, just output and always differential.
358 return self._int_to_words(
359 (0b10000 | (not self.differential) << 3 | self.channel) << (self.bits + 3)
360 )
362 @property
363 def differential(self):
364 """
365 If ``True``, the device is operated in differential mode. In this mode
366 one channel (specified by the channel attribute) is read relative to
367 the value of a second channel (implied by the chip's design).
369 Please refer to the device data-sheet to determine which channel is
370 used as the relative base value (for example, when using an
371 :class:`MCP3304` in differential mode, channel 0 is read relative to
372 channel 1).
373 """
374 return super(MCP33xx, self).differential
376 @property
377 def value(self):
378 """
379 The current value read from the device, scaled to a value between 0 and
380 1 (or -1 to +1 for devices operating in differential mode).
381 """
382 return super(MCP33xx, self).value
385class MCP3001(MCP30xx):
386 """
387 The `MCP3001`_ is a 10-bit analog to digital converter with 1 channel.
388 Please note that the MCP3001 always operates in differential mode,
389 measuring the value of IN+ relative to IN-.
391 .. _MCP3001: http://www.farnell.com/datasheets/630400.pdf
392 """
393 def __init__(self, max_voltage=3.3, **spi_args):
394 super(MCP3001, self).__init__(0, True, max_voltage, **spi_args)
396 def _read(self):
397 # MCP3001 protocol looks like the following:
398 #
399 # Byte 0 1
400 # ==== ======== ========
401 # Rx xx0RRRRR RRRRRxxx
402 return self._words_to_int(self._spi.read(2), 13) >> 3
405class MCP3002(MCP30xx, MCP3xx2):
406 """
407 The `MCP3002`_ is a 10-bit analog to digital converter with 2 channels
408 (0-1).
410 .. _MCP3002: http://www.farnell.com/datasheets/1599363.pdf
411 """
412 def __init__(self, channel=0, differential=False, max_voltage=3.3, **spi_args):
413 if not 0 <= channel < 2:
414 raise SPIBadChannel('channel must be 0 or 1')
415 super(MCP3002, self).__init__(channel, differential, max_voltage, **spi_args)
418class MCP3004(MCP30xx):
419 """
420 The `MCP3004`_ is a 10-bit analog to digital converter with 4 channels
421 (0-3).
423 .. _MCP3004: http://www.farnell.com/datasheets/808965.pdf
424 """
425 def __init__(self, channel=0, differential=False, max_voltage=3.3, **spi_args):
426 if not 0 <= channel < 4:
427 raise SPIBadChannel('channel must be between 0 and 3')
428 super(MCP3004, self).__init__(channel, differential, max_voltage, **spi_args)
431class MCP3008(MCP30xx):
432 """
433 The `MCP3008`_ is a 10-bit analog to digital converter with 8 channels
434 (0-7).
436 .. _MCP3008: http://www.farnell.com/datasheets/808965.pdf
437 """
438 def __init__(self, channel=0, differential=False, max_voltage=3.3, **spi_args):
439 if not 0 <= channel < 8:
440 raise SPIBadChannel('channel must be between 0 and 7')
441 super(MCP3008, self).__init__(channel, differential, max_voltage, **spi_args)
444class MCP3201(MCP32xx):
445 """
446 The `MCP3201`_ is a 12-bit analog to digital converter with 1 channel.
447 Please note that the MCP3201 always operates in differential mode,
448 measuring the value of IN+ relative to IN-.
450 .. _MCP3201: http://www.farnell.com/datasheets/1669366.pdf
451 """
452 def __init__(self, max_voltage=3.3, **spi_args):
453 super(MCP3201, self).__init__(0, True, max_voltage, **spi_args)
455 def _read(self):
456 # MCP3201 protocol looks like the following:
457 #
458 # Byte 0 1
459 # ==== ======== ========
460 # Rx xx0RRRRR RRRRRRRx
461 return self._words_to_int(self._spi.read(2), 13) >> 1
464class MCP3202(MCP32xx, MCP3xx2):
465 """
466 The `MCP3202`_ is a 12-bit analog to digital converter with 2 channels
467 (0-1).
469 .. _MCP3202: http://www.farnell.com/datasheets/1669376.pdf
470 """
471 def __init__(self, channel=0, differential=False, max_voltage=3.3, **spi_args):
472 if not 0 <= channel < 2:
473 raise SPIBadChannel('channel must be 0 or 1')
474 super(MCP3202, self).__init__(channel, differential, max_voltage, **spi_args)
477class MCP3204(MCP32xx):
478 """
479 The `MCP3204`_ is a 12-bit analog to digital converter with 4 channels
480 (0-3).
482 .. _MCP3204: http://www.farnell.com/datasheets/808967.pdf
483 """
484 def __init__(self, channel=0, differential=False, max_voltage=3.3, **spi_args):
485 if not 0 <= channel < 4:
486 raise SPIBadChannel('channel must be between 0 and 3')
487 super(MCP3204, self).__init__(channel, differential, max_voltage, **spi_args)
490class MCP3208(MCP32xx):
491 """
492 The `MCP3208`_ is a 12-bit analog to digital converter with 8 channels
493 (0-7).
495 .. _MCP3208: http://www.farnell.com/datasheets/808967.pdf
496 """
497 def __init__(self, channel=0, differential=False, max_voltage=3.3, **spi_args):
498 if not 0 <= channel < 8:
499 raise SPIBadChannel('channel must be between 0 and 7')
500 super(MCP3208, self).__init__(channel, differential, max_voltage, **spi_args)
503class MCP3301(MCP33xx):
504 """
505 The `MCP3301`_ is a signed 13-bit analog to digital converter. Please note
506 that the MCP3301 always operates in differential mode measuring the
507 difference between IN+ and IN-. Its output value is scaled from -1 to +1.
509 .. _MCP3301: http://www.farnell.com/datasheets/1669397.pdf
510 """
511 def __init__(self, max_voltage=3.3, **spi_args):
512 super(MCP3301, self).__init__(0, True, max_voltage, **spi_args)
514 def _read(self):
515 # MCP3301 protocol looks like the following:
516 #
517 # Byte 0 1
518 # ==== ======== ========
519 # Rx xx0SRRRR RRRRRRRR
520 result = self._words_to_int(self._spi.read(2), 13)
521 # Account for the sign bit
522 if result > 4095:
523 return -(8192 - result)
524 else:
525 return result
528class MCP3302(MCP33xx):
529 """
530 The `MCP3302`_ is a 12/13-bit analog to digital converter with 4 channels
531 (0-3). When operated in differential mode, the device outputs a signed
532 13-bit value which is scaled from -1 to +1. When operated in single-ended
533 mode (the default), the device outputs an unsigned 12-bit value scaled from
534 0 to 1.
536 .. _MCP3302: http://www.farnell.com/datasheets/1486116.pdf
537 """
538 def __init__(self, channel=0, differential=False, max_voltage=3.3, **spi_args):
539 if not 0 <= channel < 4:
540 raise SPIBadChannel('channel must be between 0 and 4')
541 super(MCP3302, self).__init__(channel, differential, max_voltage, **spi_args)
544class MCP3304(MCP33xx):
545 """
546 The `MCP3304`_ is a 12/13-bit analog to digital converter with 8 channels
547 (0-7). When operated in differential mode, the device outputs a signed
548 13-bit value which is scaled from -1 to +1. When operated in single-ended
549 mode (the default), the device outputs an unsigned 12-bit value scaled from
550 0 to 1.
552 .. _MCP3304: http://www.farnell.com/datasheets/1486116.pdf
553 """
554 def __init__(self, channel=0, differential=False, max_voltage=3.3, **spi_args):
555 if not 0 <= channel < 8:
556 raise SPIBadChannel('channel must be between 0 and 7')
557 super(MCP3304, self).__init__(channel, differential, max_voltage, **spi_args)