Skip to content

Commit e731810

Browse files
caternusontannewt
authored andcommitted
Initial driver version (#1)
Thanks @caternuson!
1 parent 6d6ae46 commit e731810

File tree

11 files changed

+753
-1
lines changed

11 files changed

+753
-1
lines changed

CODE_OF_CONDUCT.md

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
# Contributor Covenant Code of Conduct
2+
3+
## Our Pledge
4+
5+
In the interest of fostering an open and welcoming environment, we as
6+
contributors and maintainers pledge to making participation in our project and
7+
our community a harassment-free experience for everyone, regardless of age, body
8+
size, disability, ethnicity, gender identity and expression, level of experience,
9+
nationality, personal appearance, race, religion, or sexual identity and
10+
orientation.
11+
12+
## Our Standards
13+
14+
Examples of behavior that contributes to creating a positive environment
15+
include:
16+
17+
* Using welcoming and inclusive language
18+
* Being respectful of differing viewpoints and experiences
19+
* Gracefully accepting constructive criticism
20+
* Focusing on what is best for the community
21+
* Showing empathy towards other community members
22+
23+
Examples of unacceptable behavior by participants include:
24+
25+
* The use of sexualized language or imagery and unwelcome sexual attention or
26+
advances
27+
* Trolling, insulting/derogatory comments, and personal or political attacks
28+
* Public or private harassment
29+
* Publishing others' private information, such as a physical or electronic
30+
address, without explicit permission
31+
* Other conduct which could reasonably be considered inappropriate in a
32+
professional setting
33+
34+
## Our Responsibilities
35+
36+
Project maintainers are responsible for clarifying the standards of acceptable
37+
behavior and are expected to take appropriate and fair corrective action in
38+
response to any instances of unacceptable behavior.
39+
40+
Project maintainers have the right and responsibility to remove, edit, or
41+
reject comments, commits, code, wiki edits, issues, and other contributions
42+
that are not aligned to this Code of Conduct, or to ban temporarily or
43+
permanently any contributor for other behaviors that they deem inappropriate,
44+
threatening, offensive, or harmful.
45+
46+
## Scope
47+
48+
This Code of Conduct applies both within project spaces and in public spaces
49+
when an individual is representing the project or its community. Examples of
50+
representing a project or community include using an official project e-mail
51+
address, posting via an official social media account, or acting as an appointed
52+
representative at an online or offline event. Representation of a project may be
53+
further defined and clarified by project maintainers.
54+
55+
## Enforcement
56+
57+
Instances of abusive, harassing, or otherwise unacceptable behavior may be
58+
reported by contacting the project team at [email protected]. All
59+
complaints will be reviewed and investigated and will result in a response that
60+
is deemed necessary and appropriate to the circumstances. The project team is
61+
obligated to maintain confidentiality with regard to the reporter of an incident.
62+
Further details of specific enforcement policies may be posted separately.
63+
64+
Project maintainers who do not follow or enforce the Code of Conduct in good
65+
faith may face temporary or permanent repercussions as determined by other
66+
members of the project's leadership.
67+
68+
## Attribution
69+
70+
This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
71+
available at [http://contributor-covenant.org/version/1/4][version]
72+
73+
[homepage]: http://contributor-covenant.org
74+
[version]: http://contributor-covenant.org/version/1/4/

LICENSE

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
The MIT License (MIT)
2+
3+
Copyright (c) 2017 Carter Nelson for Adafruit Industries
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in all
13+
copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
SOFTWARE.

README.md

Lines changed: 0 additions & 1 deletion
This file was deleted.

README.rst

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
2+
Introduction
3+
============
4+
5+
.. image:: https://readthedocs.org/projects/adafruit-circuitpython-CircuitPython_ADS1x15/badge/?version=latest
6+
:target: https://circuitpython.readthedocs.io/projects/CircuitPython_ADS1x15/en/latest/
7+
:alt: Documentation Status
8+
9+
.. image :: https://badges.gitter.im/adafruit/circuitpython.svg
10+
:target: https://gitter.im/adafruit/circuitpython?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge
11+
:alt: Gitter
12+
13+
Support for the ADS1x15 series of analog-to-digital converters. Available in 12-bit (ADS1015)
14+
and 16-bit (ADS1115) versions.
15+
16+
Dependencies
17+
=============
18+
This driver depends on:
19+
20+
* `Adafruit CircuitPython <https://github.com/adafruit/circuitpython>`_
21+
* `Bus Device <https://github.com/adafruit/Adafruit_CircuitPython_BusDevice>`_
22+
23+
Please ensure all dependencies are available on the CircuitPython filesystem.
24+
This is easily achieved by downloading
25+
`the Adafruit library and driver bundle <https://github.com/adafruit/Adafruit_CircuitPython_Bundle>`_.
26+
27+
Usage Example
28+
=============
29+
30+
Single Ended
31+
------------
32+
33+
.. code-block:: python
34+
35+
import board
36+
import busio
37+
from adafruit_ads1x15.single_ended import ADS1015
38+
39+
i2c = busio.I2C(board.SCL, board.SDA)
40+
adc = ADS1015(i2c)
41+
while True:
42+
# channel 0
43+
print(adc[0].value, adc[0].volts)
44+
45+
Differential
46+
------------
47+
48+
.. code-block:: python
49+
50+
import board
51+
import busio
52+
from adafruit_ads1x15.differential import ADS1015
53+
54+
i2c = busio.I2C(board.SCL, board.SDA)
55+
adc = ADS1015(i2c)
56+
while True:
57+
# channel 0 - channel 1
58+
print(adc[(0,1)].value, adc[(0,1)].volts)
59+
60+
61+
Contributing
62+
============
63+
64+
Contributions are welcome! Please read our `Code of Conduct
65+
<https://github.com/adafruit/Adafruit_CircuitPython_CircuitPython_ADS1x15/blob/master/CODE_OF_CONDUCT.md>`_
66+
before contributing to help this project stay welcoming.
67+
68+
API Reference
69+
=============
70+
71+
.. toctree::
72+
:maxdepth: 2
73+
74+
api

adafruit_ads1x15/adafruit_ads1x15.py

Lines changed: 219 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,219 @@
1+
# The MIT License (MIT)
2+
#
3+
# Copyright (c) 2017 Carter Nelson for Adafruit Industries
4+
#
5+
# Permission is hereby granted, free of charge, to any person obtaining a copy
6+
# of this software and associated documentation files (the "Software"), to deal
7+
# in the Software without restriction, including without limitation the rights
8+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
# copies of the Software, and to permit persons to whom the Software is
10+
# furnished to do so, subject to the following conditions:
11+
#
12+
# The above copyright notice and this permission notice shall be included in
13+
# all copies or substantial portions of the Software.
14+
#
15+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21+
# THE SOFTWARE.
22+
"""
23+
`adafruit__ads1x15`
24+
====================================================
25+
26+
CircuitPython driver for ADS1015/1115 ADCs.
27+
28+
* Author(s): Carter Nelson
29+
"""
30+
import time
31+
from micropython import const
32+
from adafruit_bus_device.i2c_device import I2CDevice
33+
34+
# Register and other configuration values:
35+
ADS1x15_DEFAULT_ADDRESS = const(0x48)
36+
ADS1x15_POINTER_CONVERSION = const(0x00)
37+
ADS1x15_POINTER_CONFIG = const(0x01)
38+
ADS1x15_POINTER_LOW_THRESHOLD = const(0x02)
39+
ADS1x15_POINTER_HIGH_THRESHOLD = const(0x03)
40+
ADS1x15_CONFIG_OS_SINGLE = const(0x8000)
41+
ADS1x15_CONFIG_MUX_OFFSET = const(12)
42+
# Maping of gain values to config register values.
43+
ADS1x15_CONFIG_GAIN = {
44+
2/3: 0x0000,
45+
1: 0x0200,
46+
2: 0x0400,
47+
4: 0x0600,
48+
8: 0x0800,
49+
16: 0x0A00
50+
}
51+
ADS1x15_PGA_RANGE = {
52+
2/3: 6.144,
53+
1: 4.096,
54+
2: 2.048,
55+
4: 1.024,
56+
8: 0.512,
57+
16: 0.256
58+
}
59+
ADS1x15_CONFIG_MODE_CONTINUOUS = const(0x0000)
60+
ADS1x15_CONFIG_MODE_SINGLE = const(0x0100)
61+
# Mapping of data/sample rate to config register values for ADS1015 (faster).
62+
ADS1015_CONFIG_DR = {
63+
128: 0x0000,
64+
250: 0x0020,
65+
490: 0x0040,
66+
920: 0x0060,
67+
1600: 0x0080,
68+
2400: 0x00A0,
69+
3300: 0x00C0
70+
}
71+
# Mapping of data/sample rate to config register values for ADS1115 (slower).
72+
ADS1115_CONFIG_DR = {
73+
8: 0x0000,
74+
16: 0x0020,
75+
32: 0x0040,
76+
64: 0x0060,
77+
128: 0x0080,
78+
250: 0x00A0,
79+
475: 0x00C0,
80+
860: 0x00E0
81+
}
82+
ADS1x15_CONFIG_COMP_WINDOW = const(0x0010)
83+
ADS1x15_CONFIG_COMP_ACTIVE_HIGH = const(0x0008)
84+
ADS1x15_CONFIG_COMP_LATCHING = const(0x0004)
85+
ADS1x15_CONFIG_COMP_QUE = {
86+
1: 0x0000,
87+
2: 0x0001,
88+
4: 0x0002
89+
}
90+
ADS1x15_CONFIG_COMP_QUE_DISABLE = const(0x0003)
91+
ADS1x15_DIFF_CHANNELS = {
92+
(0,1): 0,
93+
(0,3): 1,
94+
(1,3): 2,
95+
(2,3): 3
96+
}
97+
98+
class ADC_Channel(object):
99+
"""Provides per channel access to ADC readings."""
100+
101+
def __init__(self, adc, channel):
102+
self._adc = adc
103+
self._channel = channel
104+
105+
@property
106+
def value(self, ):
107+
"""ADC reading in raw counts."""
108+
return self._adc._read_channel(self._channel)
109+
110+
@property
111+
def volts(self, ):
112+
"""ADC reading in volts."""
113+
return self._adc._read_channel_volts(self._channel)
114+
115+
116+
class ADS1x15(object):
117+
"""Base functionality for ADS1x15 analog to digital converters."""
118+
119+
def __init__(self, i2c, address=ADS1x15_DEFAULT_ADDRESS, **kwargs):
120+
self.buf = bytearray(3)
121+
self.i2c_device = I2CDevice(i2c, address)
122+
self.bits = None
123+
self._channels = [ADC_Channel(self, 0),
124+
ADC_Channel(self, 1),
125+
ADC_Channel(self, 2),
126+
ADC_Channel(self, 3)]
127+
128+
def _data_rate_default(self):
129+
"""Retrieve the default data rate for this ADC (in samples per second).
130+
Should be implemented by subclasses.
131+
"""
132+
raise NotImplementedError('Subclasses must implement _data_rate_default!')
133+
134+
def _data_rate_config(self, data_rate):
135+
"""Subclasses should override this function and return a 16-bit value
136+
that can be OR'ed with the config register to set the specified
137+
data rate. If a value of None is specified then a default data_rate
138+
setting should be returned. If an invalid or unsupported data_rate is
139+
provided then an exception should be thrown.
140+
"""
141+
raise NotImplementedError('Subclass must implement _data_rate_config function!')
142+
143+
def _conversion_value(self, low, high):
144+
"""Subclasses should override this function that takes the low and high
145+
byte of a conversion result and returns a signed integer value.
146+
"""
147+
raise NotImplementedError('Subclass must implement _conversion_value function!')
148+
149+
def _read_channel(self, channel):
150+
"""Subclasses should override this function to return a value for the
151+
requested channels as a signed integer value.
152+
"""
153+
raise NotImplementedError('Subclass must implement _read_channel function!')
154+
155+
def _read_channel_volts(self, channel):
156+
"""Subclasses should override this function to return a value for the
157+
requested channels as a float value.
158+
"""
159+
raise NotImplementedError('Subclass must implement _read_channel_volts function!')
160+
161+
def _read(self, mux, gain, data_rate, mode):
162+
"""Perform an ADC read with the provided mux, gain, data_rate, and mode
163+
values. Returns the signed integer result of the read.
164+
"""
165+
config = ADS1x15_CONFIG_OS_SINGLE # Go out of power-down mode for conversion.
166+
# Specify mux value.
167+
config |= (mux & 0x07) << ADS1x15_CONFIG_MUX_OFFSET
168+
# Validate the passed in gain and then set it in the config.
169+
if gain not in ADS1x15_CONFIG_GAIN:
170+
raise ValueError('Gain must be one of: 2/3, 1, 2, 4, 8, 16')
171+
config |= ADS1x15_CONFIG_GAIN[gain]
172+
# Set the mode (continuous or single shot).
173+
config |= mode
174+
# Get the default data rate if none is specified (default differs between
175+
# ADS1015 and ADS1115).
176+
if data_rate is None:
177+
data_rate = self._data_rate_default()
178+
# Set the data rate (this is controlled by the subclass as it differs
179+
# between ADS1015 and ADS1115).
180+
config |= self._data_rate_config(data_rate)
181+
config |= ADS1x15_CONFIG_COMP_QUE_DISABLE # Disble comparator mode.
182+
# Send the config value to start the ADC conversion.
183+
# Explicitly break the 16-bit value down to a big endian pair of bytes.
184+
self.buf[0] = ADS1x15_POINTER_CONFIG
185+
self.buf[1] = (config >> 8) & 0xFF
186+
self.buf[2] = config & 0xFF
187+
with self.i2c_device as i2c:
188+
i2c.write(self.buf)
189+
# Wait for the ADC sample to finish based on the sample rate plus a
190+
# small offset to be sure (0.1 millisecond).
191+
time.sleep(1.0/data_rate+0.0001)
192+
# Retrieve the result.
193+
self.buf[0] = ADS1x15_POINTER_CONVERSION
194+
i2c.write(self.buf, end=1, stop=False)
195+
i2c.read_into(self.buf, start=1)
196+
return self._conversion_value(self.buf[2], self.buf[1])
197+
198+
def stop_adc(self):
199+
"""Stop all continuous ADC conversions (either normal or difference mode).
200+
"""
201+
# Set the config register to its default value of 0x8583 to stop
202+
# continuous conversions.
203+
self.buf[0] = ADS1x15_POINTER_CONFIG
204+
self.buf[1] = 0x85
205+
self.buf[2] = 0x83
206+
with self.i2c_device as i2c:
207+
i2c.write(self.buf)
208+
209+
def get_last_result(self):
210+
"""Read the last conversion result when in continuous conversion mode.
211+
Will return a signed integer value.
212+
"""
213+
# Retrieve the conversion register value, convert to a signed int, and
214+
# return it.
215+
self.buf[0] = ADS1x15_POINTER_CONVERSION
216+
with self.i2c_device as i2c:
217+
i2c.write(self.buf, end=1, stop=False)
218+
i2c.read_into(self.buf, start=1)
219+
return self._conversion_value(self.buf[2], self.buf[1])

0 commit comments

Comments
 (0)