Skip to content

Fast channel reads via caching last channel #33

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Jun 3, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 26 additions & 15 deletions adafruit_ads1x15/ads1x15.py
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ class ADS1x15(object):
def __init__(self, i2c, gain=1, data_rate=None, mode=Mode.SINGLE,
address=_ADS1X15_DEFAULT_ADDRESS):
#pylint: disable=too-many-arguments
self._last_pin_read = None
self.buf = bytearray(3)
self._data_rate = self._gain = self._mode = None
self.gain = gain
Expand Down Expand Up @@ -149,19 +150,23 @@ def _conversion_value(self, raw_adc):

def _read(self, pin):
"""Perform an ADC read. Returns the signed integer result of the read."""
config = _ADS1X15_CONFIG_OS_SINGLE
config |= (pin & 0x07) << _ADS1X15_CONFIG_MUX_OFFSET
config |= _ADS1X15_CONFIG_GAIN[self.gain]
config |= self.mode
config |= self.rate_config[self.data_rate]
config |= _ADS1X15_CONFIG_COMP_QUE_DISABLE
self._write_register(_ADS1X15_POINTER_CONFIG, config)
fast = True
if self._last_pin_read != pin:
self._last_pin_read = pin
fast = False
config = _ADS1X15_CONFIG_OS_SINGLE
config |= (pin & 0x07) << _ADS1X15_CONFIG_MUX_OFFSET
config |= _ADS1X15_CONFIG_GAIN[self.gain]
config |= self.mode
config |= self.rate_config[self.data_rate]
config |= _ADS1X15_CONFIG_COMP_QUE_DISABLE
self._write_register(_ADS1X15_POINTER_CONFIG, config)

if self.mode == Mode.SINGLE:
while not self._conversion_complete():
pass

return self.get_last_result()
return self._conversion_value(self.get_last_result(fast))

def _conversion_complete(self):
"""Return status of ADC conversion."""
Expand All @@ -170,11 +175,13 @@ def _conversion_complete(self):
# OS = 1: Device is not currently performing a conversion
return self._read_register(_ADS1X15_POINTER_CONFIG) & 0x8000

def get_last_result(self):
def get_last_result(self, fast=False):
"""Read the last conversion result when in continuous conversion mode.
Will return a signed integer value.
Will return a signed integer value. If fast is True, the register
pointer is not updated as part of the read. This reduces I2C traffic
and increases possible read rate.
"""
return self._conversion_value(self._read_register(_ADS1X15_POINTER_CONVERSION))
return self._read_register(_ADS1X15_POINTER_CONVERSION, fast)

def _write_register(self, reg, value):
"""Write 16 bit value to register."""
Expand All @@ -184,10 +191,14 @@ def _write_register(self, reg, value):
with self.i2c_device as i2c:
i2c.write(self.buf)

def _read_register(self, reg):
"""Read 16 bit register value."""
def _read_register(self, reg, fast=False):
"""Read 16 bit register value. If fast is True, the pointer register
is not updated.
"""
self.buf[0] = reg
with self.i2c_device as i2c:
i2c.write(self.buf, end=1, stop=False)
i2c.readinto(self.buf, end=2)
if fast:
i2c.readinto(self.buf, end=2)
else:
i2c.write_then_readinto(bytearray([reg]), self.buf, in_end=2, stop=False)
return self.buf[0] << 8 | self.buf[1]
37 changes: 37 additions & 0 deletions examples/ads1x15_fast_read.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import time
import board
import busio
import adafruit_ads1x15.ads1015 as ADS
from adafruit_ads1x15.ads1x15 import Mode
from adafruit_ads1x15.analog_in import AnalogIn

# Data collection setup
RATE = 3300
SAMPLES = 1000

# Create the I2C bus with a fast frequency
i2c = busio.I2C(board.SCL, board.SDA, frequency=1000000)

# Create the ADC object using the I2C bus
ads = ADS.ADS1015(i2c)

# Create single-ended input on channel 0
chan0 = AnalogIn(ads, ADS.P0)

# ADC Configuration
ads.mode = Mode.CONTINUOUS
ads.data_rate = RATE

data = [None]*SAMPLES

start = time.monotonic()

# Read the same channel over and over
for i in range(SAMPLES):
data[i] = chan0.value

end = time.monotonic()
total_time = end - start

print("Time of capture: {}s".format(total_time))
print("Sample rate requested={} actual={}".format(RATE, SAMPLES / total_time))