mirror of
https://github.com/KevinMidboe/python-gpiozero.git
synced 2025-10-29 17:50:37 +00:00
Have made a simpler structure for MCP3008/3004 and MCP3208/3204.
The code is running on my Pi and seems to be stable Have added MCP3301/3302/3304 have implemented the "M" bit to allow Differential mode Have added an "absVal" for absolute values Have added a "relVal" for relative val from 0 to 1 (same as "value") left "value" for backwards compatabilety, but propse to delete it shifted Rx bits for MCP330x On branch master Your branch is up-to-date with 'origin/master'. Changes to be committed: modified: gpiozero/__init__.py modified: gpiozero/input_devices.py Untracked files: ZeroCombo11.py Date: Mon Jan 18 20:25:36 2016 -0500
This commit is contained in:
@@ -23,6 +23,11 @@ from .input_devices import (
|
||||
AnalogInputDevice,
|
||||
MCP3008,
|
||||
MCP3004,
|
||||
MCP3208,
|
||||
MCP3204,
|
||||
MCP3301,
|
||||
MCP3302,
|
||||
MCP3304,
|
||||
)
|
||||
from .output_devices import (
|
||||
OutputDevice,
|
||||
|
||||
@@ -508,13 +508,14 @@ class AnalogInputDevice(CompositeDevice):
|
||||
Represents an analog input device connected to SPI (serial interface).
|
||||
"""
|
||||
|
||||
def __init__(self, device=0, bits=None):
|
||||
def __init__(self, device=0, bits=None, mode=1):
|
||||
if bits is None:
|
||||
raise InputDeviceError('you must specify the bit resolution of the device')
|
||||
if device not in (0, 1):
|
||||
raise InputDeviceError('device must be 0 or 1')
|
||||
self._device = device
|
||||
self._bits = bits
|
||||
self._mode = mode
|
||||
self._spi = SpiDev()
|
||||
self._spi.open(0, self.device)
|
||||
super(AnalogInputDevice, self).__init__()
|
||||
@@ -551,53 +552,189 @@ class AnalogInputDevice(CompositeDevice):
|
||||
@property
|
||||
def value(self):
|
||||
"""
|
||||
A value read from the device. This will be a floating point value
|
||||
between 0 and 1 (scaled according to the number of bits supported by
|
||||
the device).
|
||||
The relative floating point value between 0 and 1
|
||||
(scaled according to the number of bits supported bythe device).
|
||||
"""
|
||||
return self._read() / (2**self._bits - 1)
|
||||
|
||||
@property
|
||||
def relVal(self):
|
||||
"""
|
||||
The relative floating point value between 0 and 1
|
||||
(scaled according to the number of bits supported bythe device).
|
||||
"""
|
||||
return self._read() / ((2**self._bits) - 1)
|
||||
|
||||
class MCP3008(AnalogInputDevice):
|
||||
def __init__(self, channel=0, device=0):
|
||||
if not 0 <= channel < 8:
|
||||
raise InputDeviceError('channel must be between 0 and 7')
|
||||
super(MCP3008, self).__init__(device=device, bits=10)
|
||||
@property
|
||||
def absVal(self):
|
||||
"""
|
||||
The absolute value as read from the device
|
||||
"""
|
||||
return self._read()
|
||||
|
||||
@property
|
||||
def mode(self):
|
||||
"""
|
||||
The device mode: single ended (1) or diferential (0)
|
||||
"""
|
||||
return self._mode()
|
||||
|
||||
|
||||
|
||||
class MCP3xxx(AnalogInputDevice):
|
||||
def __init__(self, channel=0, device=0, bits=10, mode=1): #default values
|
||||
if mode not in (0, 1):
|
||||
raise InputDeviceError('Mode must be 1 or 0')
|
||||
self._channel = channel
|
||||
|
||||
self._bits = bits
|
||||
self._mode = mode
|
||||
super(MCP3xxx, self).__init__(device=device, bits=bits, mode=mode)
|
||||
|
||||
@property
|
||||
def channel(self):
|
||||
"""
|
||||
The channel to read data from. The MCP3008 has 8 channels (so this will
|
||||
be between 0 and 7) while the MCP3004 has 4 channels (range 0 to 3).
|
||||
The channel to read data from. The MCP3008/3208/3304 have 8 channels (so this will
|
||||
be between 0 and 7) while the MCP3004/3204/3302 have 4 channels (range 0 to 3)and
|
||||
the MCP3301 only has 2 channels.
|
||||
"""
|
||||
return self._channel
|
||||
|
||||
@property
|
||||
def bits(self):
|
||||
"""
|
||||
The bit-resolution of the device/channel.
|
||||
"""
|
||||
return self._bits
|
||||
|
||||
@property
|
||||
def mode(self):
|
||||
"""
|
||||
The device mode: single ended (1) or diferential (0)
|
||||
"""
|
||||
return self._mode
|
||||
|
||||
|
||||
def _read(self):
|
||||
# MCP3008 protocol looks like the following:
|
||||
# MCP3008/04 or MCP3208/04 protocol looks like the following:
|
||||
#
|
||||
# Byte 0 1 2
|
||||
# ==== ======== ======== ========
|
||||
# Tx 00000001 MCCCxxxx xxxxxxxx
|
||||
# Rx xxxxxxxx xxxxx0RR RRRRRRRR
|
||||
# Tx 0001MCCC xxxxxxxx xxxxxxxx
|
||||
# Rx xxxxxxxx x0RRRRRR RRRRxxxx for the 3004/08
|
||||
# Rx xxxxxxxx x0RRRRRR RRRRRRxx for the 3204/08
|
||||
# Rx xxxxxxxx xx0RRRRR RRRRRRRR for the 3301/02/04
|
||||
#
|
||||
# The first byte sent is a start byte (1). The top bit of the second
|
||||
# holds the mode (M) which is 1 for single-ended read, and 0 for
|
||||
# differential read (we only support single here), followed by 3-bits
|
||||
# for the channel (C). The remainder of the transmission are "don't
|
||||
# care" bits (x).
|
||||
# The transmit bits start with 3 preamble bits "000" (to warm up),
|
||||
# a start bit "1" followed by the mode bit(M) which is 1 for
|
||||
# single-ended read, and 0 for differential read,
|
||||
# followed by 3-bits for the channel (C).
|
||||
# The remainder of the transmission are "don't care" bits (x).
|
||||
#
|
||||
# The first byte and the top 5 bits of the second byte received are
|
||||
# The first byte received and the top 1 bit of the second byte are
|
||||
# don't care bits (x). These are followed by a null bit (0), and then
|
||||
# the 10 bits of the result (R).
|
||||
data = self._spi.xfer2([1, (8 + self.channel) << 4, 0])
|
||||
return ((data[1] & 3) << 8) | data[2]
|
||||
# the result bits (R). 10 bits for the MCP300x, 12 bits for the MCP320x
|
||||
# and 13 bits for the MCP330x
|
||||
# Warning: The mode bit is a new implimentation and needs to be tested.
|
||||
|
||||
if self.mode:
|
||||
tx = 24 # '00011000' S bit 1 and M bit 1
|
||||
else:
|
||||
tx = 16 # '00010000' S bit 1 and M bit 0
|
||||
data = self._spi.xfer2([(tx + self.channel), 0, 0])
|
||||
if self.bits == 13:
|
||||
val = ((data[1] & 31) << (self.bits-5)) | (data[2] )
|
||||
else:
|
||||
val = ((data[1] & 63) << (self.bits-6)) | (data[2] >> (14 - self.bits))
|
||||
return (val)
|
||||
|
||||
|
||||
class MCP3004(MCP3008):
|
||||
def __init__(self, channel=0, device=0):
|
||||
# MCP3004 protocol is identical to MCP3008 but the top bit of the
|
||||
# channel number must be 0 (effectively restricting it to 4 channels)
|
||||
class MCP3004(MCP3xxx):
|
||||
"""
|
||||
The MCP3004 is a 10 bit Analog to Digital Converter with
|
||||
4 channels single ended or 2 channels diferential.
|
||||
The channel number must be 0, 1, 2 or 3
|
||||
"""
|
||||
def __init__(self, channel=0, device=0, mode=1):
|
||||
if not 0 <= channel < 4:
|
||||
raise InputDeviceError('channel must be between 0 and 3')
|
||||
super(MCP3004, self).__init__(channel, device)
|
||||
super(MCP3004, self).__init__(channel, device, bits=10, mode=mode)
|
||||
self._channel = channel
|
||||
self._mode = mode
|
||||
|
||||
class MCP3008(MCP3xxx):
|
||||
"""
|
||||
The MCP3208 is a 10 bit Analog to Digital Converter with
|
||||
8 channels single ended or 4 channels diferential.
|
||||
The channel number must be 0, 1, 2, 3, 4, 5, 6, 7 or 8
|
||||
"""
|
||||
def __init__(self, channel=0, device=0, mode=1):
|
||||
if not 0 <= channel < 8:
|
||||
raise InputDeviceError('channel must be between 0 and 7')
|
||||
super(MCP3008, self).__init__(device=device, bits=10, mode=mode)
|
||||
self._channel = channel
|
||||
self._mode = mode
|
||||
|
||||
class MCP3204(MCP3xxx):
|
||||
"""
|
||||
The MCP3204 is a 10 bit Analog to Digital Converter with
|
||||
4 channels single ended or 2 channels diferential.
|
||||
The channel number must be 0, 1, 2 or 3
|
||||
"""
|
||||
def __init__(self, channel=0, device=0, mode=1):
|
||||
if not 0 <= channel < 4:
|
||||
raise InputDeviceError('channel must be between 0 and 3')
|
||||
super(MCP3204, self).__init__(channel, device, bits=12, mode=mode)
|
||||
self._channel = channel
|
||||
self._mode = mode
|
||||
|
||||
class MCP3208(MCP3xxx):
|
||||
"""
|
||||
The MCP3208 is a 13 bit Analog to Digital Converter with
|
||||
8 channels single ended or 4 channels diferential.
|
||||
The channel number must be 0, 1, 2, 3, 4, 5, 6, 7 or 8
|
||||
"""
|
||||
def __init__(self, channel=0, device=0, mode=1):
|
||||
if not 0 <= channel < 8:
|
||||
raise InputDeviceError('channel must be between 0 and 7')
|
||||
super(MCP3208, self).__init__(device=device, bits=12, mode=mode)
|
||||
self._channel = channel
|
||||
self._mode = mode
|
||||
|
||||
class MCP3301(MCP3xxx):
|
||||
"""
|
||||
The MCP3301 is a 13 bit Analog to Digital Converter with
|
||||
2 channels single ended or 1 channel diferential.
|
||||
The channel number must be 0, or 1
|
||||
"""
|
||||
def __init__(self, channel=0, device=0, mode=1):
|
||||
if not 0 <= channel < 2:
|
||||
raise InputDeviceError('channel must be between 0 and 1')
|
||||
super(MCP3301, self).__init__(device=device, bits=13, mode=mode)
|
||||
self._channel = channel
|
||||
self._mode = mode
|
||||
|
||||
class MCP3302(MCP3xxx):
|
||||
"""
|
||||
The MCP3302 is a 13 bit Analog to Digital Converter with
|
||||
4 channels single ended or 2 channels diferential.
|
||||
The channel number must be 0, 1, 2 or 3
|
||||
"""
|
||||
def __init__(self, channel=0, device=0, mode=1):
|
||||
if not 0 <= channel < 4:
|
||||
raise InputDeviceError('channel must be between 0 and 4')
|
||||
super(MCP3302, self).__init__(device=device, bits=13, mode=mode)
|
||||
self._channel = channel
|
||||
self._mode = mode
|
||||
|
||||
class MCP3304(MCP3xxx):
|
||||
"""
|
||||
The MCP3304 is a 13 bit Analog to Digital Converter with
|
||||
4 channels single ended or 2 channels diferential.
|
||||
The channel number must be 0, 1, 2, 3, 4, 5, 6, 7 or 8
|
||||
"""
|
||||
def __init__(self, channel=0, device=0, mode=1):
|
||||
if not 0 <= channel < 8:
|
||||
raise InputDeviceError('channel must be between 0 and 7')
|
||||
super(MCP3304, self).__init__(device=device, bits=13, mode=mode)
|
||||
self._channel = channel
|
||||
self._mode = mode
|
||||
|
||||
|
||||
Reference in New Issue
Block a user