Citire senzor tmp102 pentru driver de termostatare

De la YO3ITI
Sari la navigare Sari la căutare
import smbus

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=1):
        units = units or 'C'
        if (address not in ADDRESSES):
            raise ValueError("Adresă incorectă: {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):
        # Ajustare pentru extended mode
        # vezi mai jos, def setExtendedMode
        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):
            # 2 complement (x = x-2^bits)
            res = res - 4096*(2**ext)
        # Scrie temperatura în Celsius
        return res*0.0625

    def tempToBytes(self, temp):
        # Temp trebuie transformată ÎNAINTE de introducere
        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):
            #dump complet de regiștri
            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('Unități nevalide "' + 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("Unități nevalide, trebuie utilizat C(elsius), K(elvin),"
                    "F(ahrenheit), sau R(ankine)")



    def setConversionRate(self, rate):
        # 0 : 0.25 Hz
        # 1 : 1 Hz
        # 2 : 4 Hz (implicit)
        # 3 : 8 Hz
        self.injectConfig(rate, 1, 6, 2)

    def setExtendedMode(self, mode):
        # 0 : 12-bit ( de la -55C la 128C)
        # 1 : 13-bit ( de la -55C la 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 : Activ Low
        # 1 : Activ High
        self.injectConfig(polarity, 0, 2, 1)

    def alert(self):
        return extractConfig(1, 5, 1)

    def setFault(self, faultSetting):
        # 0 : 1 eroare
        # 1 : 2 erori
        # 2 : 4 erori
        # 3 : 6 erori
        self.injectConfig(faultSetting, 0, 3, 2)

    def setAlertMode(self, mode):
        # 0 : Mode comparator (Activ în interiorul ecartului de temperatură)
        # 1 : Mod termostat (Activ dacă e peste T_High, reset la citire)
        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('Unități nevalide "' + 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('Unități nevalide "' + self.units + '"')
        return tempOut