parent
6d6ae46a2e
commit
e731810cfd
11 changed files with 753 additions and 1 deletions
74
CODE_OF_CONDUCT.md
Normal file
74
CODE_OF_CONDUCT.md
Normal file
|
|
@ -0,0 +1,74 @@
|
||||||
|
# Contributor Covenant Code of Conduct
|
||||||
|
|
||||||
|
## Our Pledge
|
||||||
|
|
||||||
|
In the interest of fostering an open and welcoming environment, we as
|
||||||
|
contributors and maintainers pledge to making participation in our project and
|
||||||
|
our community a harassment-free experience for everyone, regardless of age, body
|
||||||
|
size, disability, ethnicity, gender identity and expression, level of experience,
|
||||||
|
nationality, personal appearance, race, religion, or sexual identity and
|
||||||
|
orientation.
|
||||||
|
|
||||||
|
## Our Standards
|
||||||
|
|
||||||
|
Examples of behavior that contributes to creating a positive environment
|
||||||
|
include:
|
||||||
|
|
||||||
|
* Using welcoming and inclusive language
|
||||||
|
* Being respectful of differing viewpoints and experiences
|
||||||
|
* Gracefully accepting constructive criticism
|
||||||
|
* Focusing on what is best for the community
|
||||||
|
* Showing empathy towards other community members
|
||||||
|
|
||||||
|
Examples of unacceptable behavior by participants include:
|
||||||
|
|
||||||
|
* The use of sexualized language or imagery and unwelcome sexual attention or
|
||||||
|
advances
|
||||||
|
* Trolling, insulting/derogatory comments, and personal or political attacks
|
||||||
|
* Public or private harassment
|
||||||
|
* Publishing others' private information, such as a physical or electronic
|
||||||
|
address, without explicit permission
|
||||||
|
* Other conduct which could reasonably be considered inappropriate in a
|
||||||
|
professional setting
|
||||||
|
|
||||||
|
## Our Responsibilities
|
||||||
|
|
||||||
|
Project maintainers are responsible for clarifying the standards of acceptable
|
||||||
|
behavior and are expected to take appropriate and fair corrective action in
|
||||||
|
response to any instances of unacceptable behavior.
|
||||||
|
|
||||||
|
Project maintainers have the right and responsibility to remove, edit, or
|
||||||
|
reject comments, commits, code, wiki edits, issues, and other contributions
|
||||||
|
that are not aligned to this Code of Conduct, or to ban temporarily or
|
||||||
|
permanently any contributor for other behaviors that they deem inappropriate,
|
||||||
|
threatening, offensive, or harmful.
|
||||||
|
|
||||||
|
## Scope
|
||||||
|
|
||||||
|
This Code of Conduct applies both within project spaces and in public spaces
|
||||||
|
when an individual is representing the project or its community. Examples of
|
||||||
|
representing a project or community include using an official project e-mail
|
||||||
|
address, posting via an official social media account, or acting as an appointed
|
||||||
|
representative at an online or offline event. Representation of a project may be
|
||||||
|
further defined and clarified by project maintainers.
|
||||||
|
|
||||||
|
## Enforcement
|
||||||
|
|
||||||
|
Instances of abusive, harassing, or otherwise unacceptable behavior may be
|
||||||
|
reported by contacting the project team at support@adafruit.com. All
|
||||||
|
complaints will be reviewed and investigated and will result in a response that
|
||||||
|
is deemed necessary and appropriate to the circumstances. The project team is
|
||||||
|
obligated to maintain confidentiality with regard to the reporter of an incident.
|
||||||
|
Further details of specific enforcement policies may be posted separately.
|
||||||
|
|
||||||
|
Project maintainers who do not follow or enforce the Code of Conduct in good
|
||||||
|
faith may face temporary or permanent repercussions as determined by other
|
||||||
|
members of the project's leadership.
|
||||||
|
|
||||||
|
## Attribution
|
||||||
|
|
||||||
|
This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
|
||||||
|
available at [http://contributor-covenant.org/version/1/4][version]
|
||||||
|
|
||||||
|
[homepage]: http://contributor-covenant.org
|
||||||
|
[version]: http://contributor-covenant.org/version/1/4/
|
||||||
21
LICENSE
Normal file
21
LICENSE
Normal file
|
|
@ -0,0 +1,21 @@
|
||||||
|
The MIT License (MIT)
|
||||||
|
|
||||||
|
Copyright (c) 2017 Carter Nelson for Adafruit Industries
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
just a blank repo to get the ball rolling...
|
|
||||||
74
README.rst
Normal file
74
README.rst
Normal file
|
|
@ -0,0 +1,74 @@
|
||||||
|
|
||||||
|
Introduction
|
||||||
|
============
|
||||||
|
|
||||||
|
.. image:: https://readthedocs.org/projects/adafruit-circuitpython-CircuitPython_ADS1x15/badge/?version=latest
|
||||||
|
:target: https://circuitpython.readthedocs.io/projects/CircuitPython_ADS1x15/en/latest/
|
||||||
|
:alt: Documentation Status
|
||||||
|
|
||||||
|
.. image :: https://badges.gitter.im/adafruit/circuitpython.svg
|
||||||
|
:target: https://gitter.im/adafruit/circuitpython?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge
|
||||||
|
:alt: Gitter
|
||||||
|
|
||||||
|
Support for the ADS1x15 series of analog-to-digital converters. Available in 12-bit (ADS1015)
|
||||||
|
and 16-bit (ADS1115) versions.
|
||||||
|
|
||||||
|
Dependencies
|
||||||
|
=============
|
||||||
|
This driver depends on:
|
||||||
|
|
||||||
|
* `Adafruit CircuitPython <https://github.com/adafruit/circuitpython>`_
|
||||||
|
* `Bus Device <https://github.com/adafruit/Adafruit_CircuitPython_BusDevice>`_
|
||||||
|
|
||||||
|
Please ensure all dependencies are available on the CircuitPython filesystem.
|
||||||
|
This is easily achieved by downloading
|
||||||
|
`the Adafruit library and driver bundle <https://github.com/adafruit/Adafruit_CircuitPython_Bundle>`_.
|
||||||
|
|
||||||
|
Usage Example
|
||||||
|
=============
|
||||||
|
|
||||||
|
Single Ended
|
||||||
|
------------
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
import board
|
||||||
|
import busio
|
||||||
|
from adafruit_ads1x15.single_ended import ADS1015
|
||||||
|
|
||||||
|
i2c = busio.I2C(board.SCL, board.SDA)
|
||||||
|
adc = ADS1015(i2c)
|
||||||
|
while True:
|
||||||
|
# channel 0
|
||||||
|
print(adc[0].value, adc[0].volts)
|
||||||
|
|
||||||
|
Differential
|
||||||
|
------------
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
import board
|
||||||
|
import busio
|
||||||
|
from adafruit_ads1x15.differential import ADS1015
|
||||||
|
|
||||||
|
i2c = busio.I2C(board.SCL, board.SDA)
|
||||||
|
adc = ADS1015(i2c)
|
||||||
|
while True:
|
||||||
|
# channel 0 - channel 1
|
||||||
|
print(adc[(0,1)].value, adc[(0,1)].volts)
|
||||||
|
|
||||||
|
|
||||||
|
Contributing
|
||||||
|
============
|
||||||
|
|
||||||
|
Contributions are welcome! Please read our `Code of Conduct
|
||||||
|
<https://github.com/adafruit/Adafruit_CircuitPython_CircuitPython_ADS1x15/blob/master/CODE_OF_CONDUCT.md>`_
|
||||||
|
before contributing to help this project stay welcoming.
|
||||||
|
|
||||||
|
API Reference
|
||||||
|
=============
|
||||||
|
|
||||||
|
.. toctree::
|
||||||
|
:maxdepth: 2
|
||||||
|
|
||||||
|
api
|
||||||
219
adafruit_ads1x15/adafruit_ads1x15.py
Normal file
219
adafruit_ads1x15/adafruit_ads1x15.py
Normal file
|
|
@ -0,0 +1,219 @@
|
||||||
|
# The MIT License (MIT)
|
||||||
|
#
|
||||||
|
# Copyright (c) 2017 Carter Nelson for Adafruit Industries
|
||||||
|
#
|
||||||
|
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
# of this software and associated documentation files (the "Software"), to deal
|
||||||
|
# in the Software without restriction, including without limitation the rights
|
||||||
|
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
# copies of the Software, and to permit persons to whom the Software is
|
||||||
|
# furnished to do so, subject to the following conditions:
|
||||||
|
#
|
||||||
|
# The above copyright notice and this permission notice shall be included in
|
||||||
|
# all copies or substantial portions of the Software.
|
||||||
|
#
|
||||||
|
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
# THE SOFTWARE.
|
||||||
|
"""
|
||||||
|
`adafruit__ads1x15`
|
||||||
|
====================================================
|
||||||
|
|
||||||
|
CircuitPython driver for ADS1015/1115 ADCs.
|
||||||
|
|
||||||
|
* Author(s): Carter Nelson
|
||||||
|
"""
|
||||||
|
import time
|
||||||
|
from micropython import const
|
||||||
|
from adafruit_bus_device.i2c_device import I2CDevice
|
||||||
|
|
||||||
|
# Register and other configuration values:
|
||||||
|
ADS1x15_DEFAULT_ADDRESS = const(0x48)
|
||||||
|
ADS1x15_POINTER_CONVERSION = const(0x00)
|
||||||
|
ADS1x15_POINTER_CONFIG = const(0x01)
|
||||||
|
ADS1x15_POINTER_LOW_THRESHOLD = const(0x02)
|
||||||
|
ADS1x15_POINTER_HIGH_THRESHOLD = const(0x03)
|
||||||
|
ADS1x15_CONFIG_OS_SINGLE = const(0x8000)
|
||||||
|
ADS1x15_CONFIG_MUX_OFFSET = const(12)
|
||||||
|
# Maping of gain values to config register values.
|
||||||
|
ADS1x15_CONFIG_GAIN = {
|
||||||
|
2/3: 0x0000,
|
||||||
|
1: 0x0200,
|
||||||
|
2: 0x0400,
|
||||||
|
4: 0x0600,
|
||||||
|
8: 0x0800,
|
||||||
|
16: 0x0A00
|
||||||
|
}
|
||||||
|
ADS1x15_PGA_RANGE = {
|
||||||
|
2/3: 6.144,
|
||||||
|
1: 4.096,
|
||||||
|
2: 2.048,
|
||||||
|
4: 1.024,
|
||||||
|
8: 0.512,
|
||||||
|
16: 0.256
|
||||||
|
}
|
||||||
|
ADS1x15_CONFIG_MODE_CONTINUOUS = const(0x0000)
|
||||||
|
ADS1x15_CONFIG_MODE_SINGLE = const(0x0100)
|
||||||
|
# Mapping of data/sample rate to config register values for ADS1015 (faster).
|
||||||
|
ADS1015_CONFIG_DR = {
|
||||||
|
128: 0x0000,
|
||||||
|
250: 0x0020,
|
||||||
|
490: 0x0040,
|
||||||
|
920: 0x0060,
|
||||||
|
1600: 0x0080,
|
||||||
|
2400: 0x00A0,
|
||||||
|
3300: 0x00C0
|
||||||
|
}
|
||||||
|
# Mapping of data/sample rate to config register values for ADS1115 (slower).
|
||||||
|
ADS1115_CONFIG_DR = {
|
||||||
|
8: 0x0000,
|
||||||
|
16: 0x0020,
|
||||||
|
32: 0x0040,
|
||||||
|
64: 0x0060,
|
||||||
|
128: 0x0080,
|
||||||
|
250: 0x00A0,
|
||||||
|
475: 0x00C0,
|
||||||
|
860: 0x00E0
|
||||||
|
}
|
||||||
|
ADS1x15_CONFIG_COMP_WINDOW = const(0x0010)
|
||||||
|
ADS1x15_CONFIG_COMP_ACTIVE_HIGH = const(0x0008)
|
||||||
|
ADS1x15_CONFIG_COMP_LATCHING = const(0x0004)
|
||||||
|
ADS1x15_CONFIG_COMP_QUE = {
|
||||||
|
1: 0x0000,
|
||||||
|
2: 0x0001,
|
||||||
|
4: 0x0002
|
||||||
|
}
|
||||||
|
ADS1x15_CONFIG_COMP_QUE_DISABLE = const(0x0003)
|
||||||
|
ADS1x15_DIFF_CHANNELS = {
|
||||||
|
(0,1): 0,
|
||||||
|
(0,3): 1,
|
||||||
|
(1,3): 2,
|
||||||
|
(2,3): 3
|
||||||
|
}
|
||||||
|
|
||||||
|
class ADC_Channel(object):
|
||||||
|
"""Provides per channel access to ADC readings."""
|
||||||
|
|
||||||
|
def __init__(self, adc, channel):
|
||||||
|
self._adc = adc
|
||||||
|
self._channel = channel
|
||||||
|
|
||||||
|
@property
|
||||||
|
def value(self, ):
|
||||||
|
"""ADC reading in raw counts."""
|
||||||
|
return self._adc._read_channel(self._channel)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def volts(self, ):
|
||||||
|
"""ADC reading in volts."""
|
||||||
|
return self._adc._read_channel_volts(self._channel)
|
||||||
|
|
||||||
|
|
||||||
|
class ADS1x15(object):
|
||||||
|
"""Base functionality for ADS1x15 analog to digital converters."""
|
||||||
|
|
||||||
|
def __init__(self, i2c, address=ADS1x15_DEFAULT_ADDRESS, **kwargs):
|
||||||
|
self.buf = bytearray(3)
|
||||||
|
self.i2c_device = I2CDevice(i2c, address)
|
||||||
|
self.bits = None
|
||||||
|
self._channels = [ADC_Channel(self, 0),
|
||||||
|
ADC_Channel(self, 1),
|
||||||
|
ADC_Channel(self, 2),
|
||||||
|
ADC_Channel(self, 3)]
|
||||||
|
|
||||||
|
def _data_rate_default(self):
|
||||||
|
"""Retrieve the default data rate for this ADC (in samples per second).
|
||||||
|
Should be implemented by subclasses.
|
||||||
|
"""
|
||||||
|
raise NotImplementedError('Subclasses must implement _data_rate_default!')
|
||||||
|
|
||||||
|
def _data_rate_config(self, data_rate):
|
||||||
|
"""Subclasses should override this function and return a 16-bit value
|
||||||
|
that can be OR'ed with the config register to set the specified
|
||||||
|
data rate. If a value of None is specified then a default data_rate
|
||||||
|
setting should be returned. If an invalid or unsupported data_rate is
|
||||||
|
provided then an exception should be thrown.
|
||||||
|
"""
|
||||||
|
raise NotImplementedError('Subclass must implement _data_rate_config function!')
|
||||||
|
|
||||||
|
def _conversion_value(self, low, high):
|
||||||
|
"""Subclasses should override this function that takes the low and high
|
||||||
|
byte of a conversion result and returns a signed integer value.
|
||||||
|
"""
|
||||||
|
raise NotImplementedError('Subclass must implement _conversion_value function!')
|
||||||
|
|
||||||
|
def _read_channel(self, channel):
|
||||||
|
"""Subclasses should override this function to return a value for the
|
||||||
|
requested channels as a signed integer value.
|
||||||
|
"""
|
||||||
|
raise NotImplementedError('Subclass must implement _read_channel function!')
|
||||||
|
|
||||||
|
def _read_channel_volts(self, channel):
|
||||||
|
"""Subclasses should override this function to return a value for the
|
||||||
|
requested channels as a float value.
|
||||||
|
"""
|
||||||
|
raise NotImplementedError('Subclass must implement _read_channel_volts function!')
|
||||||
|
|
||||||
|
def _read(self, mux, gain, data_rate, mode):
|
||||||
|
"""Perform an ADC read with the provided mux, gain, data_rate, and mode
|
||||||
|
values. Returns the signed integer result of the read.
|
||||||
|
"""
|
||||||
|
config = ADS1x15_CONFIG_OS_SINGLE # Go out of power-down mode for conversion.
|
||||||
|
# Specify mux value.
|
||||||
|
config |= (mux & 0x07) << ADS1x15_CONFIG_MUX_OFFSET
|
||||||
|
# Validate the passed in gain and then set it in the config.
|
||||||
|
if gain not in ADS1x15_CONFIG_GAIN:
|
||||||
|
raise ValueError('Gain must be one of: 2/3, 1, 2, 4, 8, 16')
|
||||||
|
config |= ADS1x15_CONFIG_GAIN[gain]
|
||||||
|
# Set the mode (continuous or single shot).
|
||||||
|
config |= mode
|
||||||
|
# Get the default data rate if none is specified (default differs between
|
||||||
|
# ADS1015 and ADS1115).
|
||||||
|
if data_rate is None:
|
||||||
|
data_rate = self._data_rate_default()
|
||||||
|
# Set the data rate (this is controlled by the subclass as it differs
|
||||||
|
# between ADS1015 and ADS1115).
|
||||||
|
config |= self._data_rate_config(data_rate)
|
||||||
|
config |= ADS1x15_CONFIG_COMP_QUE_DISABLE # Disble comparator mode.
|
||||||
|
# Send the config value to start the ADC conversion.
|
||||||
|
# Explicitly break the 16-bit value down to a big endian pair of bytes.
|
||||||
|
self.buf[0] = ADS1x15_POINTER_CONFIG
|
||||||
|
self.buf[1] = (config >> 8) & 0xFF
|
||||||
|
self.buf[2] = config & 0xFF
|
||||||
|
with self.i2c_device as i2c:
|
||||||
|
i2c.write(self.buf)
|
||||||
|
# Wait for the ADC sample to finish based on the sample rate plus a
|
||||||
|
# small offset to be sure (0.1 millisecond).
|
||||||
|
time.sleep(1.0/data_rate+0.0001)
|
||||||
|
# Retrieve the result.
|
||||||
|
self.buf[0] = ADS1x15_POINTER_CONVERSION
|
||||||
|
i2c.write(self.buf, end=1, stop=False)
|
||||||
|
i2c.read_into(self.buf, start=1)
|
||||||
|
return self._conversion_value(self.buf[2], self.buf[1])
|
||||||
|
|
||||||
|
def stop_adc(self):
|
||||||
|
"""Stop all continuous ADC conversions (either normal or difference mode).
|
||||||
|
"""
|
||||||
|
# Set the config register to its default value of 0x8583 to stop
|
||||||
|
# continuous conversions.
|
||||||
|
self.buf[0] = ADS1x15_POINTER_CONFIG
|
||||||
|
self.buf[1] = 0x85
|
||||||
|
self.buf[2] = 0x83
|
||||||
|
with self.i2c_device as i2c:
|
||||||
|
i2c.write(self.buf)
|
||||||
|
|
||||||
|
def get_last_result(self):
|
||||||
|
"""Read the last conversion result when in continuous conversion mode.
|
||||||
|
Will return a signed integer value.
|
||||||
|
"""
|
||||||
|
# Retrieve the conversion register value, convert to a signed int, and
|
||||||
|
# return it.
|
||||||
|
self.buf[0] = ADS1x15_POINTER_CONVERSION
|
||||||
|
with self.i2c_device as i2c:
|
||||||
|
i2c.write(self.buf, end=1, stop=False)
|
||||||
|
i2c.read_into(self.buf, start=1)
|
||||||
|
return self._conversion_value(self.buf[2], self.buf[1])
|
||||||
111
adafruit_ads1x15/differential.py
Normal file
111
adafruit_ads1x15/differential.py
Normal file
|
|
@ -0,0 +1,111 @@
|
||||||
|
from .adafruit_ads1x15 import *
|
||||||
|
|
||||||
|
class ADS1x15_Differential(ADS1x15):
|
||||||
|
"""Base functionality for ADS1x15 analog to digital converters operating
|
||||||
|
in differential mode."""
|
||||||
|
|
||||||
|
def __getitem__(self, key):
|
||||||
|
return self._channels[ADS1x15_DIFF_CHANNELS[key]]
|
||||||
|
|
||||||
|
def read_adc_difference(self, differential, gain=1, data_rate=None):
|
||||||
|
"""Read the difference between two ADC channels and return the ADC value
|
||||||
|
as a signed integer result. Differential must be one of:
|
||||||
|
- 0 = Channel 0 minus channel 1
|
||||||
|
- 1 = Channel 0 minus channel 3
|
||||||
|
- 2 = Channel 1 minus channel 3
|
||||||
|
- 3 = Channel 2 minus channel 3
|
||||||
|
"""
|
||||||
|
assert 0 <= differential <= 3, 'Differential must be a value within 0-3!'
|
||||||
|
# Perform a single shot read using the provided differential value
|
||||||
|
# as the mux value (which will enable differential mode).
|
||||||
|
return self._read(differential, gain, data_rate, ADS1x15_CONFIG_MODE_SINGLE)
|
||||||
|
|
||||||
|
def read_volts_difference(self, differential, gain=1, data_rate=None):
|
||||||
|
"""Read the difference between two ADC channels and return the voltage value
|
||||||
|
as a floating point result. Differential must be one of:
|
||||||
|
- 0 = Channel 0 minus channel 1
|
||||||
|
- 1 = Channel 0 minus channel 3
|
||||||
|
- 2 = Channel 1 minus channel 3
|
||||||
|
- 3 = Channel 2 minus channel 3
|
||||||
|
"""
|
||||||
|
assert 0 <= differential <= 3, 'Differential must be a value within 0-3!'
|
||||||
|
raw = self.read_adc_difference(differential, gain, data_rate)
|
||||||
|
volts = raw * (ADS1x15_PGA_RANGE[gain] / (2**(self.bits-1) - 1))
|
||||||
|
return volts
|
||||||
|
|
||||||
|
def start_adc_difference(self, differential, gain=1, data_rate=None):
|
||||||
|
"""Start continuous ADC conversions between two ADC channels. Differential
|
||||||
|
must be one of:
|
||||||
|
- 0 = Channel 0 minus channel 1
|
||||||
|
- 1 = Channel 0 minus channel 3
|
||||||
|
- 2 = Channel 1 minus channel 3
|
||||||
|
- 3 = Channel 2 minus channel 3
|
||||||
|
Will return an initial conversion result, then call the get_last_result()
|
||||||
|
function continuously to read the most recent conversion result. Call
|
||||||
|
stop_adc() to stop conversions.
|
||||||
|
"""
|
||||||
|
assert 0 <= differential <= 3, 'Differential must be a value within 0-3!'
|
||||||
|
# Perform a single shot read using the provided differential value
|
||||||
|
# as the mux value (which will enable differential mode).
|
||||||
|
return self._read(differential, gain, data_rate, ADS1x15_CONFIG_MODE_CONTINUOUS)
|
||||||
|
|
||||||
|
class ADS1015(ADS1x15_Differential):
|
||||||
|
"""ADS1015 12-bit differential analog to digital converter instance."""
|
||||||
|
|
||||||
|
def __init__(self, *args, **kwargs):
|
||||||
|
super(ADS1015, self).__init__(*args, **kwargs)
|
||||||
|
self.bits = 12
|
||||||
|
|
||||||
|
def _data_rate_default(self):
|
||||||
|
# Default from datasheet page 19, config register DR bit default.
|
||||||
|
return 1600
|
||||||
|
|
||||||
|
def _data_rate_config(self, data_rate):
|
||||||
|
if data_rate not in ADS1015_CONFIG_DR:
|
||||||
|
raise ValueError('Data rate must be one of: 128, 250, 490, 920, 1600, 2400, 3300')
|
||||||
|
return ADS1015_CONFIG_DR[data_rate]
|
||||||
|
|
||||||
|
def _conversion_value(self, low, high):
|
||||||
|
# Convert to 12-bit signed value.
|
||||||
|
value = ((high & 0xFF) << 4) | ((low & 0xFF) >> 4)
|
||||||
|
# Check for sign bit and turn into a negative value if set.
|
||||||
|
if value & 0x800 != 0:
|
||||||
|
value -= 1 << 12
|
||||||
|
return value
|
||||||
|
|
||||||
|
def _read_channel(self, channel):
|
||||||
|
return self.read_adc_difference(channel)
|
||||||
|
|
||||||
|
def _read_channel_volts(self, channel):
|
||||||
|
return self.read_volts_difference(channel)
|
||||||
|
|
||||||
|
|
||||||
|
class ADS1115(ADS1x15_Differential):
|
||||||
|
"""ADS1115 16-bit differential analog to digital converter instance."""
|
||||||
|
|
||||||
|
def __init__(self, *args, **kwargs):
|
||||||
|
super(ADS1115, self).__init__(*args, **kwargs)
|
||||||
|
self.bits = 16
|
||||||
|
|
||||||
|
def _data_rate_default(self):
|
||||||
|
# Default from datasheet page 16, config register DR bit default.
|
||||||
|
return 128
|
||||||
|
|
||||||
|
def _data_rate_config(self, data_rate):
|
||||||
|
if data_rate not in ADS1115_CONFIG_DR:
|
||||||
|
raise ValueError('Data rate must be one of: 8, 16, 32, 64, 128, 250, 475, 860')
|
||||||
|
return ADS1115_CONFIG_DR[data_rate]
|
||||||
|
|
||||||
|
def _conversion_value(self, low, high):
|
||||||
|
# Convert to 16-bit signed value.
|
||||||
|
value = ((high & 0xFF) << 8) | (low & 0xFF)
|
||||||
|
# Check for sign bit and turn into a negative value if set.
|
||||||
|
if value & 0x8000 != 0:
|
||||||
|
value -= 1 << 16
|
||||||
|
return value
|
||||||
|
|
||||||
|
def _read_channel(self, channel):
|
||||||
|
return self.read_adc_difference(channel)
|
||||||
|
|
||||||
|
def _read_channel_volts(self, channel):
|
||||||
|
return self.read_volts_difference(channel)
|
||||||
98
adafruit_ads1x15/single_ended.py
Normal file
98
adafruit_ads1x15/single_ended.py
Normal file
|
|
@ -0,0 +1,98 @@
|
||||||
|
from .adafruit_ads1x15 import *
|
||||||
|
|
||||||
|
class ADS1x15_SingleEnded(ADS1x15):
|
||||||
|
"""Base functionality for ADS1x15 analog to digital converters operating
|
||||||
|
in single ended mode."""
|
||||||
|
|
||||||
|
def __getitem__(self, key):
|
||||||
|
return self._channels[key]
|
||||||
|
|
||||||
|
def read_adc(self, channel, gain=1, data_rate=None):
|
||||||
|
"""Read a single ADC channel and return the ADC value as a signed integer
|
||||||
|
result. Channel must be a value within 0-3.
|
||||||
|
"""
|
||||||
|
assert 0 <= channel <= 3, 'Channel must be a value within 0-3!'
|
||||||
|
# Perform a single shot read and set the mux value to the channel plus
|
||||||
|
# the highest bit (bit 3) set.
|
||||||
|
return self._read(channel + 0x04, gain, data_rate, ADS1x15_CONFIG_MODE_SINGLE)
|
||||||
|
|
||||||
|
def read_volts(self, channel, gain=1, data_rate=None):
|
||||||
|
"""Read a single ADC channel and return the voltage value as a floating point
|
||||||
|
result. Channel must be a value within 0-3.
|
||||||
|
"""
|
||||||
|
assert 0 <= channel <= 3, 'Channel must be a value within 0-3!'
|
||||||
|
raw = self.read_adc(channel, gain, data_rate)
|
||||||
|
volts = raw * (ADS1x15_PGA_RANGE[gain] / (2**(self.bits-1) - 1))
|
||||||
|
return volts
|
||||||
|
|
||||||
|
def start_adc(self, channel, gain=1, data_rate=None):
|
||||||
|
"""Start continuous ADC conversions on the specified channel (0-3). Will
|
||||||
|
return an initial conversion result, then call the get_last_result()
|
||||||
|
function to read the most recent conversion result. Call stop_adc() to
|
||||||
|
stop conversions.
|
||||||
|
"""
|
||||||
|
assert 0 <= channel <= 3, 'Channel must be a value within 0-3!'
|
||||||
|
# Start continuous reads and set the mux value to the channel plus
|
||||||
|
# the highest bit (bit 3) set.
|
||||||
|
return self._read(channel + 0x04, gain, data_rate, ADS1x15_CONFIG_MODE_CONTINUOUS)
|
||||||
|
|
||||||
|
class ADS1015(ADS1x15_SingleEnded):
|
||||||
|
"""ADS1015 12-bit single ended analog to digital converter instance."""
|
||||||
|
|
||||||
|
def __init__(self, *args, **kwargs):
|
||||||
|
super(ADS1015, self).__init__(*args, **kwargs)
|
||||||
|
self.bits = 12
|
||||||
|
|
||||||
|
def _data_rate_default(self):
|
||||||
|
# Default from datasheet page 19, config register DR bit default.
|
||||||
|
return 1600
|
||||||
|
|
||||||
|
def _data_rate_config(self, data_rate):
|
||||||
|
if data_rate not in ADS1015_CONFIG_DR:
|
||||||
|
raise ValueError('Data rate must be one of: 128, 250, 490, 920, 1600, 2400, 3300')
|
||||||
|
return ADS1015_CONFIG_DR[data_rate]
|
||||||
|
|
||||||
|
def _conversion_value(self, low, high):
|
||||||
|
# Convert to 12-bit signed value.
|
||||||
|
value = ((high & 0xFF) << 4) | ((low & 0xFF) >> 4)
|
||||||
|
# Check for sign bit and turn into a negative value if set.
|
||||||
|
if value & 0x800 != 0:
|
||||||
|
value -= 1 << 12
|
||||||
|
return value
|
||||||
|
|
||||||
|
def _read_channel(self, channel):
|
||||||
|
return self.read_adc(channel)
|
||||||
|
|
||||||
|
def _read_channel_volts(self, channel):
|
||||||
|
return self.read_volts(channel)
|
||||||
|
|
||||||
|
|
||||||
|
class ADS1115(ADS1x15_SingleEnded):
|
||||||
|
"""ADS1115 16-bit single ended analog to digital converter instance."""
|
||||||
|
|
||||||
|
def __init__(self, *args, **kwargs):
|
||||||
|
super(ADS1115, self).__init__(*args, **kwargs)
|
||||||
|
self.bits = 16
|
||||||
|
|
||||||
|
def _data_rate_default(self):
|
||||||
|
# Default from datasheet page 16, config register DR bit default.
|
||||||
|
return 128
|
||||||
|
|
||||||
|
def _data_rate_config(self, data_rate):
|
||||||
|
if data_rate not in ADS1115_CONFIG_DR:
|
||||||
|
raise ValueError('Data rate must be one of: 8, 16, 32, 64, 128, 250, 475, 860')
|
||||||
|
return ADS1115_CONFIG_DR[data_rate]
|
||||||
|
|
||||||
|
def _conversion_value(self, low, high):
|
||||||
|
# Convert to 16-bit signed value.
|
||||||
|
value = ((high & 0xFF) << 8) | (low & 0xFF)
|
||||||
|
# Check for sign bit and turn into a negative value if set.
|
||||||
|
if value & 0x8000 != 0:
|
||||||
|
value -= 1 << 16
|
||||||
|
return value
|
||||||
|
|
||||||
|
def _read_channel(self, channel):
|
||||||
|
return self.read_adc(channel)
|
||||||
|
|
||||||
|
def _read_channel_volts(self, channel):
|
||||||
|
return self.read_volts(channel)
|
||||||
11
api.rst
Normal file
11
api.rst
Normal file
|
|
@ -0,0 +1,11 @@
|
||||||
|
|
||||||
|
.. If you created a package, create one automodule per module in the package.
|
||||||
|
|
||||||
|
.. automodule:: adafruit_ads1x15
|
||||||
|
:members:
|
||||||
|
|
||||||
|
.. automodule:: differential
|
||||||
|
:members:
|
||||||
|
|
||||||
|
.. automodule:: single_ended
|
||||||
|
:members:
|
||||||
142
conf.py
Normal file
142
conf.py
Normal file
|
|
@ -0,0 +1,142 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
sys.path.insert(0, os.path.abspath('.'))
|
||||||
|
|
||||||
|
# -- General configuration ------------------------------------------------
|
||||||
|
|
||||||
|
# Add any Sphinx extension module names here, as strings. They can be
|
||||||
|
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
|
||||||
|
# ones.
|
||||||
|
extensions = [
|
||||||
|
'sphinx.ext.autodoc',
|
||||||
|
'sphinx.ext.intersphinx',
|
||||||
|
'sphinx.ext.viewcode',
|
||||||
|
]
|
||||||
|
|
||||||
|
intersphinx_mapping = {'python': ('https://docs.python.org/3.4', None),'BusDevice': ('https://circuitpython.readthedocs.io/projects/bus_device/en/latest/', None),'Register': ('https://circuitpython.readthedocs.io/projects/register/en/latest/', None),'CircuitPython': ('https://circuitpython.readthedocs.io/en/latest/', None)}
|
||||||
|
|
||||||
|
# Add any paths that contain templates here, relative to this directory.
|
||||||
|
templates_path = ['_templates']
|
||||||
|
|
||||||
|
source_suffix = '.rst'
|
||||||
|
|
||||||
|
# The master toctree document.
|
||||||
|
master_doc = 'README'
|
||||||
|
|
||||||
|
# General information about the project.
|
||||||
|
project = u'Adafruit CIRCUITPYTHON_ADS1X15 Library'
|
||||||
|
copyright = u'2017 Carter Nelson'
|
||||||
|
author = u'Carter Nelson'
|
||||||
|
|
||||||
|
# The version info for the project you're documenting, acts as replacement for
|
||||||
|
# |version| and |release|, also used in various other places throughout the
|
||||||
|
# built documents.
|
||||||
|
#
|
||||||
|
# The short X.Y version.
|
||||||
|
version = u'1.0'
|
||||||
|
# The full version, including alpha/beta/rc tags.
|
||||||
|
release = u'1.0'
|
||||||
|
|
||||||
|
# The language for content autogenerated by Sphinx. Refer to documentation
|
||||||
|
# for a list of supported languages.
|
||||||
|
#
|
||||||
|
# This is also used if you do content translation via gettext catalogs.
|
||||||
|
# Usually you set "language" from the command line for these cases.
|
||||||
|
language = None
|
||||||
|
|
||||||
|
# List of patterns, relative to source directory, that match files and
|
||||||
|
# directories to ignore when looking for source files.
|
||||||
|
# This patterns also effect to html_static_path and html_extra_path
|
||||||
|
exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store']
|
||||||
|
|
||||||
|
# The reST default role (used for this markup: `text`) to use for all
|
||||||
|
# documents.
|
||||||
|
#
|
||||||
|
default_role = "any"
|
||||||
|
|
||||||
|
# If true, '()' will be appended to :func: etc. cross-reference text.
|
||||||
|
#
|
||||||
|
add_function_parentheses = True
|
||||||
|
|
||||||
|
# The name of the Pygments (syntax highlighting) style to use.
|
||||||
|
pygments_style = 'sphinx'
|
||||||
|
|
||||||
|
# If true, `todo` and `todoList` produce output, else they produce nothing.
|
||||||
|
todo_include_todos = False
|
||||||
|
|
||||||
|
|
||||||
|
# -- Options for HTML output ----------------------------------------------
|
||||||
|
|
||||||
|
# The theme to use for HTML and HTML Help pages. See the documentation for
|
||||||
|
# a list of builtin themes.
|
||||||
|
#
|
||||||
|
on_rtd = os.environ.get('READTHEDOCS', None) == 'True'
|
||||||
|
|
||||||
|
if not on_rtd: # only import and set the theme if we're building docs locally
|
||||||
|
try:
|
||||||
|
import sphinx_rtd_theme
|
||||||
|
html_theme = 'sphinx_rtd_theme'
|
||||||
|
html_theme_path = [sphinx_rtd_theme.get_html_theme_path(), '.']
|
||||||
|
except:
|
||||||
|
html_theme = 'default'
|
||||||
|
html_theme_path = ['.']
|
||||||
|
else:
|
||||||
|
html_theme_path = ['.']
|
||||||
|
|
||||||
|
# Add any paths that contain custom static files (such as style sheets) here,
|
||||||
|
# relative to this directory. They are copied after the builtin static files,
|
||||||
|
# so a file named "default.css" will overwrite the builtin "default.css".
|
||||||
|
html_static_path = ['_static']
|
||||||
|
|
||||||
|
# Output file base name for HTML help builder.
|
||||||
|
htmlhelp_basename = 'AdafruitCIRCUITPYTHON_ADS1X15Librarydoc'
|
||||||
|
|
||||||
|
# -- Options for LaTeX output ---------------------------------------------
|
||||||
|
|
||||||
|
latex_elements = {
|
||||||
|
# The paper size ('letterpaper' or 'a4paper').
|
||||||
|
#
|
||||||
|
# 'papersize': 'letterpaper',
|
||||||
|
|
||||||
|
# The font size ('10pt', '11pt' or '12pt').
|
||||||
|
#
|
||||||
|
# 'pointsize': '10pt',
|
||||||
|
|
||||||
|
# Additional stuff for the LaTeX preamble.
|
||||||
|
#
|
||||||
|
# 'preamble': '',
|
||||||
|
|
||||||
|
# Latex figure (float) alignment
|
||||||
|
#
|
||||||
|
# 'figure_align': 'htbp',
|
||||||
|
}
|
||||||
|
|
||||||
|
# Grouping the document tree into LaTeX files. List of tuples
|
||||||
|
# (source start file, target name, title,
|
||||||
|
# author, documentclass [howto, manual, or own class]).
|
||||||
|
latex_documents = [
|
||||||
|
(master_doc, 'AdafruitCIRCUITPYTHON_ADS1X15Library.tex', u'Adafruit CIRCUITPYTHON_ADS1X15 Library Documentation',
|
||||||
|
author, 'manual'),
|
||||||
|
]
|
||||||
|
|
||||||
|
# -- Options for manual page output ---------------------------------------
|
||||||
|
|
||||||
|
# One entry per manual page. List of tuples
|
||||||
|
# (source start file, name, description, authors, manual section).
|
||||||
|
man_pages = [
|
||||||
|
(master_doc, 'adafruitCIRCUITPYTHON_ADS1X15library', u'Adafruit CIRCUITPYTHON_ADS1X15 Library Documentation',
|
||||||
|
[author], 1)
|
||||||
|
]
|
||||||
|
|
||||||
|
# -- Options for Texinfo output -------------------------------------------
|
||||||
|
|
||||||
|
# Grouping the document tree into Texinfo files. List of tuples
|
||||||
|
# (source start file, target name, title, author,
|
||||||
|
# dir menu entry, description, category)
|
||||||
|
texinfo_documents = [
|
||||||
|
(master_doc, 'AdafruitCIRCUITPYTHON_ADS1X15Library', u'Adafruit CIRCUITPYTHON_ADS1X15 Library Documentation',
|
||||||
|
author, 'AdafruitCIRCUITPYTHON_ADS1X15Library', 'One line description of project.',
|
||||||
|
'Miscellaneous'),
|
||||||
|
]
|
||||||
2
readthedocs.yml
Normal file
2
readthedocs.yml
Normal file
|
|
@ -0,0 +1,2 @@
|
||||||
|
requirements_file: requirements.txt
|
||||||
|
|
||||||
1
requirements.txt
Normal file
1
requirements.txt
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
adafruit-circuitpython-bus-device
|
||||||
Loading…
Reference in a new issue