Skip to content

Commit e851f80

Browse files
authored
Merge pull request #47 from kevinjwalters/mcp320x
MCP32xx (12 bit) ADC support and optional baudrate parameter for SPI comms
2 parents c5e6278 + 84f5e9f commit e851f80

File tree

8 files changed

+269
-33
lines changed

8 files changed

+269
-33
lines changed

adafruit_mcp3xxx/analog_in.py

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
AnalogIn for single-ended and
99
differential ADC readings.
1010
11-
* Author(s): Brent Rubell
11+
* Author(s): Brent Rubell, Kevin J. Walters
1212
1313
.. warning::
1414
The ADC chips supported by this library do not use negative numbers. If the resulting
@@ -47,17 +47,19 @@ def __init__(self, mcp: MCP3xxx, positive_pin: int, negative_pin: Optional[int]
4747
"Differential pin mapping not defined. Please read the "
4848
"documentation for valid differential channel mappings."
4949
)
50+
self._read_shift_left = 16 - self._mcp.BITS
51+
self._read_shift_right = self._mcp.BITS - self._read_shift_left
5052

5153
@property
5254
def value(self) -> int:
5355
"""Returns the value of an ADC pin as an integer in the range [0, 65535]."""
54-
# Initial result is only 10 bits.
56+
# Initial result is only 10 or 12 bits.
5557
result = int(self._mcp.read(self._pin_setting, is_differential=self.is_differential))
5658
# Stretch to 16 bits and cover full range.
57-
return (result << 6) | (result >> 4)
59+
return (result << self._read_shift_left) | (result >> self._read_shift_right)
5860

5961
@property
6062
def voltage(self) -> float:
61-
"""Returns the voltage from the ADC pin as a floating point value. Due to the 10-bit
62-
accuracy of the chip, returned values range from 0 to ``reference_voltage``."""
63+
"""Returns the voltage from the ADC pin as a floating point value.
64+
Returned value ranges from 0 to ``reference_voltage``."""
6365
return self.value * self._mcp.reference_voltage / 65535

adafruit_mcp3xxx/mcp3002.py

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
MCP3002 2-channel, 10-bit, analog-to-digital
1010
converter instance.
1111
12-
* Author(s): Brent Rubell, Brendan Doherty
12+
* Author(s): Brent Rubell, Brendan Doherty, Kevin J. Walters
1313
1414
For proper wiring, please refer to `Package Type diagram
1515
<http://ww1.microchip.com/downloads/en/devicedoc/21294e.pdf#G1.1011678>`_ and `Pin Description
@@ -35,9 +35,21 @@ class MCP3002(MCP3xxx):
3535
See also the warning in the `AnalogIn`_ class API.
3636
"""
3737

38+
BITS = 10
3839
DIFF_PINS = {(0, 1): P0, (1, 0): P1}
3940

4041
def read(self, pin: int, is_differential: bool = False) -> int:
42+
"""SPI Interface for MCP3xxx-based ADCs reads. Due to 10-bit accuracy, the returned
43+
value ranges [0, 1023].
44+
45+
:param int pin: individual or differential pin.
46+
:param bool is_differential: single-ended or differential read.
47+
48+
.. note:: This library offers a helper class called `AnalogIn`_ for both single-ended
49+
and differential reads. If you opt to not implement `AnalogIn`_ during differential
50+
reads, then the ``pin`` parameter should be the first of the two pins associated with
51+
the desired differential channel mapping.
52+
"""
4153
self._out_buf[0] = 0x40 | ((not is_differential) << 5) | (pin << 4)
4254
with self._spi_device as spi:
4355
spi.write_readinto(self._out_buf, self._in_buf, out_end=2, in_end=2)

adafruit_mcp3xxx/mcp3004.py

Lines changed: 19 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
MCP3004 4-channel, 10-bit, analog-to-digital
99
converter instance.
1010
11-
* Author(s): Brent Rubell
11+
* Author(s): Brent Rubell, Kevin J. Walters
1212
1313
For proper wiring, please refer to `Package Types diagram
1414
<https://cdn-shop.adafruit.com/datasheets/MCP3008.pdf#page=1>`_ and `Pin Description section
@@ -18,14 +18,6 @@
1818

1919
from .mcp3xxx import MCP3xxx
2020

