Last active
August 2, 2019 10:45
-
-
Save sidwarkd/ec427aefb41e21e77919c7f52df7ea63 to your computer and use it in GitHub Desktop.
Pycom class for interacting with the ADS1115 ADC
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import ustruct | |
import time | |
_REGISTER_MASK = const(0x03) | |
_REGISTER_CONVERT = const(0x00) | |
_REGISTER_CONFIG = const(0x01) | |
_REGISTER_LOWTHRESH = const(0x02) | |
_REGISTER_HITHRESH = const(0x03) | |
_OS_MASK = const(0x8000) | |
_OS_SINGLE = const(0x8000) # Write: Set to start a single-conversion | |
_OS_BUSY = const(0x0000) # Read: Bit=0 when conversion is in progress | |
_OS_NOTBUSY = const(0x8000) # Read: Bit=1 when device is not performing a conversion | |
_MUX_MASK = const(0x7000) | |
_MUX_DIFF_0_1 = const(0x0000) # Differential P = AIN0, N = AIN1 (default) | |
_MUX_DIFF_0_3 = const(0x1000) # Differential P = AIN0, N = AIN3 | |
_MUX_DIFF_1_3 = const(0x2000) # Differential P = AIN1, N = AIN3 | |
_MUX_DIFF_2_3 = const(0x3000) # Differential P = AIN2, N = AIN3 | |
_MUX_SINGLE_0 = const(0x4000) # Single-ended AIN0 | |
_MUX_SINGLE_1 = const(0x5000) # Single-ended AIN1 | |
_MUX_SINGLE_2 = const(0x6000) # Single-ended AIN2 | |
_MUX_SINGLE_3 = const(0x7000) # Single-ended AIN3 | |
_PGA_MASK = const(0x0E00) | |
PGA_6_144V = const(0x0000) # +/-6.144V range = Gain 2/3 | |
PGA_4_096V = const(0x0200) # +/-4.096V range = Gain 1 | |
PGA_2_048V = const(0x0400) # +/-2.048V range = Gain 2 (default) | |
PGA_1_024V = const(0x0600) # +/-1.024V range = Gain 4 | |
PGA_0_512V = const(0x0800) # +/-0.512V range = Gain 8 | |
PGA_0_256V = const(0x0A00) # +/-0.256V range = Gain 16 | |
_MODE_MASK = const(0x0100) | |
_MODE_CONTIN = const(0x0000) # Continuous conversion mode | |
_MODE_SINGLE = const(0x0100) # Power-down single-shot mode (default) | |
_DR_MASK = const(0x00E0) | |
_DR_128SPS = const(0x0000) # 128 samples per second | |
_DR_250SPS = const(0x0020) # 250 samples per second | |
_DR_490SPS = const(0x0040) # 490 samples per second | |
_DR_920SPS = const(0x0060) # 920 samples per second | |
_DR_1600SPS = const(0x0080) # 1600 samples per second (default) | |
_DR_2400SPS = const(0x00A0) # 2400 samples per second | |
_DR_3300SPS = const(0x00C0) # 3300 samples per second | |
_CMODE_MASK = const(0x0010) | |
_CMODE_TRAD = const(0x0000) # Traditional comparator with hysteresis (default) | |
_CMODE_WINDOW = const(0x0010) # Window comparator | |
_CPOL_MASK = const(0x0008) | |
_CPOL_ACTVLOW = const(0x0000) # ALERT/RDY pin is low when active (default) | |
_CPOL_ACTVHI = const(0x0008) # ALERT/RDY pin is high when active | |
_CLAT_MASK = const(0x0004) # Determines if ALERT/RDY pin latches once asserted | |
_CLAT_NONLAT = const(0x0000) # Non-latching comparator (default) | |
_CLAT_LATCH = const(0x0004) # Latching comparator | |
_CQUE_MASK = const(0x0003) | |
_CQUE_1CONV = const(0x0000) # Assert ALERT/RDY after one conversions | |
_CQUE_2CONV = const(0x0001) # Assert ALERT/RDY after two conversions | |
_CQUE_4CONV = const(0x0002) # Assert ALERT/RDY after four conversions | |
_CQUE_NONE = const(0x0003) # Disable the comparator and put ALERT/RDY in high state (default) | |
# A mapping of gain values to rail to rail voltage range | |
_GAINS = { | |
PGA_6_144V: 12.288, # 2/3x | |
PGA_4_096V: 8.192, # 1x | |
PGA_2_048V: 4.096, # 2x | |
PGA_1_024V: 2.048, # 4x | |
PGA_0_512V: 1.024, # 8x | |
PGA_0_256V: 0.512 # 16x | |
} | |
_CHANNELS = (_MUX_SINGLE_0, _MUX_SINGLE_1, _MUX_SINGLE_2, _MUX_SINGLE_3) | |
_DIFFS = { | |
(0, 1): _MUX_DIFF_0_1, | |
(0, 3): _MUX_DIFF_0_3, | |
(1, 3): _MUX_DIFF_1_3, | |
(2, 3): _MUX_DIFF_2_3, | |
} | |
class ADS1115: | |
def __init__(self, i2c, address=0x48, gain=PGA_4_096V): | |
self.i2c = i2c | |
self.address = address | |
if gain in _GAINS: | |
self.gain = gain | |
else: | |
raise ValueError('gain must be one of the values in _GAINS') | |
def _write_register(self, register, value): | |
data = ustruct.pack('>BH', register, value) | |
self.i2c.writeto(self.address, data) | |
def _read_register(self, register): | |
data = self.i2c.readfrom_mem(self.address, register, 2 ) | |
return ustruct.unpack('>h', data)[0] | |
def read_config(self): | |
return self.i2c.readfrom_mem(self.address, 1, 2) | |
def get_voltage(self, channel): | |
return _GAINS[self.gain] * (self.read(channel) / 65535) | |
def read(self, channel): | |
self._write_register(_REGISTER_CONFIG, _CQUE_NONE | _CLAT_NONLAT | | |
_CPOL_ACTVLOW | _CMODE_TRAD | _DR_1600SPS | _MODE_SINGLE | | |
_OS_SINGLE | self.gain | _CHANNELS[channel]) | |
while not self._read_register(_REGISTER_CONFIG) & _OS_NOTBUSY: | |
time.sleep_ms(1) | |
return self._read_register(_REGISTER_CONVERT) | |
def diff(self, channel1, channel2): | |
self._write_register(_REGISTER_CONFIG, _CQUE_NONE | _CLAT_NONLAT | | |
_CPOL_ACTVLOW | _CMODE_TRAD | _DR_1600SPS | _MODE_SINGLE | | |
_OS_SINGLE | self.gain | _DIFFS[(channel1, channel2)]) | |
while not self._read_register(_REGISTER_CONFIG) & _OS_NOTBUSY: | |
time.sleep_ms(1) | |
return self._read_register(_REGISTER_CONVERT) | |
def alert_start(self, channel, threshold): | |
self._write_register(_REGISTER_HITHRESH, threshold) | |
self._write_register(_REGISTER_CONFIG, _CQUE_1CONV | _CLAT_LATCH | | |
_CPOL_ACTVLOW | _CMODE_TRAD | _DR_1600SPS | _MODE_CONTIN | | |
_MODE_CONTIN | self.gain | _CHANNELS[channel]) | |
def alert_read(self): | |
return self._read_register(_REGISTER_CONVERT) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
''' | |
This example assumes you have set the ADS1115 address to 0x48 | |
by connecting the ADDR pin to ground. If you have selected a | |
differnet address you will need to modify the constructor call | |
to ADS1115 to specify a different address like: | |
adc = ADS1115(i2c, address=0x49) | |
This example also assumes the default range of the ADS of | |
+- 4.096V. If your voltage input is in a different range | |
this can also be specified in the constructor call. For | |
example if your input voltage is within the range of +-2.048V | |
you would call the constructor like this: | |
adc = ADS1115(i2c, gain=PGA_2_048V) | |
A list of available gain options can be found in ADS1115.py | |
around line27. | |
''' | |
import pycom | |
from machine import I2C, Pin, Timer | |
from network import WLAN | |
from ADS1115 import ADS1115 | |
# Use the built in LED as a status indicator | |
status_led = Pin('G16', mode=Pin.OUT, value=1) | |
# Setup ADS1115 using defaults (0x48 address and 4.096V max range) | |
i2c = I2C(0, I2C.MASTER) | |
adc = ADS1115(i2c) | |
def read_adc(alarm): | |
if status_led: | |
status_led.toggle() | |
print("\nChannel 0 voltage: {}V".format(adc.get_voltage(0))) | |
print("Channel 0 ADC value: {}\n".format(adc.read(0))) | |
def main(): | |
# Use the RGB LED as an indicator of WiFi status | |
pycom.heartbeat(False) | |
wlan = WLAN() | |
if wlan.isconnected(): | |
pycom.rgbled(0x000f00) | |
else: | |
pycom.rgbled(0x0f0000) | |
# Read the ADC on a 5 second interval | |
Timer.Alarm(read_adc, 5, periodic=True) | |
main() |
@astcode I've updated the gist to include a simple example of reading from channel 0 on the ADS1115
Thank you. It works perfectly.
Thanks a Lot
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Can you please give an example of how to use this? I am a noob to Pycom ie. GPy/FiPy and I am wanting to get the reading from a few sensors.