In this article we look at the TMP102 digital sensor and we will connect it up to a Beaglebone
The TMP102 device is a digital temperature sensor ideal for NTC/PTC thermistor replacement where high accuracy is required. The device offers an accuracy of ±0.5°C without requiring calibration or external component signal conditioning. Device temperature sensors are highly linear and do not require complex calculations or lookup tables to derive the temperature. The on-chip 12-bit ADC offers resolutions down to 0.0625°C.
The TMP102 device features SMBus™, two-wire and I2C interface compatibility, and allows up to four devices on one bus. The device also features an SMBus alert function. The device is specified to operate over supply voltages from 1.4 to 3.6 V with the maximum quiescent current of 10 µA over the full operating range.
The TMP102 device is ideal for extended temperature measurement in a variety of communication, computer, consumer, environmental, industrial, and instrumentation applications. The device is specified for operation over a temperature range of –40°C to 125°C.
Parts List
Schematic/Connection
Beaglebone | Module |
3.3v – P9.3 | Vcc |
Gnd – P9.1 | Gnd |
SDA – P9.20 | SDA |
SCL – P9.19 | SCL |
Code
Modified example from https://github.com/n8many/TMP102py
[codesyntax lang=”python”]
import smbus import time TEMPERATURE_REG = 0x00 CONFIG_REG = 0x01 T_LOW_REG = 0x02 T_HIGH_REG = 0x03 ADDRESSES = [0x48, 0x49, 0x4A, 0x4B] tempConvert = { 'C': lambda x: x, 'K': lambda x: x+273.15, 'F': lambda x: x*9/5+32, 'R': lambda x: (x+273.15)*9/5 } tempConvertInv = { 'C': lambda x: x, 'K': lambda x: x-273.15, 'F': lambda x: (x-32)*5/9, 'R': lambda x: (x*5/9)-273.15 } class TMP102(object): def __init__(self, units=None, address=0x48, busnum=2): units = units or 'C' if (address not in ADDRESSES): raise ValueError("Invalid Address: {0:#x}".format(address)) self.address = address self.busnum = busnum self.setUnits(units) self.bus = smbus.SMBus(self.busnum) self.readTemperature() def bytesToTemp(self, data): # Adjustment for extended mode ext = self.extractConfig(1, 4, 1) #ext = data[1] & 0x01 res = int((data[0] << (4+ext)) + (data[1] >> (4-ext))) if (data[0] | 0x7F is 0xFF): # Perform 2's complement operation (x = x-2^bits) res = res - 4096*(2**ext) # Outputs temperature in degC return res*0.0625 def tempToBytes(self, temp): # Temp MUST be converted prior to input data = [0 , 0] res = int(temp/0.0625) ext = self.extractConfig(1, 4, 1) if (res < 0): res = res + 4096 * (2**ext) data[0] = (res >> (4 + ext)) & 0xFF data[1] = ((res & (2**(4 + ext)-1)) << (4 - ext)) | ext return data def extractConfig(self, num, location=0, length=0): data = self.bus.read_i2c_block_data(self.address, CONFIG_REG, 2) if (num == 3): #Full register dump return data else: mask = 2**length - 1 return (data[num] >> location) & mask def injectConfig(self, setting, num, location, length): mask = (2**length - 1) << location setting = (setting << location) & mask data = self.bus.read_i2c_block_data(self.address, CONFIG_REG, 2) data[num] &= ~mask data[num] |= setting self.bus.write_i2c_block_data(self.address, CONFIG_REG, data) def readTemperature(self, units=None): data = self.bus.read_i2c_block_data(self.address, TEMPERATURE_REG, 2) tempC = self.bytesToTemp(data) units = units or self.units try: tempOut = tempConvert[units](tempC) except: raise ValueError('Invalid Units "' + self.units + '"') return tempOut def getUnits(self): return self.units def setUnits(self, units): if (units.upper() in 'RCKF' and len(units) == 1): self.units = units.upper() else: raise ValueError("Invalid Unit, must use C(elcius), K(elvin)," "F(ahrenheit), or R(ankine)") def setConversionRate(self, rate): # 0 : 0.25 Hz # 1 : 1 Hz # 2 : 4 Hz (default) # 3 : 8 Hz self.injectConfig(rate, 1, 6, 2) def setExtendedMode(self, mode): # 0 : 12-bit ( -55C to 128C) # 1 : 13-bit ( -55C to 150C) self.injectConfig(mode, 1, 4, 1) def sleep(self): self.injectConfig(True, 0, 0, 1) def wakeup(self): self.injectConfig(False, 0, 0, 1) def setAlertPolarity(self, polarity): # 0 : Active Low # 1 : Active High self.injectConfig(polarity, 0, 2, 1) def alert(self): return extractConfig(1, 5, 1) def setFault(self, faultSetting): # 0 : 1 fault # 1 : 2 faults # 2 : 4 faults # 3 : 6 faults self.injectConfig(faultSetting, 0, 3, 2) def setAlertMode(self, mode): # 0 : Comparator Mode (Active within temp range) # 1 : Thermostat Mode (Active if over T_High, reset on read) self.injectConfig(mode, 0, 1, 1) def setBoundTemp(self, upper, temperature, units=None): units = units or self.units ext = self.extractConfig(1, 4, 1) try: temperature = tempConvertInv[units](temperature) except: raise ValueError('Invalid Units "' + self.units + '"') if (ext is 1 and temperature > 150): temperature = 150 elif (temperature < -55): temperature = -55 data = self.tempToBytes(temperature) if (upper): reg = T_HIGH_REG else: reg = T_LOW_REG self.bus.write_i2c_block_data(self.address, reg, data) def getBoundTemp(self, upper, units=None): units = units or self.units if (upper): reg = T_HIGH_REG else: reg = T_LOW_REG data = self.bus.read_i2c_block_data(self.address, reg, 2) tempC = self.bytesToTemp(data) try: tempOut = tempConvert[units](tempC) except: raise ValueError('Invalid Units "' + self.units + '"') return tempOut if __name__ == "__main__": tmp = TMP102('C', 0x48, 2) # Actually, lets make the temperatures Farenheit tmp.setUnits('F') while True: print "Current temp: {:.1f}degF".format(tmp.readTemperature()) time.sleep(1)
[/codesyntax]
Output
Run the above code. You should see something like this
debian@beaglebone:/var/lib/cloud9/$ python TMP102.py
Current temp: 71.4degF
Current temp: 71.3degF
Current temp: 71.3degF
Current temp: 71.3degF
Current temp: 74.4degF
Current temp: 77.7degF
Link
http://www.ti.com/lit/gpn/tmp102