21-
try:
22-
import typing
23-
24-
from busio import SPI
25-
from digitalio import DigitalInOut
26-
except ImportError:
27-
pass
28-
2921
# MCP3004 Pin Mapping
3022
P0 = 0
3123
P1 = 1
@@ -46,8 +38,23 @@ class MCP3004(MCP3xxx):
4638
See also the warning in the `AnalogIn`_ class API.
4739
"""
4840

41+
BITS = 10
4942
DIFF_PINS = {(0, 1): P0, (1, 0): P1, (2, 3): P2, (3, 2): P3}
5043

51-
def __init__(self, spi_bus: SPI, cs: DigitalInOut, ref_voltage: float = 3.3) -> None:
52-
super().__init__(spi_bus, cs, ref_voltage=ref_voltage)
53-
self._out_buf[0] = 0x01
44+
def read(self, pin: int, is_differential: bool = False) -> int:
45+
"""SPI Interface for MCP3xxx-based ADCs reads. Due to 10-bit accuracy, the returned
46+
value ranges [0, 1023].
47+
48+
:param int pin: individual or differential pin.
49+
:param bool is_differential: single-ended or differential read.
50+
51+
.. note:: This library offers a helper class called `AnalogIn`_ for both single-ended
52+
and differential reads. If you opt to not implement `AnalogIn`_ during differential
53+
reads, then the ``pin`` parameter should be the first of the two pins associated with
54+
the desired differential channel mapping.
55+
"""
56+
self._out_buf[1] = ((not is_differential) << 7) | (pin << 4)
57+
with self._spi_device as spi:
58+
# pylint: disable=no-member
59+
spi.write_readinto(self._out_buf, self._in_buf)
60+
return ((self._in_buf[1] & 0x03) << 8) | self._in_buf[2]

adafruit_mcp3xxx/mcp3008.py

Lines changed: 19 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
MCP3008 8-channel, 10-bit, analog-to-digital
99
converter instance.
1010
11-
* Author(s): Brent Rubell
11+
* Author(s): Brent Rubell, Kevin J. Walters
1212
1313
For proper wiring, please refer to the `Package Types diagram
1414
<https://cdn-shop.adafruit.com/datasheets/MCP3008.pdf#page=1>`_ and `Pin Description section
@@ -18,14 +18,6 @@
1818

1919
from .mcp3xxx import MCP3xxx
2020

21-
try:
22-
import typing
23-
24-
from busio import SPI
25-
from digitalio import DigitalInOut
26-
except ImportError:
27-
pass
28-
2921
# MCP3008 Pin Mapping
3022
P0 = 0
3123
P1 = 1
@@ -54,6 +46,7 @@ class MCP3008(MCP3xxx):
5446
See also the warning in the `AnalogIn`_ class API.
5547
"""
5648

49+
BITS = 10
5750
DIFF_PINS = {
5851
(0, 1): P0,
5952
(1, 0): P1,
@@ -65,6 +58,20 @@ class MCP3008(MCP3xxx):
6558
(7, 6): P7,
6659
}
6760

68-
def __init__(self, spi_bus: SPI, cs: DigitalInOut, ref_voltage: float = 3.3) -> None:
69-
super().__init__(spi_bus, cs, ref_voltage=ref_voltage)
70-
self._out_buf[0] = 0x01
61+
def read(self, pin: int, is_differential: bool = False) -> int:
62+
"""SPI Interface for MCP3xxx-based ADCs reads. Due to 10-bit accuracy, the returned
63+
value ranges [0, 1023].
64+
65+
:param int pin: individual or differential pin.
66+
:param bool is_differential: single-ended or differential read.
67+
68+
.. note:: This library offers a helper class called `AnalogIn`_ for both single-ended
69+
and differential reads. If you opt to not implement `AnalogIn`_ during differential
70+
reads, then the ``pin`` parameter should be the first of the two pins associated with
71+
the desired differential channel mapping.
72+
"""
73+
self._out_buf[1] = ((not is_differential) << 7) | (pin << 4)
74+
with self._spi_device as spi:
75+
# pylint: disable=no-member
76+
spi.write_readinto(self._out_buf, self._in_buf)
77+
return ((self._in_buf[1] & 0x03) << 8) | self._in_buf[2]

