Skip to content

Commit cecbc87

Browse files
jithinbpwavicles
authored andcommitted
Add support for ADS1115 16-bit ADC (#46)
Partly Fixes #45 .
1 parent 3f018a5 commit cecbc87

File tree

1 file changed

+194
-0
lines changed

1 file changed

+194
-0
lines changed

PSL/SENSORS/ADS1115.py

Lines changed: 194 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,194 @@
1+
# -*- coding: utf-8; mode: python; indent-tabs-mode: t; tab-width:4 -*-
2+
from __future__ import print_function
3+
from numpy import int16
4+
import time
5+
try:
6+
from collections import OrderedDict
7+
except ImportError:
8+
# fallback: try to use the ordereddict backport when using python 2.6
9+
from ordereddict import OrderedDict
10+
11+
12+
def connect(route,**args):
13+
return ADS1115(route,**args)
14+
15+
class ADS1115:
16+
ADDRESS = 0x48 #addr pin grounded. floating
17+
18+
REG_POINTER_MASK = 0x3
19+
REG_POINTER_CONVERT = 0
20+
REG_POINTER_CONFIG = 1
21+
REG_POINTER_LOWTHRESH=2
22+
REG_POINTER_HITHRESH =3
23+
24+
REG_CONFIG_OS_MASK =0x8000
25+
REG_CONFIG_OS_SINGLE =0x8000
26+
REG_CONFIG_OS_BUSY =0x0000
27+
REG_CONFIG_OS_NOTBUSY =0x8000
28+
29+
REG_CONFIG_MUX_MASK =0x7000
30+
REG_CONFIG_MUX_DIFF_0_1 =0x0000 # Differential P = AIN0, N = AIN1 =default)
31+
REG_CONFIG_MUX_DIFF_0_3 =0x1000 # Differential P = AIN0, N = AIN3
32+
REG_CONFIG_MUX_DIFF_1_3 =0x2000 # Differential P = AIN1, N = AIN3
33+
REG_CONFIG_MUX_DIFF_2_3 =0x3000 # Differential P = AIN2, N = AIN3
34+
REG_CONFIG_MUX_SINGLE_0 =0x4000 # Single-ended AIN0
35+
REG_CONFIG_MUX_SINGLE_1 =0x5000 # Single-ended AIN1
36+
REG_CONFIG_MUX_SINGLE_2 =0x6000 # Single-ended AIN2
37+
REG_CONFIG_MUX_SINGLE_3 =0x7000 # Single-ended AIN3
38+
39+
REG_CONFIG_PGA_MASK =0x0E00 #bits 11:9
40+
REG_CONFIG_PGA_6_144V =(0<<9) # +/-6.144V range = Gain 2/3
41+
REG_CONFIG_PGA_4_096V =(1<<9) # +/-4.096V range = Gain 1
42+
REG_CONFIG_PGA_2_048V =(2<<9) # +/-2.048V range = Gain 2 =default)
43+
REG_CONFIG_PGA_1_024V =(3<<9) # +/-1.024V range = Gain 4
44+
REG_CONFIG_PGA_0_512V =(4<<9) # +/-0.512V range = Gain 8
45+
REG_CONFIG_PGA_0_256V =(5<<9) # +/-0.256V range = Gain 16
46+
47+
REG_CONFIG_MODE_MASK =0x0100 #bit 8
48+
REG_CONFIG_MODE_CONTIN =(0<<8) # Continuous conversion mode
49+
REG_CONFIG_MODE_SINGLE =(1<<8) # Power-down single-shot mode =default)
50+
51+
REG_CONFIG_DR_MASK =0x00E0
52+
REG_CONFIG_DR_8SPS =(0<<5) #8 SPS
53+
REG_CONFIG_DR_16SPS =(1<<5) #16 SPS
54+
REG_CONFIG_DR_32SPS =(2<<5) #32 SPS
55+
REG_CONFIG_DR_64SPS =(3<<5) #64 SPS
56+
REG_CONFIG_DR_128SPS =(4<<5) #128 SPS
57+
REG_CONFIG_DR_250SPS =(5<<5) #260 SPS
58+
REG_CONFIG_DR_475SPS =(6<<5) #475 SPS
59+
REG_CONFIG_DR_860SPS =(7<<5) #860 SPS
60+
61+
REG_CONFIG_CMODE_MASK =0x0010
62+
REG_CONFIG_CMODE_TRAD =0x0000
63+
REG_CONFIG_CMODE_WINDOW =0x0010
64+
65+
REG_CONFIG_CPOL_MASK =0x0008
66+
REG_CONFIG_CPOL_ACTVLOW =0x0000
67+
REG_CONFIG_CPOL_ACTVHI =0x0008
68+
69+
REG_CONFIG_CLAT_MASK =0x0004
70+
REG_CONFIG_CLAT_NONLAT =0x0000
71+
REG_CONFIG_CLAT_LATCH =0x0004
72+
73+
REG_CONFIG_CQUE_MASK =0x0003
74+
REG_CONFIG_CQUE_1CONV =0x0000
75+
REG_CONFIG_CQUE_2CONV =0x0001
76+
REG_CONFIG_CQUE_4CONV =0x0002
77+
REG_CONFIG_CQUE_NONE =0x0003
78+
gains = OrderedDict([('GAIN_TWOTHIRDS',REG_CONFIG_PGA_6_144V),('GAIN_ONE',REG_CONFIG_PGA_4_096V),('GAIN_TWO',REG_CONFIG_PGA_2_048V),('GAIN_FOUR',REG_CONFIG_PGA_1_024V),('GAIN_EIGHT',REG_CONFIG_PGA_0_512V),('GAIN_SIXTEEN',REG_CONFIG_PGA_0_256V)])
79+
gain_scaling = OrderedDict([('GAIN_TWOTHIRDS',0.1875),('GAIN_ONE',0.125),('GAIN_TWO',0.0625),('GAIN_FOUR',0.03125),('GAIN_EIGHT',0.015625),('GAIN_SIXTEEN',0.0078125)])
80+
type_selection = OrderedDict([('UNI_0',0),('UNI_1',1),('UNI_2',2),('UNI_3',3),('DIFF_01','01'),('DIFF_23','23')])
81+
sdr_selection = OrderedDict([(8,REG_CONFIG_DR_8SPS),(16,REG_CONFIG_DR_16SPS),(32,REG_CONFIG_DR_32SPS),(64,REG_CONFIG_DR_64SPS),(128,REG_CONFIG_DR_128SPS),(250,REG_CONFIG_DR_250SPS),(475,REG_CONFIG_DR_475SPS),(860,REG_CONFIG_DR_860SPS)]) #sampling data rate
82+
83+
NUMPLOTS=1
84+
PLOTNAMES = ['mV']
85+
def __init__(self,I2C,**args):
86+
self.ADDRESS = args.get('address',self.ADDRESS)
87+
self.I2C = I2C
88+
self.channel = 'UNI_0'
89+
self.gain = 'GAIN_ONE'
90+
self.rate = 128
91+
92+
self.setGain('GAIN_ONE')
93+
self.setChannel('UNI_0')
94+
self.setDataRate(128)
95+
self.conversionDelay = 8
96+
self.name = 'ADS1115 16-bit ADC'
97+
self.params={'setGain':self.gains.keys(),'setChannel':self.type_selection.keys(),'setDataRate':self.sdr_selection.keys()}
98+
99+
100+
101+
102+
def __readInt__(self,addr):
103+
return int16(self.__readUInt__(addr))
104+
105+
def __readUInt__(self,addr):
106+
vals = self.I2C.readBulk(self.ADDRESS,addr,2)
107+
v=1.*((vals[0]<<8)|vals[1])
108+
return v
109+
110+
def initTemperature(self):
111+
self.I2C.writeBulk(self.ADDRESS,[self.REG_CONTROL,self.CMD_TEMP])
112+
time.sleep(0.005)
113+
114+
def readRegister(self,register):
115+
vals = self.I2C.readBulk(self.ADDRESS,register,2)
116+
return (vals[0]<<8)|vals[1]
117+
118+
def writeRegister(self,reg,value):
119+
self.I2C.writeBulk(self.ADDRESS,[reg,(value>>8)&0xFF,value&0xFF])
120+
121+
def setGain(self,gain):
122+
'''
123+
options : 'GAIN_TWOTHIRDS','GAIN_ONE','GAIN_TWO','GAIN_FOUR','GAIN_EIGHT','GAIN_SIXTEEN'
124+
'''
125+
self.gain = gain
126+
127+
def setChannel(self,channel):
128+
'''
129+
options 'UNI_0','UNI_1','UNI_2','UNI_3','DIFF_01','DIFF_23'
130+
'''
131+
self.channel = channel
132+
133+
def setDataRate(self,rate):
134+
'''
135+
data rate options 8,16,32,64,128,250,475,860 SPS
136+
'''
137+
self.rate = rate
138+
139+
140+
def readADC_SingleEnded(self,chan):
141+
if chan>3:return None
142+
#start with default values
143+
config = (self.REG_CONFIG_CQUE_NONE # Disable the comparator (default val)
144+
|self.REG_CONFIG_CLAT_NONLAT # Non-latching (default val)
145+
|self.REG_CONFIG_CPOL_ACTVLOW #Alert/Rdy active low (default val)
146+
|self.REG_CONFIG_CMODE_TRAD # Traditional comparator (default val)
147+
|self.sdr_selection[self.rate] # 1600 samples per second (default)
148+
|self.REG_CONFIG_MODE_SINGLE) # Single-shot mode (default)
149+
150+
#Set PGA/voltage range
151+
config |= self.gains[self.gain]
152+
153+
if chan == 0 : config |= self.REG_CONFIG_MUX_SINGLE_0
154+
elif chan == 1 : config |= self.REG_CONFIG_MUX_SINGLE_1
155+
elif chan == 2 : config |= self.REG_CONFIG_MUX_SINGLE_2
156+
elif chan == 3 : config |= self.REG_CONFIG_MUX_SINGLE_3
157+
#Set 'start single-conversion' bit
158+
config |= self.REG_CONFIG_OS_SINGLE
159+
self.writeRegister(self.REG_POINTER_CONFIG, config);
160+
time.sleep(1./self.rate+.002) #convert to mS to S
161+
return self.readRegister(self.REG_POINTER_CONVERT)*self.gain_scaling[self.gain]
162+
163+
def readADC_Differential(self,chan = '01'):
164+
#start with default values
165+
config = (self.REG_CONFIG_CQUE_NONE # Disable the comparator (default val)
166+
|self.REG_CONFIG_CLAT_NONLAT # Non-latching (default val)
167+
|self.REG_CONFIG_CPOL_ACTVLOW #Alert/Rdy active low (default val)
168+
|self.REG_CONFIG_CMODE_TRAD # Traditional comparator (default val)
169+
|self.sdr_selection[self.rate] # samples per second
170+
|self.REG_CONFIG_MODE_SINGLE) # Single-shot mode (default)
171+
172+
#Set PGA/voltage range
173+
config |= self.gains[self.gain]
174+
if chan == '01':config |= self.REG_CONFIG_MUX_DIFF_0_1
175+
elif chan == '23':config |= self.REG_CONFIG_MUX_DIFF_2_3
176+
#Set 'start single-conversion' bit
177+
config |= self.REG_CONFIG_OS_SINGLE
178+
self.writeRegister(self.REG_POINTER_CONFIG, config);
179+
time.sleep(1./self.rate+.002) #convert to mS to S
180+
return int16(self.readRegister(self.REG_POINTER_CONVERT))*self.gain_scaling[self.gain]
181+
182+
def getLastResults(self):
183+
return int16(self.readRegister(self.REG_POINTER_CONVERT))*self.gain_scaling[self.gain]
184+
185+
def getRaw(self):
186+
'''
187+
return values in mV
188+
'''
189+
chan = self.type_selection[self.channel]
190+
if self.channel[:3]=='UNI':
191+
return [self.readADC_SingleEnded(chan)]
192+
elif self.channel[:3]=='DIF':
193+
return [self.readADC_Differential(chan)]
194+

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy