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:
pcopa
2016-01-18 20:25:36 -05:00
parent 15ce68d1a7
commit 38bc27b546
2 changed files with 172 additions and 30 deletions

View File

@@ -23,6 +23,11 @@ from .input_devices import (
AnalogInputDevice,
MCP3008,
MCP3004,
MCP3208,
MCP3204,
MCP3301,
MCP3302,
MCP3304,
)
from .output_devices import (
OutputDevice,

View File

@@ -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