adafruit_mcp3xxx/mcp3202.py

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
# SPDX-FileCopyrightText: 2018 Brent Rubell for Adafruit Industries
2+
# SPDX-FileCopyrightText: 2019 Brendan Doherty Adafruit Industries
3+
#
4+
# SPDX-License-Identifier: MIT
5+
6+
"""
7+
:py:class:`~adafruit_mcp3xxx.MCP3202.MCP3202`
8+
================================================
9+
MCP3202 2-channel, 12-bit, analog-to-digital
10+
converter instance.
11+
12+
* Author(s): Brent Rubell, Brendan Doherty, Kevin J. Walters
13+
14+
For proper wiring, please refer to `Package Type diagram
15+
<https://ww1.microchip.com/downloads/aemDocuments/documents/APID/ProductDocuments/DataSheets/21034F.pdf>`_
16+
and `Pin Description
17+
<https://ww1.microchip.com/downloads/aemDocuments/documents/APID/ProductDocuments/DataSheets/21034F.pdf#G1.1063009>`_
18+
section of the MCP3202 datasheet.
19+
"""
20+
21+
from .mcp3xxx import MCP3xxx
22+
23+
# MCP3202 Pin Mapping
24+
P0 = 0
25+
P1 = 1
26+
27+
28+
class MCP3202(MCP3xxx):
29+
"""
30+
MCP3202 Differential channel mapping. The following list of available differential readings
31+
takes the form ``(positive_pin, negative_pin) = (channel A) - (channel B)``.
32+
33+
- (P0, P1) = CH0 - CH1
34+
- (P1, P0) = CH1 - CH0
35+
36+
See also the warning in the `AnalogIn`_ class API.
37+
"""
38+
39+
BITS = 12
40+
DIFF_PINS = {(0, 1): P0, (1, 0): P1}
41+
42+
def read(self, pin: int, is_differential: bool = False) -> int:
43+
"""SPI Interface for MCP3xxx-based ADCs reads. Due to 12-bit accuracy, the returned
44+
value ranges [0, 4095].
45+
46+
:param int pin: individual or differential pin.
47+
:param bool is_differential: single-ended or differential read.
48+
49+
.. note:: This library offers a helper class called `AnalogIn`_ for both single-ended
50+
and differential reads. If you opt to not implement `AnalogIn`_ during differential
51+
reads, then the ``pin`` parameter should be the first of the two pins associated with
52+
the desired differential channel mapping.
53+
"""
54+
self._out_buf[0] = 0x40 | ((not is_differential) << 5) | (pin << 4)
55+
with self._spi_device as spi:
56+
# pylint: disable=no-member
57+
spi.write_readinto(self._out_buf, self._in_buf, out_end=2, in_end=2)
58+
return ((self._in_buf[0] & 0x0F) << 8) | self._in_buf[1]

adafruit_mcp3xxx/mcp3204.py

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
# SPDX-FileCopyrightText: 2018 Brent Rubell for Adafruit Industries
2+
#
3+
# SPDX-License-Identifier: MIT
4+
5+
"""
6+
:py:class:`~adafruit_mcp3xxx.mcp3204.MCP3204`
7+
================================================
8+
MCP3204 4-channel, 12-bit, analog-to-digital
9+
converter instance.
10+
11+
* Author(s): Brent Rubell, Kevin J. Walters
12+
13+
For proper wiring, please refer to `Package Types diagram
14+
<https://ww1.microchip.com/downloads/aemDocuments/documents/APID/ProductDocuments/DataSheets/21298e.pdf>`_
15+
and `Pin Description section
16+
<https://ww1.microchip.com/downloads/aemDocuments/documents/APID/ProductDocuments/DataSheets/21298e.pdf#G1.1041174>`_
17+
of the MCP3204/MCP3208 datasheet.
18+
"""
19+
20+
from .mcp3xxx import MCP3xxx
21+
22+
# MCP3204 Pin Mapping
23+
P0 = 0
24+
P1 = 1
25+
P2 = 2
26+
P3 = 3
27+
28+
29+
class MCP3204(MCP3xxx):
30+
"""
31+
MCP3204 Differential channel mapping. The following list of available differential readings
32+
takes the form ``(positive_pin, negative_pin) = (channel A) - (channel B)``.
33+
34+
- (P0, P1) = CH0 - CH1
35+
- (P1, P0) = CH1 - CH0
36+
- (P2, P3) = CH2 - CH3
37+
- (P3, P2) = CH3 - CH2
38+
39+
See also the warning in the `AnalogIn`_ class API.
40+
"""
41+
42+
BITS = 12
43+
DIFF_PINS = {(0, 1): P0, (1, 0): P1, (2, 3): P2, (3, 2): P3}
44+
45+
def read(self, pin: int, is_differential: bool = False) -> int:
46+
"""SPI Interface for MCP3xxx-based ADCs reads. Due to 10-bit accuracy, the returned
47+
value ranges [0, 1023].
48+
49+
:param int pin: individual or differential pin.
50+
:param bool is_differential: single-ended or differential read.
51+
52+
.. note:: This library offers a helper class called `AnalogIn`_ for both single-ended
53+
and differential reads. If you opt to not implement `AnalogIn`_ during differential
54+
reads, then the ``pin`` parameter should be the first of the two pins associated with
55+
the desired differential channel mapping.
56+
"""
57+
self._out_buf[0] = 0x04 | ((not is_differential) << 1) | (pin >> 2)
58+
self._out_buf[1] = (pin & 0x03) << 6
59+
with self._spi_device as spi:
60+
# pylint: disable=no-member
61+
spi.write_readinto(self._out_buf, self._in_buf)
62+
return ((self._in_buf[1] & 0x0F) << 8) | self._in_buf[2]

adafruit_mcp3xxx/mcp3208.py

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
# SPDX-FileCopyrightText: 2018 Brent Rubell for Adafruit Industries
2+
#
3+
# SPDX-License-Identifier: MIT
4+
5+
"""
6+
:py:class:`~adafruit_mcp3xxx.mcp3208.MCP3208`
7+
=============================================================
8+
MCP3208 8-channel, 12-bit, analog-to-digital
9+
converter instance.
10+
11+
* Author(s): Brent Rubell, Kevin J. Walters
12+
13+
For proper wiring, please refer to `Package Types diagram
14+
<https://ww1.microchip.com/downloads/aemDocuments/documents/APID/ProductDocuments/DataSheets/21298e.pdf>`_
15+
and `Pin Description section
16+
<https://ww1.microchip.com/downloads/aemDocuments/documents/APID/ProductDocuments/DataSheets/21298e.pdf#G1.1041174>`_
17+
of the MCP3204/MCP3208 datasheet.
18+
"""
19+
20+
from .mcp3xxx import MCP3xxx
21+
22+
# MCP3208 Pin Mapping
23+
P0 = 0
24+
P1 = 1
25+
P2 = 2
26+
P3 = 3
27+
P4 = 4
28+
P5 = 5
29+
P6 = 6
30+
P7 = 7
31+
32+
33+
class MCP3208(MCP3xxx):
34+
"""
35+
MCP3208 Differential channel mapping. The following list of available differential readings
36+
takes the form ``(positive_pin, negative_pin) = (channel A) - (channel B)``.
37+
38+
- (P0, P1) = CH0 - CH1
39+
- (P1, P0) = CH1 - CH0
40+
- (P2, P3) = CH2 - CH3
41+
- (P3, P2) = CH3 - CH2
42+
- (P4, P5) = CH4 - CH5
43+
- (P5, P4) = CH5 - CH4
44+
- (P6, P7) = CH6 - CH7
45+
- (P7, P6) = CH7 - CH6
46+
47+
See also the warning in the `AnalogIn`_ class API.
48+
"""
49+
50+
BITS = 12
51+
DIFF_PINS = {
52+
(0, 1): P0,
53+
(1, 0): P1,
54+
(2, 3): P2,
55+
(3, 2): P3,
56+
(4, 5): P4,
57+
(5, 4): P5,
58+
(6, 7): P6,
59+
(7, 6): P7,
60+
}
61+
62+
def read(self, pin: int, is_differential: bool = False) -> int:
63+
"""SPI Interface for MCP3xxx-based ADCs reads. Due to 10-bit accuracy, the returned
64+
value ranges [0, 1023].
65+
66+
:param int pin: individual or differential pin.
67+
:param bool is_differential: single-ended or differential read.
68+
69+
.. note:: This library offers a helper class called `AnalogIn`_ for both single-ended
70+
and differential reads. If you opt to not implement `AnalogIn`_ during differential
71+
reads, then the ``pin`` parameter should be the first of the two pins associated with
72+
the desired differential channel mapping.
73+
"""
74+
self._out_buf[0] = 0x04 | ((not is_differential) << 1) | (pin >> 2)
75+
self._out_buf[1] = (pin & 0x03) << 6
76+
with self._spi_device as spi:
77+
# pylint: disable=no-member
78+
spi.write_readinto(self._out_buf, self._in_buf)
79+
return ((self._in_buf[1] & 0x0F) << 8) | self._in_buf[2]

0 commit comments

Comments
 (0)