class Device(object): def __init__(self, address, bus): self._bus = SMBus(bus) self._address = address def writeRaw8(self, value): value = value & 0xff self._bus.write_byte(self._address, value) def readRaw8(self): result = self._bus.read_byte(self._address) & 0xff return result def write8(self, register, value): value = value & 0xff self._bus.write_byte_data(self._address, register, value) def readU8(self, register): result = self._bus.read_byte_data(self._address, register) & 0xFF return result def readS8(self, register): result = self.readU8(register) if result > 127: result -= 256 return result def write16(self, register, value): value = value & 0xffff self._bus.write_word_data(self._address, register, value) def readU16(self, register, little_endian = True): result = self._bus.read_word_data(self._address,register) & 0xFFFF if not little_endian: result = ((result << 8) & 0xFF00) + (result >> 8) return result def readS16(self, register, little_endian = True): result = self.readU16(register, little_endian) if result > 32767: result -= 65536 return result def writeList(self, register, data): self._bus.write_i2c_block_data(self._address, register, data) def readList(self, register, length): results = self._bus.read_i2c_block_data(self._address, register, length) return results
class I2C(_Bus,NET): "Class representing a I2C bus, locally or over TCP/IP. Use an Instance of this class as the bus parameter for any board" Devices = {} DeviceList= {} class Device(): """class respresening a device connected to the bus, instances are created automatically""" def __init__(self,address,InUseBy=None,Bus = None,Ident=''): """address = int (0x00-0xFF), address of this device Ident = The Identification of the device for scan matching, default:'' InUseBy = If an Instance of a device-class is created, InUseBy points to that Instance""" self.Ident = Ident self.InUseBy = InUseBy VersionStrip =Ident.split(' ')[0].lower() if Ident !='' and VersionStrip in I2C.DeviceList: self.InUseBy = I2C.DeviceList[VersionStrip](Bus,address) else: self.Type=None if self.InUseBy!=None: self.InUseBy.Ident=VersionStrip def __init__(self,device=0,Port=None,Server=None): """ @param device The I2C bus to use e.g. /dev/i2c-0, /dev/i2c-1 etc. @param Port Default=None if set to an Integer this will be the TCP/IP port to listen on. @param Server Default=None if set to a string e.g. '192.168.200.137' the bus listening on that address/port combination will be connected to. @todo Ckeck for Raspberry Pi, and its version in /Proc/CPUInfo """ self.Port = Port self.Server=Server if self.Server != None: # TCP Client mode self.NetInit() self.Transaction=self._NetTransaction else: try: self.I2cBus = SMBus(device) except : print 'Need python-smbus for I2C bus to work' print '' print 'To install: sudo apt-get install python-smbus' return None if self.Port != None: #TCP Server Mode self.ServerThread = threading.Thread(target=self.ListenerTread) self.ServerThread.start() def Close(self): self.I2cBus.close() def Transaction(self, OutBuffer,read=0): if read!=0: try: return 0,' '+''.join([chr(m) for m in self.I2cBus.read_i2c_block_data((ord(OutBuffer[0])>>1),ord(OutBuffer[1]))]) except IOError: return 0," " else: self.I2cBus.write_i2c_block_data(ord(OutBuffer[0])>>1 ,ord(OutBuffer[1]), [ord(m) for m in OutBuffer[2:]]) return 0,None # # TODO: change Transaction to _Bus.Read_String # def scan(self,Display=None,line=0): for i in range(0x00,0xFF,0x02): ret, buf = self.Transaction(chr(i)+chr(Ident),0x20) Identification ="" for c in buf[2:]: if ord(c)==0: break if ord(c) in range(32,127): Identification +=c if Identification != "": if i in self.Devices: self.Devices[i].Ident=Identification else: self.Devices[i]=I2C.Device(i,Ident=Identification,Bus=self) if Display!=None: ProgressBar(i,minval=0, maxval=0xFF , Display = Display, y=line) sleep(.05) def AddDevice(self,Address, InUseBy): self.Devices[Address]=I2C.Device(Address,InUseBy=InUseBy,Bus=self)
class HTU21D(): """Class for accessing HTU21D sensors via I2C. Code taken from https://github.com/jasiek/HTU21D. Args: busno (int): The I2C bus (0 or 1, default is 1). address (byte): The I2C address of the sensor. """ CMD_TRIG_TEMP_HM = 0xE3 CMD_TRIG_HUMID_HM = 0xE5 CMD_TRIG_TEMP_NHM = 0xF3 CMD_TRIG_HUMID_NHM = 0xF5 CMD_WRITE_USER_REG = 0xE6 CMD_READ_USER_REG = 0xE7 CMD_RESET = 0xFE def __init__(self, busno=1, address=config.SENSOR_ID_HUMIDITY_EXT): self.bus = SMBus(busno) self.i2c_address = address def read_temperature(self): self.reset() msb, lsb, crc = self.bus.read_i2c_block_data( self.i2c_address, self.CMD_TRIG_TEMP_HM, 3) return -46.85 + 175.72 * (msb * 256 + lsb) / 65536 def read_humidity(self): self.reset() msb, lsb, crc = self.bus.read_i2c_block_data( self.i2c_address, self.CMD_TRIG_HUMID_HM, 3) return (-6 + 125 * (msb * 256 + lsb) / 65536.0) / 100.0 def reset(self): self.bus.write_byte(self.i2c_address, self.CMD_RESET)
class HTU21D: def __init__(self, busno): self.bus = SMBus(busno) def read_temperature(self): self.reset() msb, lsb, crc = self.bus.read_i2c_block_data(I2C_ADDR, CMD_TRIG_TEMP_HM, 3) return -46.85 + 175.72 * (msb * 256 + lsb) / 65536 def read_humidity(self): self.reset() msb, lsb, crc = self.bus.read_i2c_block_data(I2C_ADDR, CMD_TRIG_HUMID_HM, 3) return -6 + 125 * (msb * 256 + lsb) / 65536.0 def reset(self): self.bus.write_byte(I2C_ADDR, CMD_RESET)
class AM2320(object): """ AM2320 temperature and humidity sensor class. :param interface: I2C interface id. :type interface: :int :param sensor_address: AM2320 sensor I2C address. Optional, default 0x5C (92). :type sensor_address: int """ def __init__(self, interface, sensor_address=0x5c): self.interface = interface self.address = sensor_address self.temperature = -1000.0 self.humidity = -1 self.bus = SMBus(interface) def _read_raw(self, command, regaddr, regcount): try: self.bus.write_i2c_block_data(self.address, 0x00, []) self.bus.write_i2c_block_data(self.address, command, [regaddr, regcount]) sleep(0.002) buf = self.bus.read_i2c_block_data(self.address, 0, 8) except IOError, exc: raise CommunicationError(str(exc)) buf_str = "".join(chr(x) for x in buf) crc = unpack('<H', buf_str[-2:])[0] if crc != self._am_crc16(buf[:-2]): raise CommunicationError("AM2320 CRC error.") return buf_str[2:-2]
def readMPL3155(): # I2C Constants ADDR = 0x60 CTRL_REG1 = 0x26 PT_DATA_CFG = 0x13 bus = SMBus(2) who_am_i = bus.read_byte_data(ADDR, 0x0C) print hex(who_am_i) if who_am_i != 0xc4: tfile = open('temp.txt', 'w') tfile.write("Barometer funktioniert nicht") tfile.close() exit(1) # Set oversample rate to 128 setting = bus.read_byte_data(ADDR, CTRL_REG1) #newSetting = setting | 0x38 newSetting = 0x38 bus.write_byte_data(ADDR, CTRL_REG1, newSetting) # Enable event flags bus.write_byte_data(ADDR, PT_DATA_CFG, 0x07) # Toggel One Shot setting = bus.read_byte_data(ADDR, CTRL_REG1) if (setting & 0x02) == 0: bus.write_byte_data(ADDR, CTRL_REG1, (setting | 0x02)) # Read sensor data print "Waiting for data..." status = bus.read_byte_data(ADDR,0x00) #while (status & 0x08) == 0: while (status & 0x06) == 0: #print bin(status) status = bus.read_byte_data(ADDR,0x00) time.sleep(1) print "Reading sensor data..." status = bus.read_byte_data(ADDR,0x00) p_data = bus.read_i2c_block_data(ADDR,0x01,3) t_data = bus.read_i2c_block_data(ADDR,0x04,2) p_msb = p_data[0] p_csb = p_data[1] p_lsb = p_data[2] t_msb = t_data[0] t_lsb = t_data[1] pressure = (p_msb << 10) | (p_csb << 2) | (p_lsb >> 6) p_decimal = ((p_lsb & 0x30) >> 4)/4.0 celsius = t_msb + (t_lsb >> 4)/16.0 tfile = open('temp.txt', 'w') tfile.write("Luftdruck "+str(pressure/100)+" Hektopascal. ") tfile.write("Temperatur "+str("{0:.1f}".format(celsius).replace('.',','))+" Grad Celsius") tfile.close()
class Bus_Hepler_i2c(): def __init__(self, bus_location=1): self.bus = SMBus(bus_location) def write_byte(self, address, register, byte): self.bus.write_i2c_block_data(address, register, [byte]) def read_block_data(self, address, cmd): return self.bus.read_i2c_block_data(address, cmd)
class MTSMBus(I2CBus): """ Multi-thread compatible SMBus bus. This is just a wrapper of SMBus, serializing I/O on the bus for use in multi-threaded context and adding _i2c_ variants of block transfers. """ def __init__(self, bus_id=1, **kwargs): """ :param int bus_id: the SMBus id (see Raspberry Pi documentation) :param kwargs: parameters transmitted to :py:class:`smbus.SMBus` initializer """ I2CBus.__init__(self, **kwargs) self._bus = SMBus(bus_id) # I/O serialization lock self._lock = threading.Lock() def read_byte(self, addr): with self._lock: return self._bus.read_byte(addr) def write_byte(self, addr, data): with self._lock: self._bus.write_byte(addr, data) def read_byte_data(self, addr, reg): with self._lock: return self._bus.read_byte_data(addr, reg) def write_byte_data(self, addr, reg, data): with self._lock: self._bus.write_byte_data(addr, reg, data) def read_word_data(self, addr, reg): with self._lock: return self._bus.read_word_data(addr, reg) def write_word_data(self, addr, reg, data): with self._lock: self._bus.write_word_data(addr, reg, data) def read_block_data(self, addr, reg): with self._lock: return self._bus.read_block_data(addr, reg) def write_block_data(self, addr, reg, data): with self._lock: self._bus.write_block_data(addr, reg, data) def read_i2c_block_data(self, addr, reg, count): with self._lock: return self._bus.read_i2c_block_data(addr, reg, count) def write_i2c_block_data(self, addr, reg, data): with self._lock: self._bus.write_i2c_block_data(addr, reg, data)
def getPressure(): # I2C Constants ADDR = 0x60 CTRL_REG1 = 0x26 PT_DATA_CFG = 0x13 bus = SMBus(1) who_am_i = bus.read_byte_data(ADDR, 0x0C) print hex(who_am_i) if who_am_i != 0xc4: print "Device not active." exit(1) # Set oversample rate to 128 setting = bus.read_byte_data(ADDR, CTRL_REG1) newSetting = setting | 0x38 bus.write_byte_data(ADDR, CTRL_REG1, newSetting) # Enable event flags bus.write_byte_data(ADDR, PT_DATA_CFG, 0x07) # Toggel One Shot setting = bus.read_byte_data(ADDR, CTRL_REG1) if (setting & 0x02) == 0: bus.write_byte_data(ADDR, CTRL_REG1, (setting | 0x02)) status = -1; while (status & 0x08) == 0: status = bus.read_byte_data(ADDR,0x00) time.sleep(.5); print "Reading sensor data..." p_data = bus.read_i2c_block_data(ADDR,0x01,3) t_data = bus.read_i2c_block_data(ADDR,0x04,2) status = bus.read_byte_data(ADDR,0x00) print "status: "+bin(status) p_msb = p_data[0] p_csb = p_data[1] p_lsb = p_data[2] t_msb = t_data[0] t_lsb = t_data[1] pressure = (p_msb << 10) | (p_csb << 2) | (p_lsb >> 6) p_decimal = ((p_lsb & 0x30) >> 4)/4.0 return pressure+p_decimal
class TMP100: """ Class to read the onboard temperatur Sensor""" _SLAVE_ADDR = 0x49 _CONFIG_REG = 0x01 _TEMP_REG = 0x00 # config register _CONFIG_REG_OS = 0x01 _CONFIG_REG_RES_9B = 0x00 _CONFIG_REG_RES_12B = 0x03 _CONFIG_REG_TRIG_OS = 0x80 def __init__(self,device_number = 1): """ """ try: self.bus = SMBus(device_number) except Exception: raise i2cError() configList = [self._CONFIG_REG_OS, self._CONFIG_REG_RES_12B] self.configTMP100(configList) def configTMP100(self, list): """ Write list elements to tmp100#s configuration register""" reg = (list[1] << 5) + list[0] # write to config register self.bus.write_byte_data(self._SLAVE_ADDR,self._CONFIG_REG,reg) if DEBUG: # read config register back tmpReg = self.bus.read_byte_data(self._SLAVE_ADDR,self._CONFIG_REG) print(reg,tmpReg) def getTemperature(self): """ Get temperature readings """ # read first config register config = self.bus.read_byte_data(self._SLAVE_ADDR,self._CONFIG_REG) #trigger single shot newConfig = config + self._CONFIG_REG_TRIG_OS # write config register new value back self.bus.write_byte_data(self._SLAVE_ADDR,self._CONFIG_REG,newConfig) time.sleep(0.001) # wait a bit #read temperature register raw = self.bus.read_i2c_block_data(self._SLAVE_ADDR,self._TEMP_REG)[:2] val = ((raw[0] << 8) + raw[1]) >> 4 #TODO: get resolution factor properly :) return val*0.0625
def GetAlt(): # get the altitude from the MPL3115a2 device print "GetAlt()" # device address and register addresses altAddress = 0x60 ctrlReg1 = 0x26 ptDataCfg = 0x13 # values oversample128 = 0x38 oneShot = 0x02 altMode = 0x80 bus = SMBus(1) for i in range(0, 5): whoAmI = bus.read_byte_data(altAddress, 0x0C) if whoAmI == 0xC4: break elif i == 4: sys.exit() else: time.sleep(0.5) bus.write_byte_data(altAddress, ptDataCfg, 0x07) oldSetting = bus.read_byte_data(altAddress, ctrlReg1) newSetting = oldSetting | oversample128 | oneShot | altMode bus.write_byte_data(altAddress, ctrlReg1, newSetting) status = bus.read_byte_data(altAddress, 0x00) while (status & 0x08) == 0: status = bus.read_byte_data(altAddress, 0x00) time.sleep(0.5) msb, csb, lsb = bus.read_i2c_block_data(altAddress, 0x01, 3) alt = ((msb << 24) | (csb << 16) | (lsb << 8)) / 65536.0 if alt > (1 << 15): alt -= 1 << 16 return alt
class MB85RC04: def __init__(self, I2C_bus_number = 1, address = 0x50): self.bus = SMBus(I2C_bus_number) self.address = address def readByte(self, registerAddress): if(registerAddress > 255): self.address = self.address | 1 registerAddress = registerAddress - 256 else: self.address = self.address & 0xFE return self.bus.read_byte_data(self.address, registerAddress) def writeByte(self, registerAddress, data): if(registerAddress > 255): self.address = self.address | 1 registerAddress = registerAddress - 256 else: self.address = self.address & 0xFE self.bus.write_byte_data(self.address, registerAddress, data) def readBytes(self, registerAddress): if(registerAddress > 255): self.address = self.address | 1 registerAddress = registerAddress - 256 else: self.address = self.address & 0xFE return self.bus.read_i2c_block_data(self.address, registerAddress) def writeBytes(self, registerAddress, data): if(registerAddress > 255): self.address = self.address | 1 registerAddress = registerAddress - 256 else: self.address = self.address & 0xFE self.bus.write_i2c_block_data(self.address, registerAddress, data)
buf = [0,0] if __name__ == "__main__": main() from smbus import SMBus import time i2cbus = SMBus(1) # Create a new I2C bus i2caddress = 0x18 # Address of keypad RD_KEY_CMND = 0x05 SET_KEY_VALUES_CMND = 0x10 New_Key_Values = ['9','E','x','x','x', '0','4','x','x','x', 'A','B','x','x','x', 'F','G','x','x','x', 'x','x','x','x','x' ] New_Int_Values = [ord(str) for str in New_Key_Values] print(New_Key_Values) print(New_Int_Values) i2cbus.write_i2c_block_data(i2caddress,SET_KEY_VALUES_CMND, New_Int_Values) while 1: buf = i2cbus.read_i2c_block_data(i2caddress,RD_KEY_CMND,2) # duration = i2cbus.read_byte(i2caddress) #if buf[0] != 0: print(buf) time.sleep(1)
# Toggel One Shot setting = bus.read_byte_data(ADDR, CTRL_REG1) if (setting & 0x02) == 0: bus.write_byte_data(ADDR, CTRL_REG1, (setting | 0x02)) # Read sensor data print ("Esperando datos") status = bus.read_byte_data(ADDR,0x00) while (status & 0x08) == 0: #print bin(status) status = bus.read_byte_data(ADDR,0x00) time.sleep(0.5) print ("Lectura de datos del sensor") p_data = bus.read_i2c_block_data(ADDR,0x01,3) t_data = bus.read_i2c_block_data(ADDR,0x04,2) status = bus.read_byte_data(ADDR,0x00) print ("estado:"+bin(status)) p_msb = p_data[0] p_csb = p_data[1] p_lsb = p_data[2] t_msb = t_data[0] t_lsb = t_data[1] pressure = (p_msb << 10) | (p_csb << 2) | (p_lsb >> 6) p_decimal = ((p_lsb & 0x30) >> 4)/4.0 celsius = t_msb + (t_lsb >> 4)/16.0-70 fahrenheit = (celsius * 9)/5 + 32
class MS5611: __MS5611_ADDRESS_CSB_LOW = 0x76 __MS5611_ADDRESS_CSB_HIGH = 0x77 __MS5611_DEFAULT_ADDRESS = 0x77 __MS5611_RA_ADC = 0x00 __MS5611_RA_RESET = 0x1E __MS5611_RA_C0 = 0xA0 __MS5611_RA_C1 = 0xA2 __MS5611_RA_C2 = 0xA4 __MS5611_RA_C3 = 0xA6 __MS5611_RA_C4 = 0xA8 __MS5611_RA_C5 = 0xAA __MS5611_RA_C6 = 0xAC __MS5611_RA_C7 = 0xAE __MS5611_RA_D1_OSR_256 = 0x40 __MS5611_RA_D1_OSR_512 = 0x42 __MS5611_RA_D1_OSR_1024 = 0x44 __MS5611_RA_D1_OSR_2048 = 0x46 __MS5611_RA_D1_OSR_4096 = 0x48 __MS5611_RA_D2_OSR_256 = 0x50 __MS5611_RA_D2_OSR_512 = 0x52 __MS5611_RA_D2_OSR_1024 = 0x54 __MS5611_RA_D2_OSR_2048 = 0x56 __MS5611_RA_D2_OSR_4096 = 0x58 def __init__(self, I2C_bus_number=1, address=0x77): self.bus = SMBus(I2C_bus_number) self.address = address self.C1 = 0 self.C2 = 0 self.C3 = 0 self.C4 = 0 self.C5 = 0 self.C6 = 0 self.D1 = 0 self.D2 = 0 self.TEMP = 0.0 # Calculated temperature self.PRES = 0.0 # Calculated Pressure def initialize(self): ## The MS6511 Sensor stores 6 values in the EPROM memory that we need in order to calculate the actual temperature and pressure ## These values are calculated/stored at the factory when the sensor is calibrated. ## I probably could have used the read word function instead of the whole block, but I wanted to keep things consistent. C1 = self.bus.read_i2c_block_data( self.address, self.__MS5611_RA_C1) #Pressure Sensitivity #time.sleep(0.05) C2 = self.bus.read_i2c_block_data( self.address, self.__MS5611_RA_C2) #Pressure Offset #time.sleep(0.05) C3 = self.bus.read_i2c_block_data( self.address, self.__MS5611_RA_C3 ) #Temperature coefficient of pressure sensitivity #time.sleep(0.05) C4 = self.bus.read_i2c_block_data( self.address, self.__MS5611_RA_C4) #Temperature coefficient of pressure offset #time.sleep(0.05) C5 = self.bus.read_i2c_block_data( self.address, self.__MS5611_RA_C5) #Reference temperature #time.sleep(0.05) C6 = self.bus.read_i2c_block_data( self.address, self.__MS5611_RA_C6) #Temperature coefficient of the temperature ## Again here we are converting the 2 8bit packages into a single decimal self.C1 = C1[0] * 256.0 + C1[1] self.C2 = C2[0] * 256.0 + C2[1] self.C3 = C3[0] * 256.0 + C3[1] self.C4 = C4[0] * 256.0 + C4[1] self.C5 = C5[0] * 256.0 + C5[1] self.C6 = C6[0] * 256.0 + C6[1] self.update() def refreshPressure(self, OSR=__MS5611_RA_D1_OSR_4096): self.bus.write_byte(self.address, OSR) def refreshTemperature(self, OSR=__MS5611_RA_D2_OSR_4096): self.bus.write_byte(self.address, OSR) def readPressure(self): D1 = self.bus.read_i2c_block_data(self.address, self.__MS5611_RA_ADC) self.D1 = D1[0] * 65536 + D1[1] * 256.0 + D1[2] def readTemperature(self): D2 = self.bus.read_i2c_block_data(self.address, self.__MS5611_RA_ADC) self.D2 = D2[0] * 65536 + D2[1] * 256.0 + D2[2] def calculatePressureAndTemperature(self): dT = self.D2 - self.C5 * 2**8 self.TEMP = 2000 + dT * self.C6 / 2**23 OFF = self.C2 * 2**16 + (self.C4 * dT) / 2**7 SENS = self.C1 * 2**15 + (self.C3 * dT) / 2**8 if (self.TEMP >= 2000): T2 = 0 OFF2 = 0 SENS2 = 0 elif (self.TEMP < 2000): T2 = dT * dT / 2**31 OFF2 = 5 * ((self.TEMP - 2000)**2) / 2 SENS2 = OFF2 / 2 elif (self.TEMP < -1500): OFF2 = OFF2 + 7 * ((self.TEMP + 1500)**2) SENS2 = SENS2 + 11 * (self.TEMP + 1500)**2 / 2 self.TEMP = self.TEMP - T2 OFF = OFF - OFF2 SENS = SENS - SENS2 self.PRES = (self.D1 * SENS / 2**21 - OFF) / 2**15 self.TEMP = self.TEMP / 100 # Temperature updated self.PRES = self.PRES / 100 # Pressure updated def returnPressure(self): return self.PRES def returnTemperature(self): return self.TEMP def update(self): self.refreshPressure() time.sleep(0.01) # Waiting for pressure data ready self.readPressure() self.refreshTemperature() time.sleep(0.01) # Waiting for temperature data ready self.readTemperature() self.calculatePressureAndTemperature()
addr = 0x20 # I2C Address of MCP23017 irqPin = 26 # IRQ pin for MCP23017 os.system("sudo modprobe uinput") ui = UInput({e.EV_KEY: key}, name="retrogame", bustype=e.BUS_USB) bus = SMBus(3) IODIR = 0x00 IOCON = 0x05 INTCAP = 0x08 # Initial MCP23008 config: bus.write_byte_data(addr, IOCON, 0x44) # seq, OD IRQ # Read/modify/write remaining MCP23008 config: cfg = bus.read_i2c_block_data(addr, IODIR, 7) cfg[0] = 0xF # Input bits cfg[1] = 0x0 # Polarity cfg[2] = 0xF # Interrupt pins cfg[6] = 0xF # Pull-ups bus.write_i2c_block_data(addr, IODIR, cfg) # Clear interrupt by reading INTCAP and GPIO registers x = bus.read_i2c_block_data(addr, INTCAP, 2) #oldState = x[2] | (x[3] << 8) oldState = x[1] # Callback for MCP23017 interrupt request def mcp_irq(pin):
class AM4096: """ Class of the AM4096 """ eeprom_write_delay = 0.025 #in datasheet: at least 20 ms #self.configuration = {'Pdint','AGCdis','Slowint','Pdtr','Pdie','Reg35','Adr','Abridis','Bufsel','Monsel','Sign','Zin','Nfil','Daa','Hist','Dact','Dac','SSIcfg','Sth','UVW','Res','SRCH','Rpos','Apos','Weh','Wel','Thof','Tho'} def __init__(self , bus , Name = None , address = None): """ init the am4096 class""" self.bus = SMBus(bus) self.address = address self.busaddr= bus self.configuration = {} self.devices=[] self.i2c_repeated_start_condition = self.check_start_condition() def get_settings(self, stored = True): configuration = {} reg_addr= 0 if stored else 48 row = self.read_memory(reg_addr) configuration['Pdint']= int((row[0] >> 7) & 0x01) configuration['AGCdis']= int((row[0] >> 6) & 0x01) configuration['Slowint']= int((row[0] >> 4) & 0x01) configuration['Pdtr']= int((row[0] >> 2) & 0x03) configuration['Pdie']= int((row[0] >> 1) & 0x01) configuration['Reg35']= int(row[0] & 0x01) configuration['Addr']= int(row[1] & 0x7F) row = self.read_memory(reg_addr+1) configuration['Abridis']= int((row[0] >> 7) & 0x01) configuration['Bufsel']= int((row[0] >> 6) & 0x01) configuration['Monsel']= int((row[0] >> 5) & 0x01) configuration['Sign']= int((row[0] >> 4) & 0x01) configuration['Zin']= int(((row[0] & 0x0F) << 8) + row[1]) row = self.read_memory(reg_addr+2) configuration['Nfil']= int(row[0]) configuration['Daa']= int((row[1] >> 7) & 0x01) configuration['Hist']= int(row[1] & 0x7F) row = self.read_memory(reg_addr+3) configuration['Dact']= int((row[0] >> 7) & 0x01) configuration['Dac']= int((row[0] >> 5) & 0x03) configuration['SSIcfg']= int((row[0] >> 3) & 0x03) configuration['Sth']= int(((row[0] & 0x01) << 8) + ((row[1] >> 6) & 0x03)) configuration['UVW']= int((row[1] >> 3) & 0x07) configuration['Res']= int((row[1] >> 3) & 0x07) row = self.read_memory(32) configuration['Rpos']= {'valid': int((row[0] >> 7) & 0x01) , 'value':int(((row[0] & 0x0F) << 8) + row[1])} row = self.read_memory(33) configuration['Apos']= {'valid': int((row[0] >> 7) & 0x01) , 'value':int(((row[0] & 0x0F) << 8) + row[1])} row = self.read_memory(34) configuration['Weh']= int((row[0] >> 6) & 0x01) configuration['Wel']= int((row[0] >> 5) & 0x01) row = self.read_memory(35) configuration['AGCgain']= int((row[0] >> 4) & 0x0F) configuration['Thof']= int((row[0] >> 2) & 0x01) configuration['Tho']= int(((row[0] & 0x03) << 8) + row[1]) if stored : self.configuration = configuration return configuration def set_address(self,addr = 0): row = self.read_memory(0) new_row = [row[0] , (row[1] & 0x80) + addr] return self.write_memory( 0 , new_row) def get_Absolute_position(self): row = self.read_memory(33) return int(((row[0] & 0x0F) << 8) + row[1]) def set_rotation_dir(self): pass def get_Relative_position(self): row = self.read_memory(32) return int(((row[0] & 0x0F) << 8) + row[1]) def check_default_settings(self): pass def write_default_settings(self): pass def get_status(self): pass def scan(self,addr = None): pass def get_device_list(self): pass def is_available(self): pass def read_memory(self, reg): return self.bus.read_i2c_block_data(self.address, reg) pass def write_memory(self, reg , data): """ TODO: Add control on reg and data """ if(self.address is None): raise IOError('No device address defined yet!') eeprom = True if (reg < 30) else False res = self.bus.write_i2c_block_data(self.address, reg, [((data >> 8) & 0xFF ), (data & 0xFF )]) if eeprom: sleep(eeprom_write_delay) return res def check_start_condition(self): """ Init repeated start mode""" try: f = open('/sys/module/i2c_bcm2708/parameters/combined','w+r') if(str(f.read(1)).lower() != 'y'): f.write('Y') f.close() except IOError: print "Don't have write permission" def __str__(self): print(self.configuration) pass
class ADS1015: """ Class ro read analog values""" #control constants _SLAVE_ADDR = 0x48 # pointer register _POINTER_REG_CONVERSION = 0x00 _POINTER_REG_CONFIG = 0x01 # configuration register _CONFIG_REG_MUX_CH0 = 0x04 _CONFIG_REG_MUX_CH1 = 0x05 _CONFIG_REG_MUX_CH2 = 0x06 _CONFIG_REG_MUX_CH3 = 0x07 _CONFIG_REG_PGA_6144 = 0x00 _CONFIG_REG_PGA_4096 = 0x01 _CONFIG_REG_MODE_CONT = 0x00 _CONFIG_REG_MODE_SING = 0x01 _CONFIG_REG_DR_250SPS = 0x01 _CONFIG_REG_COMP_OFF = 0x3 def __init__(self,device_number,channel): """ """ try: self.bus = SMBus(device_number) except Exception: raise i2cError() try: if channel ==3: self.CH = self._CONFIG_REG_MUX_CH3 elif channel == 2: self.CH = self._CONFIG_REG_MUX_CH2 elif channel == 1: self.CH = self._CONFIG_REG_MUX_CH1 else: self.CH = self._CONFIG_REG_MUX_CH0 # MUX PGA MODE DR COMP_QUE confList = [ self.CH, \ self._CONFIG_REG_PGA_4096, \ self._CONFIG_REG_MODE_CONT, \ self._CONFIG_REG_DR_250SPS, \ self._CONFIG_REG_COMP_OFF ] self.configADS1015(confList) # set conversion factor if confList[1] == self._CONFIG_REG_PGA_6144: self.convFactor = 6.144*2.0/4096 elif confList[1] == self._CONFIG_REG_PGA_4096: self.convFactor = 4.096*2.0/4096 except Exception as e: print(e) raise ConfigError() def configADS1015(self, list): """ configure the chip according to list""" MSB = (list[0]<<4)+ (list[1]<<1) + list[2] LSB = (list[3]<<5) + list[4] # write list to config register self.bus.write_i2c_block_data(self._SLAVE_ADDR,self._POINTER_REG_CONFIG,[MSB, LSB]) if DEBUG: print("configList:", list) print("MSB: ", MSB, "LSB: ", LSB) #read register back Data = self.bus.read_i2c_block_data(self._SLAVE_ADDR,self._POINTER_REG_CONFIG)[:2] #print ( "To be written: ",MSB, LSB) print (" Read back : ",Data[0], Data[1]) def readAnalogChannel(self): """ reads single ended analog channel""" #read config register and overwrite MUX configTmp = self.bus.read_i2c_block_data(self._SLAVE_ADDR,self._POINTER_REG_CONFIG)[:2] bitmask = 0x8F tmp = (configTmp[0] & bitmask)|(self.CH << 4) self.bus.write_i2c_block_data(self._SLAVE_ADDR,self._POINTER_REG_CONFIG,[tmp,configTmp[1]]) # get conversion value tmp = self.bus.read_i2c_block_data(self._SLAVE_ADDR,self._POINTER_REG_CONVERSION)[:2] val = ((tmp[0] << 8) + tmp[1]) >> 4 return val * self.convFactor
except OSError as e: error[3] = e sleep(delay) try: # write with cmd/idx i2c.write_byte_data(addr, cmd, data[0]) except OSError as e: error[4] = e sleep(delay) try: # read block data read[2] = i2c.read_i2c_block_data(addr, cmd, cnt) except OSError as e: error[5] = e sleep(delay) try: # write block data i2c.write_i2c_block_data(addr, cmd, data) except OSError as e: error[6] = e sleep(delay) try: # general call
class CommunicationI2C(Communication): def __init__(self, name="i2c", address="0x00"): Communication.__init__(self, name) self.bus = None self.address = int(address, 16) self.timeout = 0.2 self.stopThread = False self.rwMutex = threading.Lock() self.startByte = '^' self.endByte = '\n' def connect(self, address=0x00, timeout=0.2): try: if address is 0x00: address = self.address else: self.address = address self.timeout = timeout print "opening i2c ", self.address self.bus = SMBus(1) self.rwMutex.acquire() try: self.bus.read_byte(self.address) self.connected = True except: self.connected = False self.rwMutex.release() print "connected", self.connected self.thread = threading.Thread(target=self.__receiveLoop) self.thread.start() return self.connected except: # e = sys.exc_info()[0] # print e return False def disconnect(self): if self.bus is None: return self.stopThread = True self.thread.join() self.connected = False def getChecksum(self, message): checksum = 0 for c in message: checksum ^= ord(c) return checksum def sendMessage(self, message): while len(self.pendingMessageList): #empty receive list self.pendingMessageList.pop(0) if self.bus is None or not self.connected: print "send message, not connected" return if len(message) > 29: print "Too long(", len(message), ") ", message return #print(message) checksum = self.getChecksum(message) message += chr(checksum) #print(message, hex(checksum), chr(checksum)) message = self.startByte + message + self.endByte #print "sending: ", message self.rwMutex.acquire() #print self.name, "Locked W" try: #print self.name, "try W" self.bus.write_i2c_block_data(self.address, 68, map(ord, message)) #print self.name, "wrote" time.sleep(0.002) #print self.name, ">", message except: print "Write failed on ", self.address self.rwMutex.release() self.disconnect() self.connect(self.address, 1) if self.connected: print "reconnected ", self.address else: #print self.name, "About Unlocked W" self.rwMutex.release() #print self.name, "Unlocked W" def __receiveLoop(self): errorDetected = False while self.bus is not None and self.connected and not self.stopThread: time.sleep(0.015) message = "" self.rwMutex.acquire() corruptDetected = False try: message = self.bus.read_i2c_block_data(self.address, 0, 30) time.sleep(0.001) message = "".join(map(chr, message)) payload = message #if not message.endswith(self.endByte): # message = "" newMessage = "" foundStart = False foundEnd = False for c in message: if not foundStart and c == self.startByte: foundStart = True continue if c == self.endByte and foundStart: foundEnd = True break newMessage += c #print("new: {}".format(newMessage)) checksum = ord(newMessage[-1:]) newMessage = newMessage[:-1] if not foundStart or not foundEnd or self.getChecksum( newMessage) != checksum: corruptDetected = True #print("Start:{} End:{} Checksum:{} Msg:{}".format(foundStart, foundEnd, self.getChecksum(newMessage) == checksum, message)) message = newMessage #message = message.replace(self.endByte(), '') message = message.replace(chr(255), '') message = message.replace(chr(0), '') except Exception as e: errorDetected = True print e self.rwMutex.release() if message and len(message) > 0: if corruptDetected: #print("{} Corrupt Start:{} End:{} Checksum:{}/{} Msg:{}".format(self.name, foundStart, foundEnd, self.getChecksum(newMessage), checksum, message)) #print("corrupt message: {} > {}".format(payload, map(ord, payload))) self.addPendingMessage("ERROR") else: #print("valid message: {} > {}".format(payload, map(ord, payload))) self.addPendingMessage(message) print self.name, "<", message if errorDetected and not self.stopThread: print "recv reconnecting ", self.address self.connect(self.address, self.timeout)
class TCS34725(object): address = 0x29 AGAIN = {0: 1, 1: 4, 2: 16, 3: 60} # The middle one should be 0xd6 for the table to be correct... # unless, of course, the other two were wrong and 0xD5 is in fact # correct. # in ms. ATIME = {0xff: 2.4, 0xf6: 24, 0xd6: 101, 0xc0: 154, 0x00: 700} def __init__(self, bus=1, gain=1, integration_time=2.4): self.bus = SMBus(bus) self.gain(gain) # must be called at least once as readCRGB() relies on its cached value self.integration_time(integration_time) self.enable() def check_ID(self): return 0x44 == self._read(0x12) def enable(self): """see notes on P.15""" self._write(0, 0b1) sleep(0.003) self._write(0, 0b11) def disable(self): self._write(0, 0) def status(self): return self._read(0x13) def read(self): r = self.bus.read_i2c_block_data(self.address, 0x80 + 0x14, 8) mc = min((256 - self._it) * 1024, 65535) r = { 'c': float((r[1] << 8) + r[0]) / mc, 'r': float((r[3] << 8) + r[2]) / mc, 'g': float((r[5] << 8) + r[4]) / mc, 'b': float((r[7] << 8) + r[6]) / mc, } return r def integration_time(self, it=None): """Integration time it should be one of {2.4,24,101,154,700}ms.""" if it is not None: ii = {self.ATIME[k]: k for k in self.ATIME.keys()} if it not in ii: raise AttributeError('integration time must be one of {}'.\ format(sorted(ii.keys()))) self._write(0x01, ii[it]) tmp = self._read(0x01) self._it = tmp return self.ATIME[tmp] def gain(self, gain=None): """gain should be one of {1,4,16,60}.""" if gain is not None: ig = {self.AGAIN[k]: k for k in self.AGAIN.keys()} if gain not in ig: raise AttributeError('gain must be one of {})'.\ format(sorted(ig.keys()))) self._write(0x0f, ig[gain]) return self.AGAIN[self._read(0x0f) & 0b11] #def duh(self): # print [self._read(0x00),self._read(0x01),self._read(0x0f)] def _read(self, reg): # so this would be a so-called "combined protocol" return self.bus.read_byte_data(self.address, 0x80 + reg) def _write(self, reg, value): self.bus.write_byte_data(self.address, 0x80 + reg, value) def __del__(self): #self.disable() pass
try: if not bme: try: bme = BME280(t_mode=BME280_OSAMPLE_8, p_mode=BME280_OSAMPLE_8, h_mode=BME280_OSAMPLE_8) except: pass T = bme.read_temperature() H = bme.read_humidity() except: print('Problem with BME280') ###TSL2561 try: data = smbus.read_i2c_block_data(0x39, 0x0C | 0x80, 2) data1 = smbus.read_i2c_block_data(0x39, 0x0E | 0x80, 2) ch0 = data[1] * 256 + data[0] ch1 = data1[1] * 256 + data1[0] L = ch0 - ch1 except: print('Problem with TSL2561') ###VL53L0X start = time.time() try: D = tof.get_distance() except: print('Problem with VL53L0X') if (time.time() - start) > 2: try:
class I2C(object): MASTER = 0 SLAVE = 1 RETRY = 5 def __init__(self, *args, **kargs): self._bus = 1 self._smbus = SMBus(self._bus) def auto_reset(func): def wrapper(*args, **kw): try: return func(*args, **kw) except OSError: soft_reset() time.sleep(1) return func(*args, **kw) return wrapper @auto_reset def _i2c_write_byte(self, addr, data): # self._debug("_i2c_write_byte: [0x{:02X}] [0x{:02X}]".format(addr, data)) return self._smbus.write_byte(addr, data) @auto_reset def _i2c_write_byte_data(self, addr, reg, data): # self._debug("_i2c_write_byte_data: [0x{:02X}] [0x{:02X}] [0x{:02X}]".format(addr, reg, data)) return self._smbus.write_byte_data(addr, reg, data) @auto_reset def _i2c_write_word_data(self, addr, reg, data): # self._debug("_i2c_write_word_data: [0x{:02X}] [0x{:02X}] [0x{:04X}]".format(addr, reg, data)) return self._smbus.write_word_data(addr, reg, data) @auto_reset def _i2c_write_i2c_block_data(self, addr, reg, data): # self._debug("_i2c_write_i2c_block_data: [0x{:02X}] [0x{:02X}] {}".format(addr, reg, data)) return self._smbus.write_i2c_block_data(addr, reg, data) @auto_reset def _i2c_read_byte(self, addr): # self._debug("_i2c_read_byte: [0x{:02X}]".format(addr)) return self._smbus.read_byte(addr) @auto_reset def _i2c_read_i2c_block_data(self, addr, reg, num): # self._debug("_i2c_read_i2c_block_data: [0x{:02X}] [0x{:02X}] [{}]".format(addr, reg, num)) return self._smbus.read_i2c_block_data(addr, reg, num) def is_ready(self, addr): addresses = self.scan() if addr in addresses: return True else: return False def scan(self): cmd = "i2cdetect -y %s" % self._bus _, output = self.run_command(cmd) outputs = output.split('\n')[1:] # self._debug("outputs") addresses = [] for tmp_addresses in outputs: tmp_addresses = tmp_addresses.split(':')[1] tmp_addresses = tmp_addresses.strip().split(' ') for address in tmp_addresses: if address != '--': addresses.append(address) # self._debug("Conneceted i2c device: %s"%addresses) return addresses def send(self, send, addr, timeout=0): if isinstance(send, bytearray): data_all = list(send) elif isinstance(send, int): data_all = [] d = "{:X}".format(send) d = "{}{}".format("0" if len(d)%2 == 1 else "", d) # print(d) for i in range(len(d)-2, -1, -2): tmp = int(d[i:i+2], 16) # print(tmp) data_all.append(tmp) data_all.reverse() elif isinstance(send, list): data_all = send else: raise ValueError("send data must be int, list, or bytearray, not {}".format(type(send))) if len(data_all) == 1: data = data_all[0] self._i2c_write_byte(addr, data) elif len(data_all) == 2: reg = data_all[0] data = data_all[1] self._i2c_write_byte_data(addr, reg, data) elif len(data_all) == 3: reg = data_all[0] data = (data_all[2] << 8) + data_all[1] self._i2c_write_word_data(addr, reg, data) else: reg = data_all[0] data = list(data_all[1:]) self._i2c_write_i2c_block_data(addr, reg, data) def recv(self, recv, addr=0x00, timeout=0): if isinstance(recv, int): result = bytearray(recv) elif isinstance(recv, bytearray): result = recv else: return False for i in range(len(result)): result[i] = self._i2c_read_byte(addr) return result def mem_write(self, data, addr, memaddr, timeout=5000, addr_size=8): #memaddr match to chn if isinstance(data, bytearray): data_all = list(data) elif isinstance(data, int): data_all = [] for i in range(0, 100): d = data >> (8*i) & 0xFF if d == 0: break else: data_all.append(d) data_all.reverse() self._i2c_write_i2c_block_data(addr, memaddr, data_all) def mem_read(self, data, addr, memaddr, timeout=5000, addr_size=8): if isinstance(data, int): num = data elif isinstance(data, bytearray): num = len(data) else: return False result = bytearray(num) result = self._i2c_read_i2c_block_data(addr, memaddr, num) return result def test(): a_list = [0x2d,0x64,0x0] b = I2C() b.send(a_list,0x14)
def task(self): avg_voc = 99999 try: # see if an update is ready bus = SMBus(I2CBUS) resp = bus.read_byte_data(self.I2Caddr, CCS811_REG_STATUS) bus.close() if resp & CCS811_STATUS_DATA_RDY: bus = SMBus(I2CBUS) resp = bus.read_i2c_block_data(self.I2Caddr, CCS811_REG_RESULTS, 4) bus.close() #e_co2 = (resp[0] << 8) | resp[1] t_voc = (resp[2] << 8) | resp[3] # make sure reading looks to be within range # 1187ppb is max possible if t_voc < 1200: self.voc_buff[self.voc_ptr] = t_voc self.voc_ptr += 1 if self.voc_ptr >= CCS811_MAX: self.voc_ptr = 0 # calculate current average voc value # 3 samples per minute avg_voc = 0 for i in range(CCS811_MAX): avg_voc += self.voc_buff[i] avg_voc /= CCS811_MAX_FLOAT avg_voc = int(round(avg_voc)) print "ccs811.task() avg voc: %d" % avg_voc f = open(self.FptrVoc, "w") f.write("%d" % avg_voc) f.close() self.newcal = self.get_baseline() if self.newcal != self.oldcal: print "ccs811.task() new baseline: 0x%04x" % self.newcal f = open(self.FptrBase, "w") f.write("0x%04x" % self.newcal) f.close() self.oldcal = self.newcal err = self.error_reg() if err: print "ccs811.task() error reg: 0x%02x" % resp[0] f = open(self.FptrError, "w") f.write("0x%02x" % err) f.close() # returning latest value, not average return t_voc else: print "ccs811.task() not ready yet 0x%02x" % resp[0] return 99999 except: print "ccs811.tast() error" return 99999
class ADS1x15(object): # IC Identifiers __IC_ADS1015 = 0x00 __IC_ADS1115 = 0x01 # Pointer Register __ADS1015_REG_POINTER_MASK = 0x03 __ADS1015_REG_POINTER_CONVERT = 0x00 __ADS1015_REG_POINTER_CONFIG = 0x01 __ADS1015_REG_POINTER_LOWTHRESH = 0x02 __ADS1015_REG_POINTER_HITHRESH = 0x03 # Config Register __ADS1015_REG_CONFIG_OS_MASK = 0x8000 __ADS1015_REG_CONFIG_OS_SINGLE = 0x8000 # Write: Set to start a single-conversion __ADS1015_REG_CONFIG_OS_BUSY = 0x0000 # Read: Bit = 0 when conversion is in progress __ADS1015_REG_CONFIG_OS_NOTBUSY = 0x8000 # Read: Bit = 1 when device is not performing a conversion __ADS1015_REG_CONFIG_MUX_MASK = 0x7000 __ADS1015_REG_CONFIG_MUX_DIFF_0_1 = 0x0000 # Differential P = AIN0, N = AIN1 (default) __ADS1015_REG_CONFIG_MUX_DIFF_0_3 = 0x1000 # Differential P = AIN0, N = AIN3 __ADS1015_REG_CONFIG_MUX_DIFF_1_3 = 0x2000 # Differential P = AIN1, N = AIN3 __ADS1015_REG_CONFIG_MUX_DIFF_2_3 = 0x3000 # Differential P = AIN2, N = AIN3 __ADS1015_REG_CONFIG_MUX_SINGLE_0 = 0x4000 # Single-ended AIN0 __ADS1015_REG_CONFIG_MUX_SINGLE_1 = 0x5000 # Single-ended AIN1 __ADS1015_REG_CONFIG_MUX_SINGLE_2 = 0x6000 # Single-ended AIN2 __ADS1015_REG_CONFIG_MUX_SINGLE_3 = 0x7000 # Single-ended AIN3 __ADS1015_REG_CONFIG_PGA_MASK = 0x0E00 __ADS1015_REG_CONFIG_PGA_6_144V = 0x0000 # +/-6.144V range __ADS1015_REG_CONFIG_PGA_4_096V = 0x0200 # +/-4.096V range __ADS1015_REG_CONFIG_PGA_2_048V = 0x0400 # +/-2.048V range (default) __ADS1015_REG_CONFIG_PGA_1_024V = 0x0600 # +/-1.024V range __ADS1015_REG_CONFIG_PGA_0_512V = 0x0800 # +/-0.512V range __ADS1015_REG_CONFIG_PGA_0_256V = 0x0A00 # +/-0.256V range __ADS1015_REG_CONFIG_MODE_MASK = 0x0100 __ADS1015_REG_CONFIG_MODE_CONTIN = 0x0000 # Continuous conversion mode __ADS1015_REG_CONFIG_MODE_SINGLE = 0x0100 # Power-down single-shot mode (default) __ADS1015_REG_CONFIG_DR_MASK = 0x00E0 __ADS1015_REG_CONFIG_DR_128SPS = 0x0000 # 128 samples per second __ADS1015_REG_CONFIG_DR_250SPS = 0x0020 # 250 samples per second __ADS1015_REG_CONFIG_DR_490SPS = 0x0040 # 490 samples per second __ADS1015_REG_CONFIG_DR_920SPS = 0x0060 # 920 samples per second __ADS1015_REG_CONFIG_DR_1600SPS = 0x0080 # 1600 samples per second (default) __ADS1015_REG_CONFIG_DR_2400SPS = 0x00A0 # 2400 samples per second __ADS1015_REG_CONFIG_DR_3300SPS = 0x00C0 # 3300 samples per second (also 0x00E0) __ADS1115_REG_CONFIG_DR_8SPS = 0x0000 # 8 samples per second __ADS1115_REG_CONFIG_DR_16SPS = 0x0020 # 16 samples per second __ADS1115_REG_CONFIG_DR_32SPS = 0x0040 # 32 samples per second __ADS1115_REG_CONFIG_DR_64SPS = 0x0060 # 64 samples per second __ADS1115_REG_CONFIG_DR_128SPS = 0x0080 # 128 samples per second __ADS1115_REG_CONFIG_DR_250SPS = 0x00A0 # 250 samples per second (default) __ADS1115_REG_CONFIG_DR_475SPS = 0x00C0 # 475 samples per second __ADS1115_REG_CONFIG_DR_860SPS = 0x00E0 # 860 samples per second __ADS1015_REG_CONFIG_CMODE_MASK = 0x0010 __ADS1015_REG_CONFIG_CMODE_TRAD = 0x0000 # Traditional comparator with hysteresis (default) __ADS1015_REG_CONFIG_CMODE_WINDOW = 0x0010 # Window comparator __ADS1015_REG_CONFIG_CPOL_MASK = 0x0008 __ADS1015_REG_CONFIG_CPOL_ACTVLOW = 0x0000 # ALERT/RDY pin is low when active (default) __ADS1015_REG_CONFIG_CPOL_ACTVHI = 0x0008 # ALERT/RDY pin is high when active __ADS1015_REG_CONFIG_CLAT_MASK = 0x0004 # Determines if ALERT/RDY pin latches once asserted __ADS1015_REG_CONFIG_CLAT_NONLAT = 0x0000 # Non-latching comparator (default) __ADS1015_REG_CONFIG_CLAT_LATCH = 0x0004 # Latching comparator __ADS1015_REG_CONFIG_CQUE_MASK = 0x0003 __ADS1015_REG_CONFIG_CQUE_1CONV = 0x0000 # Assert ALERT/RDY after one conversions __ADS1015_REG_CONFIG_CQUE_2CONV = 0x0001 # Assert ALERT/RDY after two conversions __ADS1015_REG_CONFIG_CQUE_4CONV = 0x0002 # Assert ALERT/RDY after four conversions __ADS1015_REG_CONFIG_CQUE_NONE = 0x0003 # Disable the comparator and put ALERT/RDY in high state (default) # Dictionaries with the sampling speed values # These simplify and clean the code (avoid the abuse of if/elif/else clauses) spsADS1115 = { 8:__ADS1115_REG_CONFIG_DR_8SPS, 16:__ADS1115_REG_CONFIG_DR_16SPS, 32:__ADS1115_REG_CONFIG_DR_32SPS, 64:__ADS1115_REG_CONFIG_DR_64SPS, 128:__ADS1115_REG_CONFIG_DR_128SPS, 250:__ADS1115_REG_CONFIG_DR_250SPS, 475:__ADS1115_REG_CONFIG_DR_475SPS, 860:__ADS1115_REG_CONFIG_DR_860SPS } spsADS1015 = { 128:__ADS1015_REG_CONFIG_DR_128SPS, 250:__ADS1015_REG_CONFIG_DR_250SPS, 490:__ADS1015_REG_CONFIG_DR_490SPS, 920:__ADS1015_REG_CONFIG_DR_920SPS, 1600:__ADS1015_REG_CONFIG_DR_1600SPS, 2400:__ADS1015_REG_CONFIG_DR_2400SPS, 3300:__ADS1015_REG_CONFIG_DR_3300SPS } # Dictionariy with the programable gains pgaADS1x15 = { 6144:__ADS1015_REG_CONFIG_PGA_6_144V, 4096:__ADS1015_REG_CONFIG_PGA_4_096V, 2048:__ADS1015_REG_CONFIG_PGA_2_048V, 1024:__ADS1015_REG_CONFIG_PGA_1_024V, 512:__ADS1015_REG_CONFIG_PGA_0_512V, 256:__ADS1015_REG_CONFIG_PGA_0_256V } def __init__(self, busId, slaveAddr=0x48, ic=__IC_ADS1115, debug=True): """Initializes I2C connection object with the ADX1x15. Note that the default address is 0x48 and the default device is the ADS1115. """ self.__i2c = SMBus(busId) # initializes I2C connection on /dev/i2c-<busID> self.__slave = slaveAddr # sets the address of the I2C slave device (the ADS1115) # Make sure the IC specified is valid if ((ic < self.__IC_ADS1015) | (ic > self.__IC_ADS1115)): if (self.debug): print "ADS1x15: Invalid IC specfied: %h" % ic return -1 else: self.ic = ic # Set pga value, so that getLastConversionResult() can use it, # any function that accepts a pga value must update this. self.pga = 6144 # turns on debug print statements self.debug = debug def __del__(self): del(self.__i2c) # deletes I2C connection def readADCSingleEnded(self, channel=0, pga=6144, sps=250): """Gets a single-ended ADC reading from the specified channel in mV. The sample rate for this mode (single-shot) can be used to lower the noise (low sps) or to lower the power consumption (high sps) by duty cycling, see datasheet page 14 for more info. The pga must be given in mV, see page 13 for the supported values.""" # With invalid channel return -1 if (channel > 3): if (self.debug): print "ADS1x15: Invalid channel specified: %d" % channel return -1 # Disable comparator, Non-latching, Alert/Rdy active low # traditional comparator, single-shot mode config = self.__ADS1015_REG_CONFIG_CQUE_NONE | \ self.__ADS1015_REG_CONFIG_CLAT_NONLAT | \ self.__ADS1015_REG_CONFIG_CPOL_ACTVLOW | \ self.__ADS1015_REG_CONFIG_CMODE_TRAD | \ self.__ADS1015_REG_CONFIG_MODE_SINGLE # Set sample per seconds, defaults to 250sps # If sps is in the dictionary (defined in init) it returns the value of the constant # othewise it returns the value for 250sps. This saves a lot of if/elif/else code! if (self.ic == self.__IC_ADS1015): config |= self.spsADS1015.setdefault(sps, self.__ADS1015_REG_CONFIG_DR_1600SPS) else: if ( (sps not in self.spsADS1115) & self.debug): print "ADS1x15: Invalid pga specified: %d, using 6144mV" % sps config |= self.spsADS1115.setdefault(sps, self.__ADS1115_REG_CONFIG_DR_250SPS) # Set PGA/voltage range, defaults to +-6.144V if ( (pga not in self.pgaADS1x15) & self.debug): print "ADS1x15: Invalid pga specified: %d, using 6144mV" % sps config |= self.pgaADS1x15.setdefault(pga, self.__ADS1015_REG_CONFIG_PGA_6_144V) self.pga = pga # Set the channel to be converted if channel == 3: config |= self.__ADS1015_REG_CONFIG_MUX_SINGLE_3 elif channel == 2: config |= self.__ADS1015_REG_CONFIG_MUX_SINGLE_2 elif channel == 1: config |= self.__ADS1015_REG_CONFIG_MUX_SINGLE_1 else: config |= self.__ADS1015_REG_CONFIG_MUX_SINGLE_0 # Set 'start single-conversion' bit config |= self.__ADS1015_REG_CONFIG_OS_SINGLE # Write config register to the ADC bytes = [(config >> 8) & 0xFF, config & 0xFF] self.__i2c.write_i2c_block_data(self.__slave, self.__ADS1015_REG_POINTER_CONFIG, bytes) # Wait for the ADC conversion to complete # The minimum delay depends on the sps: delay >= 1/sps # We add 0.1ms to be sure delay = 1.0/sps+0.0001 time.sleep(delay) # Read the conversion results result = self.__i2c.read_i2c_block_data(self.__slave, self.__ADS1015_REG_POINTER_CONVERT, 2) if (self.ic == self.__IC_ADS1015): # Shift right 4 bits for the 12-bit ADS1015 and convert to mV return ( ((result[0] << 8) | (result[1] & 0xFF)) >> 4 )*pga/2048.0 else: # Return a mV value for the ADS1115 # (Take signed values into account as well) val = (result[0] << 8) | (result[1]) if val > 0x7FFF: return (val - 0xFFFF)*pga/32768.0 else: return ( (result[0] << 8) | (result[1]) )*pga/32768.0 def readADCDifferential(self, chP=0, chN=1, pga=6144, sps=250): """Gets a differential ADC reading from channels chP and chN in mV. The sample rate for this mode (single-shot) can be used to lower the noise (low sps) or to lower the power consumption (high sps) by duty cycling, see data sheet page 14 for more info. The pga must be given in mV, see page 13 for the supported values.""" # Disable comparator, Non-latching, Alert/Rdy active low # traditional comparator, single-shot mode config = self.__ADS1015_REG_CONFIG_CQUE_NONE | \ self.__ADS1015_REG_CONFIG_CLAT_NONLAT | \ self.__ADS1015_REG_CONFIG_CPOL_ACTVLOW | \ self.__ADS1015_REG_CONFIG_CMODE_TRAD | \ self.__ADS1015_REG_CONFIG_MODE_SINGLE # Set channels if ( (chP == 0) & (chN == 1) ): config |= self.__ADS1015_REG_CONFIG_MUX_DIFF_0_1 elif ( (chP == 0) & (chN == 3) ): config |= self.__ADS1015_REG_CONFIG_MUX_DIFF_0_3 elif ( (chP == 2) & (chN == 3) ): config |= self.__ADS1015_REG_CONFIG_MUX_DIFF_2_3 elif ( (chP == 1) & (chN == 3) ): config |= self.__ADS1015_REG_CONFIG_MUX_DIFF_1_3 else: if (self.debug): print "ADS1x15: Invalid channels specified: %d, %d" % (chP, chN) return -1 # Set sample per seconds, defaults to 250sps # If sps is in the dictionary (defined in init()) it returns the value of the constant # othewise it returns the value for 250sps. This saves a lot of if/elif/else code! if (self.ic == self.__IC_ADS1015): config |= self.spsADS1015.setdefault(sps, self.__ADS1015_REG_CONFIG_DR_1600SPS) else: if ( (sps not in self.spsADS1115) & self.debug): print "ADS1x15: Invalid pga specified: %d, using 6144mV" % sps config |= self.spsADS1115.setdefault(sps, self.__ADS1115_REG_CONFIG_DR_250SPS) # Set PGA/voltage range, defaults to +-6.144V if ( (pga not in self.pgaADS1x15) & self.debug): print "ADS1x15: Invalid pga specified: %d, using 6144mV" % sps config |= self.pgaADS1x15.setdefault(pga, self.__ADS1015_REG_CONFIG_PGA_6_144V) self.pga = pga # Set 'start single-conversion' bit config |= self.__ADS1015_REG_CONFIG_OS_SINGLE # Write config register to the ADC bytes = [(config >> 8) & 0xFF, config & 0xFF] self.__i2c.write_i2c_block_data(self.__slave, self.__ADS1015_REG_POINTER_CONFIG, bytes) # Wait for the ADC conversion to complete # The minimum delay depends on the sps: delay >= 1/sps # We add 0.1ms to be sure delay = 1.0/sps+0.0001 time.sleep(delay) # Read the conversion results result = self.__i2c.read_i2c_block_data(self.__slave, self.__ADS1015_REG_POINTER_CONVERT, 2) # TODO: self.__i2c.read_i2c_block_data(self.address, reg, length) # consider making wrapper if (self.ic == self.__IC_ADS1015): # Shift right 4 bits for the 12-bit ADS1015 and convert to mV val = ((result[0] << 8) | (result[1] & 0xFF)) >> 4 # (Take signed values into account as well) if val >> 11: val = val - 0xfff return val*pga/2048.0 else: # Return a mV value for the ADS1115 # (Take signed values into account as well) val = (result[0] << 8) | (result[1]) if val > 0x7FFF: return (val - 0xFFFF)*pga/32768.0 else: return ( (result[0] << 8) | (result[1]) )*pga/32768.0 def startContinuousConversion(self, channel=0, pga=6144, sps=250): """Starts the continuous conversion mode and returns the first ADC reading in mV from the specified channel. The sps controls the sample rate. The pga must be given in mV, see datasheet page 13 for the supported values. Use getLastConversionResults() to read the next values and stopContinuousConversion() to stop converting.""" # Default to channel 0 with invalid channel, or return -1? if (channel > 3): if (self.debug): print "ADS1x15: Invalid channel specified: %d" % channel return -1 # Disable comparator, Non-latching, Alert/Rdy active low # traditional comparator, continuous mode # The last flag is the only change we need, page 11 datasheet config = self.__ADS1015_REG_CONFIG_CQUE_NONE | \ self.__ADS1015_REG_CONFIG_CLAT_NONLAT | \ self.__ADS1015_REG_CONFIG_CPOL_ACTVLOW | \ self.__ADS1015_REG_CONFIG_CMODE_TRAD | \ self.__ADS1015_REG_CONFIG_MODE_CONTIN # Set sample per seconds, defaults to 250sps # If sps is in the dictionary (defined in init()) it returns the value of the constant # othewise it returns the value for 250sps. This saves a lot of if/elif/else code! if (self.ic == self.__IC_ADS1015): config |= self.spsADS1015.setdefault(sps, self.__ADS1015_REG_CONFIG_DR_1600SPS) else: if ( (sps not in self.spsADS1115) & self.debug): print "ADS1x15: Invalid pga specified: %d, using 6144mV" % sps config |= self.spsADS1115.setdefault(sps, self.__ADS1115_REG_CONFIG_DR_250SPS) # Set PGA/voltage range, defaults to +-6.144V if ( (pga not in self.pgaADS1x15) & self.debug): print "ADS1x15: Invalid pga specified: %d, using 6144mV" % sps config |= self.pgaADS1x15.setdefault(pga, self.__ADS1015_REG_CONFIG_PGA_6_144V) self.pga = pga # Set the channel to be converted if channel == 3: config |= self.__ADS1015_REG_CONFIG_MUX_SINGLE_3 elif channel == 2: config |= self.__ADS1015_REG_CONFIG_MUX_SINGLE_2 elif channel == 1: config |= self.__ADS1015_REG_CONFIG_MUX_SINGLE_1 else: config |= self.__ADS1015_REG_CONFIG_MUX_SINGLE_0 # Set 'start single-conversion' bit to begin conversions # No need to change this for continuous mode! config |= self.__ADS1015_REG_CONFIG_OS_SINGLE # Write config register to the ADC # Once we write the ADC will convert continously # we can read the next values using getLastConversionResult bytes = [(config >> 8) & 0xFF, config & 0xFF] self.__i2c.write_i2c_block_data(self.__slave, self.__ADS1015_REG_POINTER_CONFIG, bytes) # Wait for the ADC conversion to complete # The minimum delay depends on the sps: delay >= 1/sps # We add 0.5ms to be sure delay = 1.0/sps+0.0005 time.sleep(delay) # Read the conversion results result = self.__i2c.read_i2c_block_data(self.__slave, self.__ADS1015_REG_POINTER_CONVERT, 2) if (self.ic == self.__IC_ADS1015): # Shift right 4 bits for the 12-bit ADS1015 and convert to mV return ( ((result[0] << 8) | (result[1] & 0xFF)) >> 4 )*pga/2048.0 else: # Return a mV value for the ADS1115 # (Take signed values into account as well) val = (result[0] << 8) | (result[1]) if val > 0x7FFF: return (val - 0xFFFF)*pga/32768.0 else: return ( (result[0] << 8) | (result[1]) )*pga/32768.0 def startContinuousDifferentialConversion(self, chP=0, chN=1, pga=6144, sps=250): """Starts the continuous differential conversion mode and returns the first ADC reading in mV as the difference from the specified channels. The sps controls the sample rate. The pga must be given in mV, see datasheet page 13 for the supported values. Use getLastConversionResults() to read the next values and stopContinuousConversion() to stop converting.""" # Disable comparator, Non-latching, Alert/Rdy active low # traditional comparator, continuous mode # The last flag is the only change we need, page 11 datasheet config = self.__ADS1015_REG_CONFIG_CQUE_NONE | \ self.__ADS1015_REG_CONFIG_CLAT_NONLAT | \ self.__ADS1015_REG_CONFIG_CPOL_ACTVLOW | \ self.__ADS1015_REG_CONFIG_CMODE_TRAD | \ self.__ADS1015_REG_CONFIG_MODE_CONTIN # Set sample per seconds, defaults to 250sps # If sps is in the dictionary (defined in init()) it returns the value of the constant # othewise it returns the value for 250sps. This saves a lot of if/elif/else code! if (self.ic == self.__IC_ADS1015): config |= self.spsADS1015.setdefault(sps, self.__ADS1015_REG_CONFIG_DR_1600SPS) else: if ( (sps not in self.spsADS1115) & self.debug): print "ADS1x15: Invalid pga specified: %d, using 6144mV" % sps config |= self.spsADS1115.setdefault(sps, self.__ADS1115_REG_CONFIG_DR_250SPS) # Set PGA/voltage range, defaults to +-6.144V if ( (pga not in self.pgaADS1x15) & self.debug): print "ADS1x15: Invalid pga specified: %d, using 6144mV" % sps config |= self.pgaADS1x15.setdefault(pga, self.__ADS1015_REG_CONFIG_PGA_6_144V) self.pga = pga # Set channels if ( (chP == 0) & (chN == 1) ): config |= self.__ADS1015_REG_CONFIG_MUX_DIFF_0_1 elif ( (chP == 0) & (chN == 3) ): config |= self.__ADS1015_REG_CONFIG_MUX_DIFF_0_3 elif ( (chP == 2) & (chN == 3) ): config |= self.__ADS1015_REG_CONFIG_MUX_DIFF_2_3 elif ( (chP == 1) & (chN == 3) ): config |= self.__ADS1015_REG_CONFIG_MUX_DIFF_1_3 else: if (self.debug): print "ADS1x15: Invalid channels specified: %d, %d" % (chP, chN) return -1 # Set 'start single-conversion' bit to begin conversions # No need to change this for continuous mode! config |= self.__ADS1015_REG_CONFIG_OS_SINGLE # Write config register to the ADC # Once we write the ADC will convert continously # we can read the next values using getLastConversionResult bytes = [(config >> 8) & 0xFF, config & 0xFF] self.__i2c.write_i2c_block_data(self.__slave, self.__ADS1015_REG_POINTER_CONFIG, bytes) # Wait for the ADC conversion to complete # The minimum delay depends on the sps: delay >= 1/sps # We add 0.5ms to be sure delay = 1.0/sps+0.0005 time.sleep(delay) # Read the conversion results result = self.__i2c.read_i2c_block_data(self.__slave, self.__ADS1015_REG_POINTER_CONVERT, 2) if (self.ic == self.__IC_ADS1015): # Shift right 4 bits for the 12-bit ADS1015 and convert to mV return ( ((result[0] << 8) | (result[1] & 0xFF)) >> 4 )*pga/2048.0 else: # Return a mV value for the ADS1115 # (Take signed values into account as well) val = (result[0] << 8) | (result[1]) if val > 0x7FFF: return (val - 0xFFFF)*pga/32768.0 else: return ( (result[0] << 8) | (result[1]) )*pga/32768.0 def stopContinuousConversion(self): """Stops the ADC's conversions when in continuous mode and resets the configuration to its default value.""" # Write the default config register to the ADC # Once we write, the ADC will do a single conversion and # enter power-off mode. config = 0x8583 # Page 18 datasheet. bytes = [(config >> 8) & 0xFF, config & 0xFF] self.__i2c.write_i2c_block_data(self.__slave, self.__ADS1015_REG_POINTER_CONFIG, bytes) return True def getLastConversionResults(self): """Returns the last ADC conversion result in mV""" # Read the conversion results result = self.__i2c.read_i2c_block_data(self.__slave, self.__ADS1015_REG_POINTER_CONVERT, 2) if (self.ic == self.__IC_ADS1015): # Shift right 4 bits for the 12-bit ADS1015 and convert to mV return ( ((result[0] << 8) | (result[1] & 0xFF)) >> 4 )*self.pga/2048.0 else: # Return a mV value for the ADS1115 # (Take signed values into account as well) val = (result[0] << 8) | (result[1]) if val > 0x7FFF: return (val - 0xFFFF)*self.pga/32768.0 else: return ( (result[0] << 8) | (result[1]) )*self.pga/32768.0 def startSingleEndedComparator(self, channel, thresholdHigh, thresholdLow, pga=6144, sps=250, activeLow=True, traditionalMode=True, latching=False, numReadings=1): """Starts the comparator mode on the specified channel, see datasheet pg. 15. In traditional mode it alerts (ALERT pin will go low) when voltage exceeds thresholdHigh until it falls below thresholdLow (both given in mV). In window mode (traditionalMode=False) it alerts when voltage doesn't lie between both thresholds. In latching mode the alert will continue until the conversion value is read. numReadings controls how many readings are necessary to trigger an alert: 1, 2 or 4. Use getLastConversionResults() to read the current value (which may differ from the one that triggered the alert) and clear the alert pin in latching mode. This function starts the continuous conversion mode. The sps controls the sample rate and the pga the gain, see datasheet page 13.""" # With invalid channel return -1 if (channel > 3): if (self.debug): print "ADS1x15: Invalid channel specified: %d" % channel return -1 # Continuous mode config = self.__ADS1015_REG_CONFIG_MODE_CONTIN if (activeLow==False): config |= self.__ADS1015_REG_CONFIG_CPOL_ACTVHI else: config |= self.__ADS1015_REG_CONFIG_CPOL_ACTVLOW if (traditionalMode==False): config |= self.__ADS1015_REG_CONFIG_CMODE_WINDOW else: config |= self.__ADS1015_REG_CONFIG_CMODE_TRAD if (latching==True): config |= self.__ADS1015_REG_CONFIG_CLAT_LATCH else: config |= self.__ADS1015_REG_CONFIG_CLAT_NONLAT if (numReadings==4): config |= self.__ADS1015_REG_CONFIG_CQUE_4CONV elif (numReadings==2): config |= self.__ADS1015_REG_CONFIG_CQUE_2CONV else: config |= self.__ADS1015_REG_CONFIG_CQUE_1CONV # Set sample per seconds, defaults to 250sps # If sps is in the dictionary (defined in init()) it returns the value of the constant # othewise it returns the value for 250sps. This saves a lot of if/elif/else code! if (self.ic == self.__IC_ADS1015): if ( (sps not in self.spsADS1015) & self.debug): print "ADS1x15: Invalid sps specified: %d, using 1600sps" % sps config |= self.spsADS1015.setdefault(sps, self.__ADS1015_REG_CONFIG_DR_1600SPS) else: if ( (sps not in self.spsADS1115) & self.debug): print "ADS1x15: Invalid sps specified: %d, using 250sps" % sps config |= self.spsADS1115.setdefault(sps, self.__ADS1115_REG_CONFIG_DR_250SPS) # Set PGA/voltage range, defaults to +-6.144V if ( (pga not in self.pgaADS1x15) & self.debug): print "ADS1x15: Invalid pga specified: %d, using 6144mV" % pga config |= self.pgaADS1x15.setdefault(pga, self.__ADS1015_REG_CONFIG_PGA_6_144V) self.pga = pga # Set the channel to be converted if channel == 3: config |= self.__ADS1015_REG_CONFIG_MUX_SINGLE_3 elif channel == 2: config |= self.__ADS1015_REG_CONFIG_MUX_SINGLE_2 elif channel == 1: config |= self.__ADS1015_REG_CONFIG_MUX_SINGLE_1 else: config |= self.__ADS1015_REG_CONFIG_MUX_SINGLE_0 # Set 'start single-conversion' bit to begin conversions config |= self.__ADS1015_REG_CONFIG_OS_SINGLE # Write threshold high and low registers to the ADC # V_digital = (2^(n-1)-1)/pga*V_analog if (self.ic == self.__IC_ADS1015): thresholdHighWORD = int(thresholdHigh*(2048.0/pga)) else: thresholdHighWORD = int(thresholdHigh*(32767.0/pga)) bytes = [(thresholdHighWORD >> 8) & 0xFF, thresholdHighWORD & 0xFF] self.__i2c.write_i2c_block_data(self.__slave, self.__ADS1015_REG_POINTER_HITHRESH, bytes) if (self.ic == self.__IC_ADS1015): thresholdLowWORD = int(thresholdLow*(2048.0/pga)) else: thresholdLowWORD = int(thresholdLow*(32767.0/pga)) bytes = [(thresholdLowWORD >> 8) & 0xFF, thresholdLowWORD & 0xFF] self.__i2c.write_i2c_block_data(self.__slave, self.__ADS1015_REG_POINTER_LOWTHRESH, bytes) # Write config register to the ADC # Once we write the ADC will convert continously and alert when things happen, # we can read the converted values using getLastConversionResult bytes = [(config >> 8) & 0xFF, config & 0xFF] self.__i2c.write_i2c_block_data(self.__slave, self.__ADS1015_REG_POINTER_CONFIG, bytes) # TODO: replace "writeList"... self.__i2c.write_i2c_block_data(self.address, reg, list) def startDifferentialComparator(self, chP, chN, thresholdHigh, thresholdLow, pga=6144, sps=250, activeLow=True, traditionalMode=True, latching=False, numReadings=1): """Starts the comparator mode on the specified channel, see datasheet pg. 15. In traditional mode it alerts (ALERT pin will go low) when voltage exceeds thresholdHigh until it falls below thresholdLow (both given in mV). In window mode (traditionalMode=False) it alerts when voltage doesn't lie between both thresholds. In latching mode the alert will continue until the conversion value is read. numReadings controls how many readings are necessary to trigger an alert: 1, 2 or 4. Use getLastConversionResults() to read the current value (which may differ from the one that triggered the alert) and clear the alert pin in latching mode. This function starts the continuous conversion mode. The sps controls the sample rate and the pga the gain, see datasheet page 13.""" # Continuous mode config = self.__ADS1015_REG_CONFIG_MODE_CONTIN if (activeLow==False): config |= self.__ADS1015_REG_CONFIG_CPOL_ACTVHI else: config |= self.__ADS1015_REG_CONFIG_CPOL_ACTVLOW if (traditionalMode==False): config |= self.__ADS1015_REG_CONFIG_CMODE_WINDOW else: config |= self.__ADS1015_REG_CONFIG_CMODE_TRAD if (latching==True): config |= self.__ADS1015_REG_CONFIG_CLAT_LATCH else: config |= self.__ADS1015_REG_CONFIG_CLAT_NONLAT if (numReadings==4): config |= self.__ADS1015_REG_CONFIG_CQUE_4CONV elif (numReadings==2): config |= self.__ADS1015_REG_CONFIG_CQUE_2CONV else: config |= self.__ADS1015_REG_CONFIG_CQUE_1CONV # Set sample per seconds, defaults to 250sps # If sps is in the dictionary (defined in init()) it returns the value of the constant # othewise it returns the value for 250sps. This saves a lot of if/elif/else code! if (self.ic == self.__IC_ADS1015): if ( (sps not in self.spsADS1015) & self.debug): print "ADS1x15: Invalid sps specified: %d, using 1600sps" % sps config |= self.spsADS1015.setdefault(sps, self.__ADS1015_REG_CONFIG_DR_1600SPS) else: if ( (sps not in self.spsADS1115) & self.debug): print "ADS1x15: Invalid sps specified: %d, using 250sps" % sps config |= self.spsADS1115.setdefault(sps, self.__ADS1115_REG_CONFIG_DR_250SPS) # Set PGA/voltage range, defaults to +-6.144V if ( (pga not in self.pgaADS1x15) & self.debug): print "ADS1x15: Invalid pga specified: %d, using 6144mV" % pga config |= self.pgaADS1x15.setdefault(pga, self.__ADS1015_REG_CONFIG_PGA_6_144V) self.pga = pga # Set channels if ( (chP == 0) & (chN == 1) ): config |= self.__ADS1015_REG_CONFIG_MUX_DIFF_0_1 elif ( (chP == 0) & (chN == 3) ): config |= self.__ADS1015_REG_CONFIG_MUX_DIFF_0_3 elif ( (chP == 2) & (chN == 3) ): config |= self.__ADS1015_REG_CONFIG_MUX_DIFF_2_3 elif ( (chP == 1) & (chN == 3) ): config |= self.__ADS1015_REG_CONFIG_MUX_DIFF_1_3 else: if (self.debug): print "ADS1x15: Invalid channels specified: %d, %d" % (chP, chN) return -1 # Set 'start single-conversion' bit to begin conversions config |= self.__ADS1015_REG_CONFIG_OS_SINGLE # Write threshold high and low registers to the ADC # V_digital = (2^(n-1)-1)/pga*V_analog if (self.ic == self.__IC_ADS1015): thresholdHighWORD = int(thresholdHigh*(2048.0/pga)) else: thresholdHighWORD = int(thresholdHigh*(32767.0/pga)) bytes = [(thresholdHighWORD >> 8) & 0xFF, thresholdHighWORD & 0xFF] self.__i2c.write_i2c_block_data(self.__slave, self.__ADS1015_REG_POINTER_HITHRESH, bytes) if (self.ic == self.__IC_ADS1015): thresholdLowWORD = int(thresholdLow*(2048.0/pga)) else: thresholdLowWORD = int(thresholdLow*(32767.0/pga)) bytes = [(thresholdLowWORD >> 8) & 0xFF, thresholdLowWORD & 0xFF] self.__i2c.write_i2c_block_data(self.__slave, self.__ADS1015_REG_POINTER_LOWTHRESH, bytes) # Write config register to the ADC # Once we write the ADC will convert continously and alert when things happen, # we can read the converted values using getLastConversionResult bytes = [(config >> 8) & 0xFF, config & 0xFF] self.__i2c.write_i2c_block_data(self.__slave, self.__ADS1015_REG_POINTER_CONFIG, bytes)
class daq: def __init__(self, fs=1666): self.__name__ = "daq" try: self.bus = SMBus(1) print("bus connected") except Exception as e: print("ERROR ", e) self.dev = [] self.fs = fs self.dt = 1/self.fs self.state = 1 self.raw = 1 self.G = 9.81 self.Rot = np.pi self.odr = 9 #8=1666Hz 9=3330Hz 10=6660Hz self.range = [1, 3] #[16G, 2000DPS] for device in range(128): try: self.bus.read_byte(device) if device == 0x6a: self.dev.append([device, 0x22, 12, '<hhhhhh',['A_'+'Gx','A_'+'Gy','A_'+'Gz','A_'+'Ax','A_'+'Ay','A_'+'Az'], None]) elif device == 0x6b: self.dev.append([device, 0x22, 12, '<hhhhhh',['B_'+'Gx','B_'+'Gy','B_'+'Gz','B_'+'Ax','B_'+'Ay','B_'+'Az'], None]) elif device == 0x36: self.dev.append([device, 0x0C, 2, '>H',['rot'], None]) elif device == 0x48: self.dev.append([device, 0x00, 2, '>h', ['cur'], None]) self.config(device) print("Device Config: ", device) except Exception as e: #print("ERROR ", e) pass self.N = len(self.dev) def config(self, _device): _settings = None if _device == 0x6a or _device == 0x6b: _settings = [[0x10, (self.odr<<4 | self.range[0]<<2 | 1<<1)], [0x11, (self.odr<<4 | self.range[1]<<2)], [0x12, 0x44], [0x13, 1<<1], [0x15, 0b011], [0X17, (0b000 <<5)]] #[0x44 is hardcoded acording to LSM6DSO datasheet] for _set in _settings: try: self.bus.write_byte_data(_device, _set[0], _set[1]) except Exception as e: print("ERROR: ",e) elif _device == 0x48: _config = (3<<9 | 0<<8 | 4<<5 | 3) _settings = [0x01, [_config>>8 & 0xFF, _config & 0xFF]] try: self.bus.write_i2c_block_data(_device, _settings[0], _settings[1]) except Exception as e: print("ERROR: ",e) else: pass def pull(self, _device): return unpack(_device[3], bytearray(self.bus.read_i2c_block_data(_device[0],_device[1], _device[2]))) def pulldata(self, _size = 1): self.q = queue.Queue() gc.collect() self.state = 1 if int(_size) == 0: t0=tf = time.perf_counter() while self.state: ti=time.perf_counter() if ti-tf>=self.dt: tf = ti for _j in range(self.N): try: self.q.put(self.bus.read_i2c_block_data(self.dev[_j][0],self.dev[_j][1],self.dev[_j][2])) except Exception as e: self.q.put((0,)*self.dev[_j][2]) print(e) t1 = time.perf_counter() print(t1-t0) else: Ns = int(_size)//self.dt i=0 t0=tf = time.perf_counter() while i < Ns: ti=time.perf_counter() if ti-tf>=self.dt: tf = ti i+=1 for _j in range(self.N): try: self.q.put(self.bus.read_i2c_block_data(self.dev[_j][0],self.dev[_j][1],self.dev[_j][2])) except Exception as e: self.q.put((0,)*self.dev[_j][2]) print(e) t1 = time.perf_counter() print(t1-t0) return self.q def savedata(self, _q): os.chdir(root) if 'DATA' not in os.listdir(): os.mkdir('DATA') os.chdir('DATA') _path = 'data_{}.csv'.format(len(os.listdir())) #os.mkdir(_path) #os.chdir(_path) head=['t'] #print(head) data = self.to_num(_q) N = len(data[str(self.dev[0][0])]) data_out = np.linspace(0, N*self.dt, N).reshape((N,1)) print(data_out.shape) for _j in range(self.N): arr = np.array(data[str(self.dev[_j][0])]) head = head+self.dev[_j][-2] print(head) if str(self.dev[_j][0]) == '54': if self.dev[_j][-1] != None: _scale = np.load(root+'/sensors/'+self.dev[_j][-1]) data_out = np.hstack((data_out, sp.fix_outlier(arr*_scale))) else: data_out = np.hstack((data_out, arr)) elif str(self.dev[_j][0]) == '106' or str(self.dev[_j][0]) == '107': if self.dev[_j][-1] != None: #_param = np.load(root+'/sensors/'+self.dev[_j][-1], allow_pickle=True) params = pd.read_csv(root+'/sensors/'+self.dev[_j][-1], index_col=0) data_out = np.hstack((data_out, np.hstack((self.transl(arr[:,0:3], params['gyr_p'].to_numpy()), self.transl(arr[:,3:6], params['acc_p'].to_numpy()))))) else: data_out = np.hstack((data_out, arr)) elif str(self.dev[_j][0]) == '72': _scale = np.load(root+'/sensors/'+self.dev[_j][-1]) data_out = np.hstack((data_out, (arr.astype('int')>>4)*_scale)) print(data_out) frame = {} for jj in range(len(head)): frame[head[jj]]=data_out[:,jj] df = pd.DataFrame(frame) df.to_csv(_path, index=False) print('{} saved'.format(_path)) return data_out def to_num(self, _q): _data={} for _j in range(self.N): _data[str(self.dev[_j][0])] = [] while _q.qsize()>0: for _j in range(self.N): _data[str(self.dev[_j][0])].append(unpack(self.dev[_j][-3], bytearray(_q.get()))) return _data def transl(self, _data, X): _T = np.array(X[0:9].reshape((3,3))) _b = np.array(X[-3:]).reshape((3,1)) _data_out = _T@(_data.T-_b) return _data_out.T def calibrate(self, _device): os.chdir(root) _sensname = input('Connnect sensor and name it: ') _sensor = {'name': _sensname} self._caldata = [] print('Iniciando 6 pos calibration') NS = int((input('KiloSamples/Position: ') or 6)*1000) for _n in range(6): input('Position {}'.format(_n+1)) i=0 tf = time.perf_counter() while i<self.Ns: ti=time.perf_counter() if ti-tf>=self.dt: tf = ti i+=1 self._caldata.append(self.pull(_device)) ND = int((input('KiloSamples/Rotation: ') or 6)*1000) for _n in range(0,6,2): input('Rotate 180 deg around axis {}-{}'.format(_n+1,_n+2)) i=0 tf = time.perf_counter() while i<ND: ti=time.perf_counter() if ti-tf>=self.dt: tf = ti i+=1 self._caldata.append(self.pull(_device)) _data = np.array(self._caldata) self.acc_raw = _data[0:6*NS,3:6] self.gyr_raw = _data[:,0:3] np.save('./sensors/'+_sensor['name']+'rawdata.npy', _data) print('Calculating calibration parameters. Wait...') gc.collect() _sensor['acc_p'] = self.calibacc(self.acc_raw, NS) gc.collect() _sensor['gyr_p'] = self.calibgyr(self.gyr_raw, NS, ND) np.savez('./sensors/'+_sensor['name'], _sensor['gyr_p'], _sensor['acc_p']) print(_sensor['name']+' saved') gc.collect() def calibacc(self, _accdata, NS): #mean values for the 6 positions aux=[] for ii in range(6): aux.append(_accdata[ii*NS:(ii+1)*NS,:].mean(0)) a_m = np.array(aux).T #determination of biases aux=[] for ii in range(3): aux.append((a_m[ii,:].max() + a_m[ii,:].min()) / 2) b = np.array(aux, ndmin=2).T #unbiased mean values and expected (real) mean values a_mu = a_m-b a_mr = np.zeros_like(a_mu) for ii in range(3): a_mr[ii,a_mu[ii,:].argmax()] = self.G a_mr[ii,a_mu[ii,:].argmin()] = -self.G #transformation matrix T = a_mr@pinv(a_mu) _param = np.append(T.flatten(), b.T) return _param def calibgyr(self, _gyrdata, NS, ND): g_s = _gyrdata[0:6*NS,:] #static gyro data g_d = _gyrdata[6*NS:,:] #dynamic gyro data b = g_s.mean(0).reshape(3,1) #bias from mean static measurements # integrate dynamic rates to determine total angle g_dm = np.zeros((3,3)) for ii in range(3): g_dm[ii,:] = np.abs(intg.trapz(g_d[ii*ND:(ii+1)*ND,:].T-b,dx=self.dt , axis=1)) g_dr = np.zeros_like(g_dm) for ii in range(3): g_dr[ii,g_dm[ii,:].argmax()] = self.Rot T = g_dr@inv(g_dm) _param = np.append(T.flatten(), b.T) return _param
#https://www.pololu.com/file/download/LPS25H.pdf?file_id=0J761 from smbus import SMBus busNum = 1 b = SMBus(busNum) PTS = 0x5d #Device I2C slave address PTS_WHOAMI = 0b1011101 #Device self-id (chip_id, version) = b.read_i2c_block_data(PTS, 0xD0, 2) print "Chip Id:", chip_id, "Version:", version if b.read_byte_data(PTS, 0x0f) == PTS_WHOAMI: print 'LPS25H detected successfully.' else: print 'No LPS25H detected on bus '+str(busNum)+'.'
class atm90e26(object): def __init__(self): self.atm90e26_addrs = { 'SoftReset' : { 'addr': 0x00, }, 'SysStatus' : { 'addr': 0x01, }, 'FuncEn' : { 'addr': 0x02, }, 'SagTh' : { 'addr': 0x03, }, 'SmallPMod' : { 'addr': 0x04, }, 'LastData' : { 'addr': 0x06, }, 'CalStart' : { 'addr': 0x20, }, 'PLconstH' : { 'addr': 0x21, }, 'PLconstL' : { 'addr': 0x22, }, 'Lgain' : { 'addr': 0x23, }, 'Lphi' : { 'addr': 0x24, }, 'Ngain' : { 'addr': 0x25, }, 'Nphi' : { 'addr': 0x26, }, 'PStartTh' : { 'addr': 0x27, }, 'PNolTh' : { 'addr': 0x28, }, 'QStartTh' : { 'addr': 0x29, }, 'QNolTh' : { 'addr': 0x2a, }, 'MMode' : { 'addr': 0x2b, }, 'CS1' : { 'addr': 0x2c, }, 'AdjStart' : { 'addr': 0x30, }, 'Ugain' : { 'addr': 0x31, }, 'IgainL' : { 'addr': 0x32, }, 'IgainN' : { 'addr': 0x33, }, 'Uoffset' : { 'addr': 0x34, }, 'IoffsetL' : { 'addr': 0x35, }, 'IoffsetN' : { 'addr': 0x36, }, 'PoffsetL' : { 'addr': 0x37, }, 'QoffsetL' : { 'addr': 0x38, }, 'PoffsetN' : { 'addr': 0x39, }, 'QoffsetN' : { 'addr': 0x3a, }, 'CS2' : { 'addr': 0x3b }, 'APenergy' : { 'addr': 0x40, 'prec': 0.1, 'unit': 'kJ'}, 'ANenergy' : { 'addr': 0x41, 'prec': 0.1, 'unit': 'kJ'}, 'ATenergy' : { 'addr': 0x42, 'prec': 0.1, 'unit': 'kJ'}, 'RPenergy' : { 'addr': 0x43, 'prec': 0.1, 'unit': 'kJ'}, 'RNenergy' : { 'addr': 0x44, 'prec': 0.1, 'unit': 'kJ'}, 'RTenergy' : { 'addr': 0x45, 'prec': 0.1, 'unit': 'kJ'}, 'EnStatus' : { 'addr': 0x46, }, 'Irms' : { 'addr': 0x48, 'prec': 0.001, 'unit': 'A'}, 'Urms' : { 'addr': 0x49, 'prec': 0.01, 'unit': 'V'}, 'Pmean' : { 'addr': 0x4a, 'prec': 0.001, 'sgn': 'complement', 'unit': 'kW'}, 'Qmean' : { 'addr': 0x4b, 'prec': 0.001, 'sgn': 'complement', 'unit': 'kVAR'}, 'Freq' : { 'addr': 0x4c, 'prec': 0.01, 'unit': 'Hz'}, 'PowerF' : { 'addr': 0x4d, 'sgn': 'msb', 'prec': 0.001, }, 'Pangle' : { 'addr': 0x4e, 'prec': 0.1, 'sgn': 'msb', 'unit': 'deg'}, 'Smean' : { 'addr': 0x4f, 'prec': 0.001, 'sgn': 'complement', 'unit': 'kVA'}, 'Irms2' : { 'addr': 0x68, 'prec': 0.001, 'unit': 'A'}, 'Pmean2' : { 'addr': 0x6a, 'prec': 0.001, 'sgn': 'complement', 'unit': 'kW'}, 'Qmean2' : { 'addr': 0x6b, 'prec': 0.001, 'sgn': 'complement', 'unit': 'kVAR'}, 'PowerF2' : { 'addr': 0x6d, 'sgn': 'msb', 'prec': 0.001, }, 'Pangle2' : { 'addr': 0x6e, 'prec': 0.1, 'sgn': 'msb', 'unit': 'deg'}, 'SmeanF' : { 'addr': 0x4f, 'prec': 0.001, 'sgn': 'complement', 'unit': 'kVA'}, } self.atm90e26_reverse_addrs = {} for name in self.atm90e26_addrs: self.atm90e26_reverse_addrs[self.atm90e26_addrs[name]['addr']] = name self.calibvals = { 'funcen': 0x0, 'calibration': [ ('PLconstH', 0x1c), ('PLconstL', 0xa90e), ('Lgain', 0x0), ('Lphi', 0x0), ('Ngain', 0x0), ('Nphi', 0x0), ('PStartTh', 0x8bd), ('PNolTh', 0x0), ('QStartTh', 0xaec), ('QNolTh', 0x0), ('MMode', 0x9422 & ~0xe000), # switch to 4x on current sense amp ], 'adjustment': [ ('Ugain', 14949), ('IgainL', 0x8d88), ('IgainN', 0x0), ('Uoffset', 0x0), ('IoffsetL', 0x0), ('IoffsetN', 0x0), ('PoffsetL', 0x0), ('QoffsetL', 0x0), ('PoffsetN', 0x0), ('QoffsetN', 0x0), ], } self.magic = { 'reset': 0x789a, 'cal_mode': 0x5678, 'check_mode': 0x8765, 'small_power': 0xa987, } def loadCalibration(self,cdata): for section in self.calibvals: if cdata.get(section,None) is not None: for varn in cdata[section]: val = cdata[section][varn] if val < 0: val = -val val |= 0x8000 if isinstance(val,str): val = int(val,16) idx = 0 while idx < len(self.calibvals[section]): if self.calibvals[section][idx][0] == varn: print('Overriding default calibration for ' + varn + ' = ' + str(val)) self.calibvals[section][idx] = (varn, val) break idx += 1 def setup(self, iftype = 'i2c'): if iftype == 'i2c': from smbus import SMBus self.bus = SMBus(1) self.addr = 0x32 self.iftype = iftype elif iftype == 'spi': import spidev self.spi = spidev.SpiDev() self.spi.open(0, 0) self.spi_speed_hz = 500000 self.spi.max_speed_hz = self.spi_speed_hz self.spi.mode = 0x3 self.spi_bits_per_byte = 8 self.spi_cs_delay = 10 self.iftype = iftype else: self.iftype = None def reset(self): def writeBunch(self, pairs): chk_l = 0 chk_h = 0 regnames = [] plh_wr_stored = None for regpair in pairs: if False: cs1_afe = self.getReg('CS1') debugprint('CS1: {:04x}'.format(cs1_afe['raw'])) vn = regpair[0] regnames.append(vn) wrval = regpair[1] # increment the checksum calculation wrv_l = wrval & 0xff wrv_h = (wrval >> 8) & 0xff chk_h ^= wrv_h chk_h ^= wrv_l chk_l += wrv_h chk_l += wrv_l self.setReg(vn, wrval) time.sleep(0.01) res0 = self.getReg(vn) time.sleep(0.01) # handle PLconstH specially, since it won't show its # new value until PLconstL has been written if vn == 'PLconstH': plh_wr_stored = wrval else: if not res0 or res0['raw'] != wrval: debugprint('[{}] wrote: {:04x} got {:04x}'.format(vn, wrval,res0['raw'])) if vn == 'PLconstL': res1 = self.getReg('PLconstH') if not res1 or res1['raw'] != plh_wr_stored: debugprint('[{}] wrote: {:04x} got {:04x}'.format('PLconstH', plh_wr_stored, res1['raw'])) chk_l &= 0xff debugprint('MY chk_h: {:02x} chk_l: {:02x}'.format(chk_h,chk_l)) return (chk_h << 8) | chk_l debugprint('- Resetting atm90e26 chip and setting calibration registers.') self.setReg('SoftReset', self.magic['reset']) time.sleep(0.5) if True: self.setReg('CalStart', self.magic['cal_mode']) mychk = writeBunch(self, self.calibvals['calibration']) self.setReg('CS1',mychk) self.setReg('CalStart', self.magic['check_mode']) if True: self.setReg('AdjStart', self.magic['cal_mode']) mychk = writeBunch(self, self.calibvals['adjustment']) self.setReg('CS2',mychk) self.setReg('AdjStart', self.magic['check_mode']) if True: cs1_afe = self.getReg('CS1') cs2_afe = self.getReg('CS2') sys_afe = self.getReg('SysStatus') debugprint('CS1: {:04x} CS2: {:04x} SysStatus: {:04x}'.format(cs1_afe['raw'],cs2_afe['raw'],sys_afe['raw'])) def spi_xfer(self, outd): ind = self.spi.xfer2(outd, self.spi_speed_hz, self.spi_cs_delay, self.spi_bits_per_byte) return ind def _startRead_i2c(self, aname): reginfo = self.atm90e26_addrs.get(aname,None) if not reginfo: return None try: addr = reginfo['addr'] self.bus.write_i2c_block_data(self.addr,addr | 0x80,[0,0]) #time.sleep(0.5) return reginfo['addr'] except Exception as e: debugprint('- Error writing to i2c device.'); debugprint(e) try: debugprint('- attempting to restart i2c') self.__init__() self.reset() except Exception as f: pass return False def setReg(self, aname, data): reginfo = self.atm90e26_addrs.get(aname,None) if not reginfo: return None addr = reginfo['addr'] d1 = (data >> 8) & 0xff d0 = data & 0xff try: if self.iftype == 'i2c': self.bus.write_i2c_block_data(self.addr,addr & ~0x80,[d1,d0]) time.sleep(0.05) else: self.spi_xfer([addr & ~0x80, d1, d0]) return True except Exception as e: debugprint('- Error writing to hardware device: {0}'.format(repr(e))) try: debugprint('- attempting to restart device') self.__init__() self.reset() except Exception as f: pass return False def _finishRead_i2c(self): tries = 10 while tries: try: data = self.bus.read_i2c_block_data(self.addr, 1, 4) if data[0] == 0x12: addr = data[1] & ~0x80; # address without msb word = (data[2] << 8) | data[3] return { 'addr': addr, 'word': word } else: tries -= 1 time.sleep(0.01) except Exception as e: debugprint('Exception reading state: {0}'.format(e)) tries -= 1; time.sleep(0.10) try: self.__init__() except Exception as f: pass #debugprint('_finishRead_i2c tries: {0}'.format(tries)) return None def _polishRead(self, rawres): if rawres: name = self.atm90e26_reverse_addrs.get(rawres['addr'],'_unknown') fmt = self.atm90e26_addrs.get(name,None) word = rawres['word'] val = word + 0 unit = '' if fmt: sgn = fmt.get('sgn','unsigned') if sgn == 'unsigned': pass elif sgn == 'complement': if (word & 0x8000): val -= 65535 elif sgn == 'msb': if (word & 0x8000): word &= ~0x8000 val = -word prec = fmt.get('prec',1) val *= prec unit = fmt.get('unit','') return { 'addr': rawres['addr'], 'aname': name, 'raw': word, 'value': val, 'unit': unit } return None def getReg(self, aname): if self.iftype == 'i2c': return self.getReg_i2c(aname) else: return self.getReg_spi(aname) def getReg_spi(self, aname): reginfo = self.atm90e26_addrs.get(aname,None) if not reginfo: return None addr = reginfo['addr'] try: outd = [ addr | 0x80, 0, 0 ] rdata = self.spi_xfer(outd) word0 = rdata[1] << 8 | rdata[2] outd = [ self.atm90e26_addrs['LastData']['addr'] | 0x80, 0, 0 ] rdata = self.spi_xfer(outd) word1 = rdata[1] << 8 | rdata[2] if word0 == word1: res0 = { 'addr': addr, 'word': word0, } return self._polishRead(res0) except Exception as e: debugprint('Exception reading from SPI: {0}'.format(repr(e))) return None def getReg_i2c(self, aname): tries =10 while tries: reqaddr = self._startRead_i2c(aname) if reqaddr: time.sleep(0.001) res0 = self._finishRead_i2c() lastaddr = self._startRead_i2c('LastData') if lastaddr: time.sleep(0.001) res1 = self._finishRead_i2c() if res1: a0match = res0['addr'] == reqaddr a1match = res1['addr'] == self.atm90e26_addrs['LastData']['addr'] vmatch = res0['word'] == res1['word'] if a0match and a1match and vmatch: return self._polishRead(res0) else: if not a0match: debugprint('Request return addr {:02x} does not match requested {:02x}'.format(res0['addr'],reqaddr)) if not a1match: debugprint('LastData return addr {:02x} does not match requested {:02x}'.format(res1['addr'],self.atm90e26_addrs['LastData']['addr'])) if not vmatch: debugprint('Read value {:04x} does not match LastData value {:04x}'.format(res0['word'],res1['word'])) else: debugprint("no reqaddr. Maybe {0} isn't right?".format(aname)) tries -= 1 debugprint('getReg tries: {0}'.format(tries)) return None def getRegs(self, names): res = {} for name in names: res[name] = self.getReg(name) return res
class TemperaturePressure: address = 0x77 oversampling = 3 # 0..3 def __init__(self): # 0 for R-Pi Rev. 1, 1 for Rev. 2 self.bus = SMBus(1) # Read whole calibration EEPROM data cal = self.bus.read_i2c_block_data(self.address, 0xAA, 22) # Convert byte data to word values self.ac1 = get_short(cal, 0) self.ac2 = get_short(cal, 2) self.ac3 = get_short(cal, 4) self.ac4 = get_ushort(cal, 6) self.ac5 = get_ushort(cal, 8) self.ac6 = get_ushort(cal, 10) self.b1 = get_short(cal, 12) self.b2 = get_short(cal, 14) self.mb = get_short(cal, 16) self.mc = get_short(cal, 18) self.md = get_short(cal, 20) return def read(self): # temperature conversion self.bus.write_byte_data(self.address, 0xF4, 0x2E) sleep(0.005) (msb, lsb) = self.bus.read_i2c_block_data(self.address, 0xF6, 2) ut = (msb << 8) + lsb # pressure conversion self.bus.write_byte_data(self.address, 0xF4, 0x34 + (self.oversampling << 6)) sleep(0.04) (msb, lsb, xsb) = self.bus.read_i2c_block_data(self.address, 0xF6, 3) up = ((msb << 16) + (lsb << 8) + xsb) >> (8 - self.oversampling) # calculate temperature x1 = ((ut - self.ac6) * self.ac5) >> 15 x2 = (self.mc << 11) / (x1 + self.md) b5 = x1 + x2 t = (b5 + 8) >> 4 # calculate pressure b6 = b5 - 4000 b62 = b6 * b6 >> 12 x1 = (self.b2 * b62) >> 11 x2 = self.ac2 * b6 >> 11 x3 = x1 + x2 b3 = (((self.ac1 * 4 + x3) << self.oversampling) + 2) >> 2 x1 = self.ac3 * b6 >> 13 x2 = (self.b1 * b62) >> 16 x3 = ((x1 + x2) + 2) >> 2 b4 = (self.ac4 * (x3 + 32768)) >> 15 b7 = (up - b3) * (50000 >> self.oversampling) p = (b7 * 2) / b4 x1 = (p >> 8) * (p >> 8) x1 = (x1 * 3038) >> 16 x2 = (-7357 * p) >> 16 p = p + ((x1 + x2 + 3791) >> 4) return (t/10.0, p / 100)
addr = 0x77 oversampling = 3 # 0..3 bus = SMBus(2); # 0 for R-Pi Rev. 1, 1 for Rev. 2 # 2 for BeagleBone Green using Grove connector # return two bytes from data as a signed 16-bit value def get_short(data, index): return c_short((data[index] << 8) + data[index + 1]).value # return two bytes from data as an unsigned 16-bit value def get_ushort(data, index): return (data[index] << 8) + data[index + 1] (chip_id, version) = bus.read_i2c_block_data(addr, 0xD0, 2) print "Chip Id:", chip_id, "Version:", version print print "Reading calibration data..." # Read whole calibration EEPROM data cal = bus.read_i2c_block_data(addr, 0xAA, 22) # Convert byte data to word values ac1 = get_short(cal, 0) ac2 = get_short(cal, 2) ac3 = get_short(cal, 4) ac4 = get_ushort(cal, 6) ac5 = get_ushort(cal, 8) ac6 = get_ushort(cal, 10) b1 = get_short(cal, 12)
#leer aceptador de monedas before = int(time.time()) #se necesita esto aqui? if modo_serial == 'usb': bytesToRead = ser_acc.inWaiting() elif modo_serial == 'i2c': #aca viene lo de Jose Velarde bytesToRead = 0 pass #leer rfid if modo_serial == 'usb': pass elif modo_serial == 'i2c': try: rfid_id = bus.read_i2c_block_data(0x04,0,4) except: pass if bytesToRead > 0: formadepago = "cash" try: os.system('mpg123 -q iguino_sounds/_iguino_beep2.mp3 &') except: print('no se puedo reproducir audio de moneda') now = int(time.time()) #se necesita esto aqui? process_id = 1 if modo_serial == 'i2c':
irqPin = 17 # IRQ pin for MCP23017 os.system("sudo modprobe uinput") ui = UInput({e.EV_KEY: key}, name="retrogame", bustype=e.BUS_USB) bus = SMBus(1) IODIRA = 0x00 IOCONA = 0x0A INTCAPA = 0x10 # Initial MCP23017 config: bus.write_byte_data(addr, 0x05 , 0x00) # If bank 1, switch to 0 bus.write_byte_data(addr, IOCONA, 0x44) # Bank 0, INTB=A, seq, OD IRQ # Read/modify/write remaining MCP23017 config: cfg = bus.read_i2c_block_data(addr, IODIRA, 14) cfg[ 0] = 0xFF # Input bits cfg[ 1] = 0xFF cfg[ 2] = 0x00 # Polarity cfg[ 3] = 0x00 cfg[ 4] = 0xFF # Interrupt pins cfg[ 5] = 0xFF cfg[12] = 0xFF # Pull-ups cfg[13] = 0xFF bus.write_i2c_block_data(addr, IODIRA, cfg) # Clear interrupt by reading INTCAP and GPIO registers x = bus.read_i2c_block_data(addr, INTCAPA, 4) oldState = x[2] | (x[3] << 8) # Callback for MCP23017 interrupt request
class MCP9804Sensor(object): """Represents an MCP9820 i2c sensor connected to a GPIO pin""" def __init__(self, connections, logger, params, sensors, actuators): """Sets the sensor pin to pud and publishes its current value""" self.lastpoll = time.time() #Initialise to some time ago (make sure it publishes) self.lastPublish = time.time() - 1000 self.logger = logger self.sensorMode = params("Mode") # Note the int(xx, 16) here as this is Hex (base 16) in the Config self.addr = int(params("Address"), 16) # 0x1f self.bus = SMBus(int(params("Bus"))) # 1 self.precisionTemp = int(params("PrecisionTemp")) self.useF = False try: if (params("Scale") == 'F'): self.useF = True except ConfigParser.NoOptionError: pass #Use 1 reading as default self.ARRAY_SIZE = 1 if (self.sensorMode == "Advanced"): #Array size of last readings self.ARRAY_SIZE = 5 #Initialize Array self.arrTemperature = [None] * self.ARRAY_SIZE self.temperature = None self.forcePublishInterval = 60 self.destination = params("Destination") self.poll = float(params("Poll")) self.publish = connections self.logger.info( "----------Configuring MCP9804 Sensor: bus='{0}' address='{1}' poll='{2}' destination='{3}' Initial values: Temp='{4}'" .format(self.bus, self.addr, self.poll, self.destination, self.temperature)) self.publishState() def wakeup(self): try: self.bus.write_word_data(self.addr, 1, 0x0000) except: self.logger.warn("Wakeup failed..") def shutdown(self): try: self.bus.write_word_data(self.addr, 1, 0x0001) except: self.logger.warn("Shutdown failed..") def convertTemp(self, value): return value if self.useF == False else value * 9 / 5.0 + 32 def checkState(self): """Detects and publishes any state change""" hasChanged = False valueTemp = self.readSensor(True) if (valueTemp is None): self.logger.warn( "Last reading isn't valid. preserving old reading T='{0}'". format(self.temperature)) return #Verify reading of temperature if (valueTemp != self.temperature): self.temperature = valueTemp hasChanged = True if (hasChanged or (time.time() - self.lastPublish) > self.forcePublishInterval): self.publishState() def publishStateImpl(self, data, destination): for conn in self.publish: conn.publish(data, destination) def publishState(self): """Publishes the current state""" didPublish = False if (self.temperature is not None): didPublish = True strTemp = str(round(self.temperature, self.precisionTemp)) self.logger.debug("Publish temperature '{0}' to '{1}'".format( strTemp, self.destination + "/temperature")) self.publishStateImpl(strTemp, self.destination + "/temperature") if (didPublish): self.lastPublish = time.time() def isReadingValid(self, value, acceptableMin, acceptableMax): if (value is None): return False if ((value >= acceptableMin) and (value <= acceptableMax)): return True return False def readSensor(self, shutdown=True): resultTemp = None valueTemp = float(-99) try: if shutdown: self.wakeup() time.sleep(0.36) msb, lsb = self.bus.read_i2c_block_data(self.addr, 5, 2) if shutdown: self.shutdown() tcrit = msb >> 7 & 1 tupper = msb >> 6 & 1 tlower = msb >> 5 & 1 temperature = (msb & 0xf) * 16 + lsb / 16.0 if msb >> 4 & 1: temperature = 256 - temperature valueTemp = float(temperature) except IOError as ex: self.logger.debug("ERROR - {0} - {1}".format( ex.errno, ex.strerror)) finally: if shutdown: try: self.shutdown() except Exception as e: self.logger.debug("ERROR - {0} {1}".format( e.errno, e.strerror)) #print("Raw reading T:{0}".format(valueTemp )) # Is temperature reading valid? if (self.isReadingValid(valueTemp, -40.0, 125.0)): valueTemp = self.convertTemp(valueTemp) self.arrTemperature.append(round(valueTemp, 2)) else: #Reading out of bounds return resultTemp if (len(self.arrTemperature) > self.ARRAY_SIZE): del self.arrTemperature[0] if (self.sensorMode == "Advanced"): sumTemp = sum(filter(None, self.arrTemperature)) noTempReadings = len(filter(None, self.arrTemperature)) if (noTempReadings > 0): resultTemp = float( str(round(sumTemp / noTempReadings, self.precisionTemp))) #print("readValueAdvanced: Result - Temp:'{0}'".format(resultTemp)) self.logger.info("readValue: Temp:'{0}'".format(resultTemp)) #Simple mode -> Just return last reading else: resultTemp = float(str(round(valueTemp, self.precissionTemp))) self.logger.info("readValue: Temp:'{0}'".format(resultTemp)) #print("readValueSimple: Result - Temp:'{0}'".format(resultTemp)) return resultTemp
class MCP3428(object): """ """ def __init__(self): self.LSB_12BITS = 0.001000 self.LSB_14BITS = 0.000250 self.LSB_16BITS = 0.0000625 self.CW_RDY = 0b10000000 self.CW_C1 = 0b00000000 self.CW_C2 = 0b00100000 self.CW_C3 = 0b01000000 self.CW_C4 = 0b01100000 self.CW_CC = 0b00010000 self.CW_CM = 0b00000000 self.CW_240SPS = 0b00000000 self.CW_60SPS = 0b00000100 self.CW_15SPS = 0b00001000 self.CW_G1 = 0b00000000 self.CW_G2 = 0b00000001 self.CW_G4 = 0b00000010 self.CW_G8 = 0b00000011 self.addr = 0 self.mode = self.CW_CC self.sps = self.CW_15SPS self.lsb = self.LSB_16BITS self.gain = self.CW_G1 def open(self, bus_num, bus=None): if bus != None: self.bus = bus else: self.bus = SMBus() self.bus.open(bus_num) def addr_is(self, pin0, pin1): """ Calcule l'addresse du chip avec la configuration des pin adresse pin0 et pin1 None : pin floatante True : V+ False : GND """ BASE_ADDR = 0b1101000 if pin0 == None and pin1 == None: return BASE_ADDR | 0b000 if pin0 == False and pin1 == False: return BASE_ADDR | 0b000 if pin0 == False and pin1 == None: return BASE_ADDR | 0b001 if pin0 == False and pin1 == True: return BASE_ADDR | 0b010 if pin0 == None and pin1 == False: return BASE_ADDR | 0b011 if pin0 == True and pin1 == False: return BASE_ADDR | 0b100 if pin0 == True and pin1 == None: return BASE_ADDR | 0b101 if pin0 == True and pin1 == True: return BASE_ADDR | 0b110 if pin0 == None and pin1 == True: return BASE_ADDR | 0b111 def set_addr(self, addr): self.addr = addr def set_mode(self, mode): self.mode = mode & 0b10010011 def set_channel(self, CW_Cx): self.bus.write_byte( self.addr, self.CW_RDY | CW_Cx | self.mode | self.sps | self.gain) time.sleep(0.12) return def close(self): bus.close() def get_value(self): buf = self.bus.read_i2c_block_data(self.addr, 0, 2) #print buf if self.gain == self.CW_G1: return (buf[0] << 8 | buf[1]) * self.lsb if self.gain == self.CW_G2: return (buf[0] << 8 | buf[1]) * self.lsb / 2 if self.gain == self.CW_G4: return (buf[0] << 8 | buf[1]) * self.lsb / 4 if self.gain == self.CW_G8: return (buf[0] << 8 | buf[1]) * self.lsb / 8 def set_lsb(self, lsb): self.lsb = lsb if self.lsb == self.LSB_12BITS: self.sps = self.CW_240SPS if self.lsb == self.LSB_14BITS: self.sps = self.CW_60SPS if self.lsb == self.LSB_16BITS: self.sps = self.CW_15SPS return self.sps def set_sps(self, sps): self.sps = sps if self.sps == self.CW_240SPS: self.lsb = self.LSB_12BITS if self.sps == self.CW_60SPS: self.lsb = self.LSB_14BITS if self.sps == self.CW_15SPS: self.lsb = self.LSB_16BITS return self.lsb def close(self): self.bus.close() def send_general_reset(self): self.bus.write_byte(self.addr, 0x06) time.sleep(0.5) return def send_general_latch(self): self.bus.write_byte(self.addr, 0x04) time.sleep(0.12) return def send_general_conversion(self): self.bus.write_byte(self.addr, 0x08) time.sleep(0.12) return def set_gain(self, gain): self.gain = gain
class MS5611: ''' Driver for reading temperature/pressure MS5611 Pressure Sensor. @params bus: can be set as 0 or 1 in rasberry3B+, 0 means port SDA.0 while 1 means port SDA.1 in pi @params i2c: the address of i2c, i2c is 0x77 when CSB<-->GND, 0x76 when CSB<-->3V3 @params elevation: height ''' def __init__(self, bus = 1, i2c = 0x77, elevation = 0): self.bus = SMBus(bus) self.i2c = i2c self.elevation = elevation def read(self): ## Get raw pressure self.bus.write_byte(self.i2c, 0x48) time.sleep(0.05) D1 = self.bus.read_i2c_block_data(self.i2c, 0x00) D1 = D1[0] * 65536 + D1[1] * 256.0 + D1[2] time.sleep(0.05) ## Get raw temperature self.bus.write_byte(self.i2c, 0x58) time.sleep(0.05) D2 = self.bus.read_i2c_block_data(self.i2c, 0x00) D2 = D2[0] * 65536 + D2[1] * 256.0 + D2[2] time.sleep(0.05) ## Read Constants from Sensor if hasattr(self, 'C1'): C1 = self.C1 else: C1 = self.bus.read_i2c_block_data(self.i2c, 0xA2) #Pressure Sensitivity C1 = C1[0] * 256.0 + C1[1] self.C1 = C1 time.sleep(0.05) if hasattr(self, 'C2'): C2 = self.C2 else: C2 = self.bus.read_i2c_block_data(self.i2c, 0xA4) #Pressure Offset C2 = C2[0] * 256.0 + C2[1] self.C2 = C2 time.sleep(0.05) if hasattr(self, 'C3'): C3 = self.C3 else: C3 = self.bus.read_i2c_block_data(self.i2c, 0xA6) #Temperature coefficient of pressure sensitivity C3 = C3[0] * 256.0 + C3[1] self.C3 = C3 time.sleep(0.05) if hasattr(self, 'C4'): C4 = self.C4 else: C4 = self.bus.read_i2c_block_data(self.i2c, 0xA8) #Temperature coefficient of pressure offset C4 = C4[0] * 256.0 + C4[1] self.C4 = C4 time.sleep(0.05) if hasattr(self, 'C5'): C5 = self.C5 else: C5 = self.bus.read_i2c_block_data(self.i2c, 0xAA) #Reference temperature C5 = C5[0] * 256.0 + C5[1] self.C5 = C5 time.sleep(0.05) if hasattr(self, 'C6'): C6 = self.C6 else: C6 = self.bus.read_i2c_block_data(self.i2c, 0xAC) #Temperature coefficient of the temperature C6 = C6[0] * 256.0 + C6[1] self.C6 = C6 time.sleep(0.05) ## These are the calculations provided in the datasheet for the sensor. dT = D2 - C5 * 2**8 TEMP = 2000 + dT * C6 / 2**23 ## Set Values to class to be used elsewhere self.tempC = TEMP/100.0 self.tempK = TEMP/100.0 + 273.15 ## These calculations are all used to produce the final pressure value OFF = C2 * 2**16 + (C4 * dT) / 2**7 SENS = C1 * 2**15 + (C3 * dT) / 2**8 P = (D1 * SENS / 2**21 - OFF) / 2**15 self.pressure = P/1000.0 ## Calculate an offset for the pressure. This is required so that the readings are correct. ## Equation can be found here: http://en.wikipedia.org/wiki/Barometric_formula altOffset = math.exp( (-9.80665 * 0.0289644 * self.elevation) / (8.31432 * self.tempK) ) self.pressureAdj = ( P/altOffset ) / 1000.0 def getTempC(self): return self.tempC def getPressure(self): return self.pressure def getPressureAdj(self): return self.pressureAdj def printResults(self): print("Temperature:", round(self.tempC, 2), "C") print("Pressure Absolute:", round(self.pressure, 2), "kPa") print(" Adjusted:", round(self.pressureAdj, 2), "kPa")
class MS5611: """Driver for reading temperature/pressure MS5611 Pressure Sensor.""" def __init__(self, bus=1, i2c=0x76, elevation=0): """Initialize the Driver. Default bus is 1. If you have a Rev 1 RPi then you will need to use bus 0. A bus object can also be passed in if you are sharing it among other modules Arguments (All optional): bus -- 0, 1, or a bus object i2c -- I2C address elevation -- Elevation in meters""" if (bus == 0 or bus == 1): self.bus = SMBus(bus) else: self.bus = bus self.i2c = i2c self.elevation = elevation def setElevation(self, elevation): self.elevation = elevation def setElevationFt(self, elevation): self.elevation = elevation / 3.2808 def setI2c(self, i2c): self.i2c = i2c def read(self): ## Get raw pressure self.bus.write_byte(self.i2c, 0x48) time.sleep(0.05) D1 = self.bus.read_i2c_block_data(self.i2c, 0x00) D1 = D1[0] * 65536 + D1[1] * 256.0 + D1[2] time.sleep(0.05) ## Get raw temperature self.bus.write_byte(self.i2c, 0x58) time.sleep(0.05) D2 = self.bus.read_i2c_block_data(self.i2c, 0x00) D2 = D2[0] * 65536 + D2[1] * 256.0 + D2[2] time.sleep(0.05) ## Read Constants from Sensor if hasattr(self, 'C1'): C1 = self.C1 else: C1 = self.bus.read_i2c_block_data(self.i2c, 0xA2) #Pressure Sensitivity C1 = C1[0] * 256.0 + C1[1] self.C1 = C1 time.sleep(0.05) if hasattr(self, 'C2'): C2 = self.C2 else: C2 = self.bus.read_i2c_block_data(self.i2c, 0xA4) #Pressure Offset C2 = C2[0] * 256.0 + C2[1] self.C2 = C2 time.sleep(0.05) if hasattr(self, 'C3'): C3 = self.C3 else: C3 = self.bus.read_i2c_block_data( self.i2c, 0xA6) #Temperature coefficient of pressure sensitivity C3 = C3[0] * 256.0 + C3[1] self.C3 = C3 time.sleep(0.05) if hasattr(self, 'C4'): C4 = self.C4 else: C4 = self.bus.read_i2c_block_data( self.i2c, 0xA8) #Temperature coefficient of pressure offset C4 = C4[0] * 256.0 + C4[1] self.C4 = C4 time.sleep(0.05) if hasattr(self, 'C5'): C5 = self.C5 else: C5 = self.bus.read_i2c_block_data(self.i2c, 0xAA) #Reference temperature C5 = C5[0] * 256.0 + C5[1] self.C5 = C5 time.sleep(0.05) if hasattr(self, 'C6'): C6 = self.C6 else: C6 = self.bus.read_i2c_block_data( self.i2c, 0xAC) #Temperature coefficient of the temperature C6 = C6[0] * 256.0 + C6[1] self.C6 = C6 time.sleep(0.05) ## These are the calculations provided in the datasheet for the sensor. dT = D2 - C5 * 2**8 TEMP = 2000 + dT * C6 / 2**23 ## Set Values to class to be used elsewhere self.tempC = TEMP / 100.0 self.tempF = TEMP / 100.0 * 9.0 / 5 + 32 self.tempK = TEMP / 100.0 + 273.15 ## These calculations are all used to produce the final pressure value OFF = C2 * 2**16 + (C4 * dT) / 2**7 SENS = C1 * 2**15 + (C3 * dT) / 2**8 P = (D1 * SENS / 2**21 - OFF) / 2**15 self.pressure = P / 100.0 ## Calculate an offset for the pressure. This is required so that the readings are correct. ## Equation can be found here: http://en.wikipedia.org/wiki/Barometric_formula altOffset = math.exp( (-9.80665 * 0.0289644 * self.elevation) / (8.31432 * self.tempK)) self.pressureAdj = (P / altOffset) / 100.0 def getTempC(self): return self.tempC def getTempF(self): return self.tempF def getPressure(self): return self.pressure def getPressureAdj(self): return self.pressureAdj def getBus(self): return self.bus def printResults(self): print "Temperature:", round(self.tempC, 2), "C" print " ", round(self.tempF, 2), "F" print "Pressure Absolute:", round(self.pressure, 2), "hPa" print " Adjusted:", round(self.pressureAdj, 2), "hPa" print " Adjusted:", round(self.convert2In(self.pressureAdj), 2), "in" def convert2In(self, pressure): return pressure * 0.0295301
class I2C(_Basic_class): MASTER = 0 SLAVE = 1 RETRY = 5 def __init__(self, *args, **kargs): # *args表示位置参数(形式参数),可无,; **kargs表示默认值参数,可无。 super().__init__() self._bus = 1 self._smbus = SMBus(self._bus) def _i2c_write_byte(self, addr, data): # i2C 写系列函数 self._debug("_i2c_write_byte: [0x{:02X}] [0x{:02X}]".format(addr, data)) return self._smbus.write_byte(addr, data) def _i2c_write_byte_data(self, addr, reg, data): self._debug("_i2c_write_byte_data: [0x{:02X}] [0x{:02X}] [0x{:02X}]".format(addr, reg, data)) return self._smbus.write_byte_data(addr, reg, data) def _i2c_write_word_data(self, addr, reg, data): self._debug("_i2c_write_word_data: [0x{:02X}] [0x{:02X}] [0x{:04X}]".format(addr, reg, data)) return self._smbus.write_word_data(addr, reg, data) def _i2c_write_i2c_block_data(self, addr, reg, data): self._debug("_i2c_write_i2c_block_data: [0x{:02X}] [0x{:02X}] {}".format(addr, reg, data)) return self._smbus.write_i2c_block_data(addr, reg, data) def _i2c_read_byte(self, addr): # i2C 读系列函数 self._debug("_i2c_read_byte: [0x{:02X}]".format(addr)) return self._smbus.read_byte(addr) def _i2c_read_i2c_block_data(self, addr, reg, num): self._debug("_i2c_read_i2c_block_data: [0x{:02X}] [0x{:02X}] [{}]".format(addr, reg, num)) return self._smbus.read_i2c_block_data(addr, reg, num) def is_ready(self, addr): addresses = self.scan() if addr in addresses: return True else: return False def scan(self): # 查看有哪些i2c设备 cmd = "i2cdetect -y %s" % self._bus _, output = self.run_command(cmd) # 调用basic中的方法,在linux中运行cmd指令,并返回运行后的内容 outputs = output.split('\n')[1:] # 以回车符为分隔符,分割第二行之后的所有行 self._debug("outputs") addresses = [] for tmp_addresses in outputs: if tmp_addresses == "": continue tmp_addresses = tmp_addresses.split(':')[1] tmp_addresses = tmp_addresses.strip().split(' ') # strip函数是删除字符串两端的字符,split函数是分隔符 for address in tmp_addresses: if address != '--': addresses.append(int(address, 16)) self._debug("Conneceted i2c device: %s"%addresses) # append以列表的方式添加address到addresses中 return addresses def send(self, send, addr, timeout=0): # 发送数据,addr为从机地址,send为数据 if isinstance(send, bytearray): data_all = list(send) elif isinstance(send, int): data_all = [] d = "{:X}".format(send) d = "{}{}".format("0" if len(d)%2 == 1 else "", d) # format是将()中的内容对应填入{}中,()中的第一个参数是一个三目运算符,if条件成立则为“0”,不成立则为“”(空的意思),第二个参数是d,此行代码意思为,当字符串为奇数位时,在字符串最强面添加‘0’,否则,不添加, 方便以下函数的应用 # print(d) for i in range(len(d)-2, -1, -2): # 从字符串最后开始取,每次取2位 tmp = int(d[i:i+2], 16) # 将两位字符转化为16进制 # print(tmp) data_all.append(tmp) # 添加到data_all数组中 data_all.reverse() elif isinstance(send, list): data_all = send else: raise ValueError("send data must be int, list, or bytearray, not {}".format(type(send))) if len(data_all) == 1: # 如果data_all只有一组数 data = data_all[0] self._i2c_write_byte(addr, data) elif len(data_all) == 2: # 如果data_all只有两组数 reg = data_all[0] data = data_all[1] self._i2c_write_byte_data(addr, reg, data) elif len(data_all) == 3: # 如果data_all只有三组数 reg = data_all[0] data = (data_all[2] << 8) + data_all[1] self._i2c_write_word_data(addr, reg, data) else: reg = data_all[0] data = list(data_all[1:]) self._i2c_write_i2c_block_data(addr, reg, data) def recv(self, recv, addr=0x00, timeout=0): # 接收数据 if isinstance(recv, int): # 将recv转化为二进制数 result = bytearray(recv) elif isinstance(recv, bytearray): result = recv else: return False for i in range(len(result)): result[i] = self._i2c_read_byte(addr) return result def mem_write(self, data, addr, memaddr, timeout=5000, addr_size=8): #memaddr match to chn if isinstance(data, bytearray): data_all = list(data) elif isinstance(data, list): data_all = data elif isinstance(data, int): data_all = [] data = "%x"%data if len(data) % 2 == 1: data = "0" + data # print(data) for i in range(0, len(data), 2): # print(data[i:i+2]) data_all.append(int(data[i:i+2], 16)) else: raise ValueError("memery write require arguement of bytearray, list, int less than 0xFF") # print(data_all) self._i2c_write_i2c_block_data(addr, memaddr, data_all) def mem_read(self, data, addr, memaddr, timeout=5000, addr_size=8): # 读取数据 if isinstance(data, int): num = data elif isinstance(data, bytearray): num = len(data) else: return False result = bytearray(self._i2c_read_i2c_block_data(addr, memaddr, num)) return result def readfrom_mem_into(self, addr, memaddr, buf): buf = self.mem_read(len(buf), addr, memaddr) return buf def writeto_mem(self, addr, memaddr, data): self.mem_write(data, addr, memaddr) # i2c = I2C() # i2c.scan() # i2c.mem_write(0xff53773, 20, 20)
class Mpl3115a2(object): _bus = None def __init__(self, i2c_bus=0): """ :type i2c_bus: int specifying i2c bus number """ self._bus = SMBus(i2c_bus) whoami = self._bus.read_byte_data(MPL3115A2_ADDRESS, MPL3115A2_WHOAMI) if whoami != 0xc4: print("MPL3115A2 not active.") exit(1) # Set MPL3115A2 oversampling to 128, put in Barometer mode, enabled standby on CTRL_REG1 self._bus.write_byte_data( MPL3115A2_ADDRESS, MPL3115A2_CTRL_REG1, MPL3115A2_CTRL_REG1_SBYB | MPL3115A2_CTRL_REG1_OS128 | MPL3115A2_CTRL_REG1_BAR) # Configure MPL3115A2 self._bus.write_byte_data( MPL3115A2_ADDRESS, MPL3115A2_PT_DATA_CFG, MPL3115A2_PT_DATA_CFG_TDEFE | MPL3115A2_PT_DATA_CFG_PDEFE | MPL3115A2_PT_DATA_CFG_DREM) def poll(self): sta = 0 while not (sta & MPL3115A2_REGISTER_STATUS_PDR): sta = self._bus.read_byte_data(MPL3115A2_ADDRESS, MPL3115A2_REGISTER_STATUS) def get_altitude(self): # print "Reading Altitude Data..." self._bus.write_byte_data( MPL3115A2_ADDRESS, MPL3115A2_CTRL_REG1, MPL3115A2_CTRL_REG1_SBYB | MPL3115A2_CTRL_REG1_OS128 | MPL3115A2_CTRL_REG1_ALT) # change to altimeter mode self.poll() msb, csb, lsb = self._bus.read_i2c_block_data(MPL3115A2_ADDRESS, MPL3115A2_REGISTER_PRESSURE_MSB, 3) # print msb, csb, lsb alt = float((((msb << 24) | (csb << 16) | lsb) * 10) / 65536) # correct sign if alt > (1 << 15): alt -= 1 << 16 return alt def get_pressure(self): # print "Reading Pressure Data..." self._bus.write_byte_data( MPL3115A2_ADDRESS, MPL3115A2_CTRL_REG1, MPL3115A2_CTRL_REG1_SBYB | MPL3115A2_CTRL_REG1_OS128 | MPL3115A2_CTRL_REG1_BAR) # change to barometer mode self.poll() msb, csb, lsb = self._bus.read_i2c_block_data(MPL3115A2_ADDRESS, MPL3115A2_REGISTER_PRESSURE_MSB, 3) # print msb, csb, lsb return ((msb << 16) | (csb << 8) | lsb) / 64. def calibrate(self): # print "Calibrating..." p = 0 t = 0 a = 0 calibration_rounds = 5 for _i in np.arange(0, calibration_rounds, 1): p += self.get_pressure() t += self.get_temperature() a += self.get_altitude() print("MPL3115A2 Calibration Round: {0} of {1}".format((_i+1), calibration_rounds)) pa = int((p / 10) / 2) ta = (t / 10) aa = (a / 10) self._bus.write_i2c_block_data(MPL3115A2_ADDRESS, MPL3115A2_BAR_IN_MSB, [pa >> 8 & 0xff, pa & 0xff]) return [pa, ta, aa] def get_temperature(self): # print "Reading Temperature Data..." self._bus.write_byte_data( MPL3115A2_ADDRESS, MPL3115A2_CTRL_REG1, MPL3115A2_CTRL_REG1_SBYB | MPL3115A2_CTRL_REG1_OS128 | MPL3115A2_CTRL_REG1_BAR) self.poll() t_data = self._bus.read_i2c_block_data(MPL3115A2_ADDRESS, MPL3115A2_REGISTER_STATUS_PDR, 2) # status = _bus.read_byte_data(MPL3115A2_ADDRESS, 0x00) # print t_data return t_data[0] + (t_data[1] >> 4) / 16.0
def __init__(self, name, i2c_addr): self.I2Caddr = i2c_addr directory = "/tmp/" + name if not os.path.exists(directory): os.makedirs(directory) self.FptrVoc = directory + "/voc" self.FptrBase = directory + "/base" self.FptrError = directory + "/error" # to retreave RH values for compensation self.FptrTemp = "/tmp/HTU21D/tc" self.FptrHumid = "/tmp/HTU21D/rh" # for maintaining the moving averages self.voc_buff = [0] * CCS811_MAX self.voc_ptr = 0 # for tracking baseline value changes self.newcal = 0 self.oldcal = 0 # to track RH compenation event self.comp_minute = CCS811_T_MAX # Long term T & RH averaging self.temp_buff = [23] * CCS811_T_MAX self.rh_buff = [50] * CCS811_T_MAX bus = SMBus(I2CBUS) resp = bus.read_byte_data(self.I2Caddr, CCS811_REG_STATUS) print "ccs811.init() status reg: 0x%02x" % resp if resp & CCS811_APP_VALID: bus.write_byte(self.I2Caddr, CCS811_APP_START) print "ccs811.init() starting application" else: print "ccs811.init() failed to start application" bus.close() sys.exit(10) time.sleep(1) # Start making measurements bus.write_byte_data(self.I2Caddr, CCS811_REG_MEAS_MODE, CCS811_MEAS_MODE_ON) resp = bus.read_byte_data(self.I2Caddr, CCS811_REG_ERROR) if resp: print "ccs811.init() error reg: 0x%02x" % resp sys.exit(11) # Display CCS811 information on startup resp = bus.read_byte_data(self.I2Caddr, CCS811_HW_ID) print "ccs811.inint() HW ID: 0x%02x" % resp resp = bus.read_byte_data(self.I2Caddr, CCS811_VER_HW) print "ccs811.inint() HW Ver: 0x%02x" % resp resp = bus.read_i2c_block_data(self.I2Caddr, CCS811_VER_APP, 2) major = resp[0] & 0xf0 >> 4 minor = resp[0] & 0x0f trivial = resp[1] print "css811.init() app ver: %d.%d.%d" % (major, minor, trivial) resp = bus.read_byte_data(self.I2Caddr, CCS811_REG_ERROR) if resp: print "ccs811.init() error reg: 0x%02x" % resp sys.exit(12) # Init envronmental compensation registers temp_c = 23 r_humidity = 50 self.set_comp(temp_c, r_humidity) # will implement periodically in loop #print "CCS811 init complete" bus.close()
class nunchuck: def __init__(self): if rpi.RPI_REVISION == 1: i2c_bus = 0 elif rpi.RPI_REVISION == 2: i2c_bus = 1 else: print "Unable to determine Raspberry Pi revision." exit self.bus = SMBus(i2c_bus) self.bus.write_byte_data(0x52, 0xF0, 0x55) def read(self): buf = self.bus.read_i2c_block_data(0x52, 0x00, 6) data = [0x00]*6 for i in range(len(buf)): data[i] = buf[i] return data def raw(self): data = self.read() return data def joystick(self): data = self.read() return data[0],data[1] def accelerometer(self): data = self.read() return data[2],data[3],data[4] def button_c(self): data = self.read() butc = (data[5] & 0x02) if butc == 0: return True else: return False def button_z(self): data = self.read() butc = (data[5] & 0x01) if butc == 0: return True else: return False def joystick_x(self): data = self.read() return data[0] def joystick_y(self): data = self.read() return data[1] def accelerometer_x(self): data = self.read() return data[2] def accelerometer_y(self): data = self.read() return data[3] def accelerometer_z(self): data = self.read() return data[4] def scale(self,value,_min,_max,_omin,_omax): return (value - _min) * (_omax - _omin) // (_max - _min) + _omin
class WeatherStation: def __init__(self, dataFile='/dev/null'): self.dataFile = dataFile self.fetched = False # Initialise the BMP085 and use STANDARD mode (default value) # self.bmp = BMP085(0x77, debug=True) self.bmp = BMP085(0x77) # To specify a different operating mode, uncomment one of the following: # self.bmp = BMP085(0x77, 0) # ULTRALOWPOWER Mode # self.bmp = BMP085(0x77, 1) # STANDARD Mode # self.bmp = BMP085(0x77, 2) # HIRES Mode # self.bmp = BMP085(0x77, 3) # ULTRAHIRES Mode # Initilize HIH-6130. bus = GFDITools.guessBus() self.HIH6130 = SMBus(bus=bus) # Temporary storage array for HIH6130 data self.blockData = [0, 0, 0, 0] def fetchData(self): # Fetch temp & pressure data from BMP self.temp = self.bmp.readTemperature() self.pressure = self.bmp.readPressure() / 100.0 # Altitude seems buggy, so we're skipping it for now. # altitude = self.bmp.readAltitude() # Tell HIH-6130 we want temperature and humidity data. self.HIH6130.write_quick(0x27) # Wait for it. time.sleep(0.050) # Read the data we requested. blockData = self.HIH6130.read_i2c_block_data(0x27, 0) # Process the data. self.status = (blockData[0] & 0xc0) >> 6 self.humidity = (((blockData[0] & 0x3f) << 8) + blockData[1]) * 100.0 / 16383.0 self.tempC = ((blockData[2] << 6) + ((blockData[3] & 0xfc) >> 2)) * 165.0 / 16383.0 - 40.0 # tempF = tempC*9.0/5.0 + 32.0 # Make a note that there is now data to be had. self.fetched = True def printData(self): # print data to screen # print "Data: ", "%02x "*len(d)%tuple(d) # print "Status: ", status if self.fetched: print "Humidity: %.2f" % self.humidity, "%RH" print "Temperature: %.2f C" % self.tempC print "Barometric Pressure: %.2f hPa" % self.pressure print "Temperature: %.2f C" % self.temp else: print "No data has been fetched." return -1 def recordData(self): if self.fetched: if not os.path.exists(self.dataFile): with open(self.dataFile, 'w') as csvfile: datawriter = csv.writer( csvfile, quotechar=',', quoting=csv.QUOTE_MINIMAL ) datawriter.writerow([ 'Date', 'Temp(C)', 'Pressure(hPa)', 'Humidity(%RH)' ]) with open(self.dataFile, 'a+') as csvfile: datawriter = csv.writer(csvfile, quotechar=',', quoting=csv.QUOTE_MINIMAL) datawriter.writerow([datetime.datetime.now(), self.tempC, self.pressure, self.humidity]) else: print "No data has been fetched." return -1
class Device(object): """Class for communicating with an I2C device using the adafruit-pureio pure python smbus library, or other smbus compatible I2C interface. Allows reading and writing 8-bit, 16-bit, and byte array values to registers on the device.""" def __init__(self, address, busnum, i2c_interface=None): """Create an instance of the I2C device at the specified address on the specified I2C bus number.""" self._address = address if i2c_interface is None: # Use pure python I2C interface if none is specified. # import Adafruit_PureIO.smbus self._bus = SMBus(busnum) else: # Otherwise use the provided class to create an smbus interface. self._bus = i2c_interface(busnum) self._logger = logging.getLogger('Adafruit_I2C.Device.Bus.{0}.Address.{1:#0X}' \ .format(busnum, address)) def writeRaw8(self, value): """Write an 8-bit value on the bus (without register).""" value = value & 0xFF self._bus.write_byte(self._address, value) self._logger.debug("Wrote 0x%02X", value) def write8(self, register, value): """Write an 8-bit value to the specified register.""" value = value & 0xFF self._bus.write_byte_data(self._address, register, value) self._logger.debug("Wrote 0x%02X to register 0x%02X", value, register) def write16(self, register, value): """Write a 16-bit value to the specified register.""" value = value & 0xFFFF self._bus.write_word_data(self._address, register, value) self._logger.debug("Wrote 0x%04X to register pair 0x%02X, 0x%02X", value, register, register+1) def writeList(self, register, data): """Write bytes to the specified register.""" self._bus.write_i2c_block_data(self._address, register, data) self._logger.debug("Wrote to register 0x%02X: %s", register, data) def readList(self, register, length): """Read a length number of bytes from the specified register. Results will be returned as a bytearray.""" results = self._bus.read_i2c_block_data(self._address, register, length) self._logger.debug("Read the following from register 0x%02X: %s", register, results) return results def readRaw8(self): """Read an 8-bit value on the bus (without register).""" result = self._bus.read_byte(self._address) & 0xFF self._logger.debug("Read 0x%02X", result) return result def readU8(self, register): """Read an unsigned byte from the specified register.""" result = self._bus.read_byte_data(self._address, register) & 0xFF self._logger.debug("Read 0x%02X from register 0x%02X", result, register) return result def readS8(self, register): """Read a signed byte from the specified register.""" result = self.readU8(register) if result > 127: result -= 256 return result def readU16(self, register, little_endian=True): """Read an unsigned 16-bit value from the specified register, with the specified endianness (default little endian, or least significant byte first).""" result = self._bus.read_word_data(self._address,register) & 0xFFFF self._logger.debug("Read 0x%04X from register pair 0x%02X, 0x%02X", result, register, register+1) # Swap bytes if using big endian because read_word_data assumes little # endian on ARM (little endian) systems. if not little_endian: result = ((result << 8) & 0xFF00) + (result >> 8) return result def readS16(self, register, little_endian=True): """Read a signed 16-bit value from the specified register, with the specified endianness (default little endian, or least significant byte first).""" result = self.readU16(register, little_endian) if result > 32767: result -= 65536 return result def readU16LE(self, register): """Read an unsigned 16-bit value from the specified register, in little endian byte order.""" return self.readU16(register, little_endian=True) def readU16BE(self, register): """Read an unsigned 16-bit value from the specified register, in big endian byte order.""" return self.readU16(register, little_endian=False) def readS16LE(self, register): """Read a signed 16-bit value from the specified register, in little endian byte order.""" return self.readS16(register, little_endian=True) def readS16BE(self, register): """Read a signed 16-bit value from the specified register, in big endian byte order.""" return self.readS16(register, little_endian=False)
deg = u'\N{DEGREE SIGN}' # sqlite config # CREATE TABLE temp_humidity(id INTEGER primary key, datetime DATETIME DEFAULT CURRENT_TIMESTAMP, temp_c REAL NOT NULL, temp_f REAL NOT NULL, humidity INTEGER NOT NULL); sqliteCon = sqlite.connect(dbPath) # Main loop while True: # Get the current system date and time datetime = time.strftime('%m/%d/%Y %H:%M:%S') # Read data from sensor bus.write_byte(ADDR, 0x00) ans = bus.read_i2c_block_data(ADDR, 0x00, 4) # Convert to human readable humdidity humidity = ((ans[0] & 0x3f) << 8) + ans[1] humidity = humidity * float('6.10e-3') humidity = '{:.0f}'.format(humidity) # Convert to human readable temperature tempC = (ans[2] << 8) + ans[3] tempC = tempC >> 2 tempC = (tempC * float('1.007e-2')) - 40 tempF = (tempC * 1.8) + 32 #insert into SQLITE database cursor = sqliteCon.cursor() cursor.execute("INSERT INTO temp_humidity (datetime, temp_c, temp_f, humidity) VALUES (?, ?, ?, ?)", (time.strftime('%Y-%m-%dT%H:%M:%S'), tempC, tempF, humidity))
class DS3231: """Class to read/write time from/to DS3231""" ## Control constants _SLAVE_ADDR = 0x68 _TIME_START_ADDR = 0x00 _TEMP_START_ADDR = 0x11 _REG_SECONDS = 0x00 _REG_MINUTES = 0x01 _REG_HOURS = 0x02 _REG_DAY = 0x03 _REG_DATE = 0x04 _REG_MONTH = 0x05 _REG_YEAR = 0x06 _REG_CONTROL = 0x07 def __init__(self, device_number = 1): """Opens the i2c device (assuming that the kernel modules have been loaded) & run soft reset. (user register leaved to default value)""" try: self.bus = SMBus(device_number) except i2cError: #raise i2cError pass if DEBUG: print("DS3231 init done.") def getTime(self): """ """ try: data = self.bus.read_i2c_block_data(self._SLAVE_ADDR,0x00,7) except i2cError: #raise i2cError pass sec = self._bcd_to_int(data[0] & 0x7F) min = self._bcd_to_int(data[1] & 0x3F) hour = self._bcd_to_int(data[2]) day = self._bcd_to_int(data[3]) date = self._bcd_to_int(data[4]) month = self._bcd_to_int(data[5]) year = self._bcd_to_int(data[6]) if DEBUG: print(datetime((21-1)*100 + year, month,date,hour,min,sec,0,tzinfo = None)) #print(*data, sep='\t') return datetime((21-1)*100 + year, \ month,date,hour,min,sec,0,tzinfo=None) def setTime(self,timetuple): """ write Time/date Information to Ds3231 Range: seconds [0,59], minutes [0,59], hours [0,23], day [0,7], date [1-31], month [1-12], year [0-99]. """ if self.checkTimeDataValidity(timetuple)is True: #write seconds regSec = self._int_to_bcd(timetuple[5]) self.bus.write_byte_data(self._SLAVE_ADDR,self._REG_SECONDS,regSec) #write minutes regMin = self._int_to_bcd(timetuple[4]) self.bus.write_byte_data(self._SLAVE_ADDR,self._REG_MINUTES,regMin) #write hours regHr = self._int_to_bcd(timetuple[3]) self.bus.write_byte_data(self._SLAVE_ADDR,self._REG_HOURS,regHr) #write Date regDate = self._int_to_bcd(timetuple[2]) self.bus.write_byte_data(self._SLAVE_ADDR,self._REG_DATE,regDate) #write month regMonth = self._int_to_bcd(timetuple[1]) self.bus.write_byte_data(self._SLAVE_ADDR,self._REG_MONTH,regMonth) #write year regYr = self._int_to_bcd(timetuple[0]-2000) self.bus.write_byte_data(self._SLAVE_ADDR,self._REG_YEAR,regYr) def setTimeNow(self): """ Set time to datetime.now(). Return tuple needed by setTime() """ #TODO: Get a better function to check if the pi is online if self.checkIfOnline() is not None: tmp = datetime.now() self.setTime((tmp.year,tmp.month, tmp.day,tmp.hour,tmp.minute,tmp.second )) else: raise ConnectionError("Please connect your Pi to the internet first...") @staticmethod def checkIfOnline(): """ Check if the pi is online """ try: import requests except ImportError: print('Please make sure Python library requests is installed') r = requests.get('https://api.github.com/events') if r is True: return True else: return False @staticmethod def checkTimeDataValidity(timetuple): """ Checks time data inputs """ if 2000 <= timetuple[0] <= 2099 and \ 1 <= timetuple[1] <= 12 and \ 1 <= timetuple[2] <= 31 and \ 0 <= timetuple[3] <= 23 and \ 0 <= timetuple[4] <= 59 and \ 0 <= timetuple[5] <= 59: return True else: return False @staticmethod def _bcd_to_int(bcd): """ Decode a 2x4bit BCD to a integer. """ out = 0 for d in (bcd >> 4, bcd): for p in (1, 2, 4 ,8): if d & 1: out += p d >>= 1 out *= 10 return int(out / 10) @staticmethod def _int_to_bcd(n): """ Encode a one or two digits number to the BCD. """ bcd = 0 for i in (n // 10, n % 10): for p in (8, 4, 2, 1): if i >= p: bcd += 1 i -= p bcd <<= 1 return bcd >> 1
class UltrasonicCapteur: _PORTS = "34" # Liste des ports disponibles def __init__(self, port): if port not in UltrasonicCapteur._PORTS: raise CapteurPortErreur self._port = port if port == "3": self._read_addr = 2 self._write_addr = 3 else: self._read_addr = 2 self._write_addr = 3 self._bus = SMBus(1) def getPort(self): return self._port def setPort(self, port): if port not in TouchCapteur._PORTS: raise CapteurPortErreur self._port = port def getInfos(self): pass def setScaleFactor(self, value): self._bus.write_byte_data(self._write_addr, 0x51, value) time.sleep(0.1) def setScaleDivisor(self, value): self._bus.write_byte_data(self._write_addr, 0x52, value) time.sleep(0.1) def setActualZero(self, value): self._bus.write_byte_data(self._write_addr, 0x50, value) time.sleep(0.1) def setInterval(self, value): self._bus.write_byte_data(self._write_addr, 0x40, value) time.sleep(0.1) def getInterval(self): data = self._bus.read_i2c_block_data(self._read_addr, 0x40, 1) time.sleep(0.1) return data[0] def getDistance(self): # Retourne la distance devant le capteur. # self._bus.write_byte_data(self._write_addr, 0x41, 0x01) time.sleep(0.1) data = self._bus.read_i2c_block_data(self._read_addr, 0x42, 8) distance = (data[0] + data[1] + data[2] + data[3] + data[4] + data[5] + data[6] + data[7]) / 8 return distance def __repr__(self): # Quand on entre notre objet dans l'interpréteur return "Capteur sur le port {}\nVersion : V1.0\nID produit : LEGO\nDistance : {}\t".format( self._port, self.getDistance() )
# read Atmel AT30TSE004A temp through I2C from smbus import SMBus i2c = SMBus(0) atmelraw = i2c.read_i2c_block_data(0x1e,0x05,2) atmeltemp = 16.0*(atmelraw[0] & 0xf) + (atmelraw[1] & 0xfe)/16.0 print "Atmel temp: ", atmeltemp # read Zynq XADC temp through IIO driver (XAPP1172, UG480) f = open('/sys/bus/iio/devices/iio:device0/in_temp0_raw','r') zynqraw = f.read() f.close() zynqtemp = int(zynqraw)*503.975/4096 - 273.15 print "Zynq temp: ", zynqtemp
class I2C(object): """ Class to set up and access I2C devices. """ ## ## Class methods ## ## Private methods def __init__(self, busId = 1): """ Initialize the I2C bus. """ self._i2c = SMBus(busId) def __del__(self): """ Clean up routines. """ try: # Remove SMBus connection del(self._i2c) except: pass def _combineLoHi(self, loByte, hiByte): """ Combine low and high bytes to an unsigned 16 bit value. """ return (loByte | hiByte << 8) def _combineSignedLoHi(self, loByte, hiByte): """ Combine low and high bytes to a signed 16 bit value. """ combined = self._combineLoHi (loByte, hiByte) return combined if combined < 32768 else (combined - 65536) def _combineXLoLoHi(self, xloByte, loByte, hiByte): """ Combine extra low, low, and high bytes to an unsigned 24 bit value. """ return (xloByte | loByte << 8 | hiByte << 16) def _combineSignedXLoLoHi(self, xloByte, loByte, hiByte): """ Combine extra low, low, and high bytes to a signed 24 bit value. """ combined = self._combineXLoLoHi(xloByte, loByte, hiByte) return combined if combined < 8388608 else (combined - 16777216) def _getSensorRawLoHi1(self, address, outRegs): """ Return a scalar representing the combined raw signed 16 bit value of the output registers of a one-dimensional sensor, e.g. temperature. 'address' is the I2C slave address. 'outRegs' is a list of the output registers to read. """ # Read register outputs and combine low and high byte values xl = self._readRegister(address, outRegs[0]) xh = self._readRegister(address, outRegs[1]) xVal = self._combineSignedLoHi(xl, xh) # Return the scalar return xVal def _getSensorRawXLoLoHi1(self, address, outRegs): """ Return a scalar representing the combined raw signed 24 bit value of the output registers of a one-dimensional sensor, e.g. temperature. 'address' is the I2C slave address. 'outRegs' is a list of the output registers to read. """ # Read register outputs and combine low and high byte values xxl = self._readRegister(address, outRegs[0]) xl = self._readRegister(address, outRegs[1]) xh = self._readRegister(address, outRegs[2]) xVal = self._combineSignedXLoLoHi(xxl, xl, xh) # Return the scalar return xVal def _getSensorRawLoHi3(self, address, outRegs): """ Return a vector (i.e. list) representing the combined raw signed 16 bit values of the output registers of a 3-dimensional (IMU) sensor. 'address' is the I2C slave address. 'outRegs' is a list of the output registers to read. """ # Read register outputs and combine low and high byte values xl = self._readRegister(address, outRegs[0]) xh = self._readRegister(address, outRegs[1]) yl = self._readRegister(address, outRegs[2]) yh = self._readRegister(address, outRegs[3]) zl = self._readRegister(address, outRegs[4]) zh = self._readRegister(address, outRegs[5]) xVal = self._combineSignedLoHi(xl, xh) yVal = self._combineSignedLoHi(yl, yh) zVal = self._combineSignedLoHi(zl, zh) # Return the vector return [xVal, yVal, zVal] def _readRegister(self, address, register): """ Read a single I2C register. """ return self._i2c.read_byte_data(address, register) def _readRegisters(self, address, register, count): """ Read (up to 32) 'count' consecutive I2C registers. """ return self._i2c.read_i2c_block_data(address, register, count) def _read(self, address): """ Read a single byte from the I2C device without specifying a register. """ return self._i2c.read_byte(address) def _writeRegister(self, address, register, value): """ Write a single byte to a I2C register. Return the value the register had before the write. """ valueOld = self._readRegister(address, register) self._i2c.write_byte_data(address, register, value) return valueOld def _write(self, address, value): """ Write a single byte to the I2C device without specifying a register. """ return self._i2c.write_byte(address, value) def _testRegister(self, address, register): """ Check, if a I2C register is readable/accessible. """ try: return self._readRegister(address, register) except: return -1
class BMP280: def __init__(self, address=BMP280_DEFAULT_ADRESS): self.i2c = SMBus() self.i2c.open(1) self.address = address self._load_calibration() self.i2c.write_byte_data(self.address, BMP280_CONTROL, 0x3F) def i2c_check(self): """Output should be 88, if not. I2c not correct""" data = self.i2c.read_byte_data(self.address, 0xD0) print(data) def _readU16(self, reg): """Reads an unsigned 16 bit value van i2c""" result = self.i2c.read_word_data(self.address, reg) return result def _readS16(self, reg): """Reads a signed 16 bit value van i2c""" result = self._readU16(reg) if result > 32767: result -= 65536 return result def _load_calibration(self): self.cal_t1 = int(self._readU16(BMP280_DIG_T1)) # UINT16 self.cal_t2 = int(self._readS16(BMP280_DIG_T2)) # INT16 self.cal_t3 = int(self._readS16(BMP280_DIG_T3)) # INT16 self.cal_p1 = int(self._readU16(BMP280_DIG_P1)) # UINT16 self.cal_p2 = int(self._readS16(BMP280_DIG_P2)) # INT16 self.cal_p3 = int(self._readS16(BMP280_DIG_P3)) # INT16 self.cal_p4 = int(self._readS16(BMP280_DIG_P4)) # INT16 self.cal_p5 = int(self._readS16(BMP280_DIG_P5)) # INT16 self.cal_p6 = int(self._readS16(BMP280_DIG_P6)) # INT16 self.cal_p7 = int(self._readS16(BMP280_DIG_P7)) # INT16 self.cal_p8 = int(self._readS16(BMP280_DIG_P8)) # INT16 self.cal_p9 = int(self._readS16(BMP280_DIG_P9)) # INT16 def read_raw_data(self, register): data = self.i2c.read_i2c_block_data(self.address, register, 3) data = self.convert_data(data[0], data[1], data[2]) return data def _compensate_temp(self, raw_temp): t1 = (((raw_temp >> 3) - (self.cal_t1 << 1)) * (self.cal_t2) >> 11) t2 = (((((raw_temp >> 4) - (self.cal_t1)) * ((raw_temp >> 4) - (self.cal_t1))) >> 12) * (self.cal_t3)) >> 14 return t1 + t2 def read_temperature(self): raw_temp = self.read_raw_data(BMP280_TEMPDATA) compensated_temp = self._compensate_temp(raw_temp) temp = float(((compensated_temp * 5 + 128) >> 8)) / 100 return temp def read_pressure(self): raw_temp = self.read_raw_data(BMP280_TEMPDATA) compensated_temp = self._compensate_temp(raw_temp) raw_pressure = self.read_raw_data(BMP280_PRESSUREDATA) p1 = compensated_temp - 128000 p2 = p1 * p1 * self.cal_p6 p2 += (p1 * self.cal_p5) << 17 p2 += self.cal_p4 << 35 p1 = ((p1 * p1 * self.cal_p3) >> 8) + ((p1 * self.cal_p2) << 12) p1 = ((1 << 47) + p1) * (self.cal_p1) >> 33 if 0 == p1: return 0 p = 1048576 - raw_pressure p = (((p << 31) - p2) * 3125) / p1 p1 = (self.cal_p9 * (int(p) >> 13) * (int(p) >> 13)) >> 25 p2 = int((self.cal_p8 * p)) >> 19 p = (int((p + p1 + p2)) >> 8) + ((self.cal_p7) << 4) return float(p / 256) def read_altitude(self, sealevel_pa=101325.0): """Calculates the altitude in meters.""" # Calculation taken straight from section 3.6 of the datasheet. pressure = float(self.read_pressure()) altitude = 44330.0 * (1.0 - pow(pressure / sealevel_pa, (1.0 / 5.255))) return altitude def read_sealevel_pressure(self, altitude_m=0.0): """Calculates the pressure at sealevel when given a known altitude in meters. Returns a value in Pascals.""" pressure = float(self.read_pressure()) p0 = pressure / pow(1.0 - altitude_m / 44330.0, 5.255) return p0 @staticmethod def convert_data(msb, lsb, xlsb): data = ((msb << 8 | lsb) << 8 | xlsb) >> 4 return data
class SHT21 : RHmeasure_noHold = 0xF5 Tmeasure_noHold = 0xF3 RHmeasure_Hold = 0xE5 Tmeasure_Hold = 0xE3 Soft_Reset = 0xFE Write_Reg = 0xE6 Read_Reg = 0xE7 ############################################################################## ## Experimental register found by looking for each one individually ## ## with a 10 seconds wait between each try. CheckCRC says true for all. ## RH_Reg = 0x05 ## T_Reg = 0x03 ## ## read_reg? 0x06 ## ## read_reg 0x07 ## ## unknown 0x09 result was 6,0,90(constant over time) ## ## unknown 0x0F result was 2,68,32(constant over time) ## ## serial number? 0x1A periodic on 64 bits? ## ## result was [25, 203, 218, 223, 71, 170, 137, 242, 217, 140, 232 ## ## , 120, 231, 86, 128, 122, 7, 151, 248, 59, 252, 255, ## ## 232, 120, 54, 99, 129, 75, 30, 92, 80, 126] ## ## serial number? 0x1B same as 0x1A with random shift ## ## T_reg? 0xE3 result was 103,88,60(made a new measure?) ## ## RH_reg? 0xE5 result was 83,206,146(new measure?) ## ## read_reg 0xE6 result was 58,30 ## ## read_reg 0xE7 result was 58,30 ## ## unknown 0xE9 result was 6,0,90 ## ## unknown 0xEF result was 2,68,32 ## ## serial number 0xFA same as 1A, check sensirion(says 64 bits ID)## ## serial number? 0xFB same as 1B ## ## device ID? 0xFF check i2c full specs, results seems random ## ############################1################################################# class CRCError(Exception): pass def __init__(self, addr, busnum = 1) : self.address = addr self.bus = SMBus(busnum) #self.bus.open(busnum) self.Reset() #reg = self.ReadReg() reg = 0 if (reg & 0x80) and (reg & 0x01): self.RH_res = 11 self.T_res = 11 elif (reg & 0x80) and not(reg & 0x01): self.RH_res = 10 self.T_res = 13 elif not(reg & 0x80) and not(reg & 0x01): self.RH_res = 12 self.T_res = 14 else: self.RH_res = 8 self.T_res = 12 def getRH(self): self.bus.write_byte(self.address, self.RHmeasure_noHold) time.sleep(0.1) RH = self.bus.read_i2c_block_data(self.address, self.RH_Reg, 3) #print RH if self.CheckCRC(RH): self.RHum = RH RH[1] &= ~0x03 #reset 2 status bits(LSB) return -6+125.*(RH[0]*256+RH[1])/65536. else: #print 'CRC checksum failed, data was corrupted(RH reading)' #return -1 raise self.CRCError def getT(self): self.bus.write_byte(self.address, self.Tmeasure_noHold) time.sleep(0.1) T = self.bus.read_i2c_block_data(self.address, self.T_Reg, 3) #print T if self.CheckCRC(T): self.Temp = T T[1] &= ~0x03 #reset 2 status bits(LSB) return -46.85+175.72*(T[0]*256+T[1])/65536. else: #print 'CRC checksum failed, data was corrupted(temp reading)' #return -1 raise self.CRCError def Reset(self): self.bus.write_byte(self.address, self.Soft_Reset) time.sleep(0.02) #must wait 15ms def ReadReg(self): reg = self.bus.read_word_data(self.address, self.Read_Reg) crc = [ reg & 0xFF, (reg & 0xFF00) >> 8] if self.CheckCRC(crc): return reg & 0xFF else: #print 'Error : CRC not matching !' #return 0 raise self.CRCError def WriteReg(self, val): reg = self.ReadReg() reg &= 0x38 self.bus.write_byte_data(self.address, self.Write_Reg, val) def test(self): self.T = [] self.getRH() self.getT() for i in range(256): try : time.sleep(10) self.T.append((hex(i), self.bus.read_i2c_block_data(sensor.address, i))) print(hex(i), 'success reading') except IOError as err: print(hex(i), 'failed reading') return self.T def CheckCRC(self, buf): poly = 0x131 crc = 0 #print buf[2] for by in buf: crc ^= by for i in range(8): if crc & 0x80 : crc = (crc << 1)^poly else: crc <<= 1 #print crc return crc==0
class Hardware: def __init__(self, leds, pins): self.leds = leds self.pins = pins GPIO.setmode(GPIO.BCM) GPIO.setup(self.leds.values(), GPIO.OUT) self.HumidityTemperature = Adafruit_DHT.DHT11 self.lightAddress = 0x23 self.lightMode = 0x20 self.Light = SMBus(1) GPIO.setup(self.pins['PIR'], GPIO.IN) for pin in self.pins['PIR']: GPIO.add_event_detect(pin, GPIO.RISING, callback=self._onPIR) self.PIRON = False GPIO.setup(self.pins['Sound'], GPIO.IN) GPIO.add_event_detect(self.pins['Sound'], GPIO.RISING, callback=self._onSound) self.SOUNDON = False GPIO.setup(self.pins['Human'], GPIO.IN) GPIO.add_event_detect(self.pins['Human'], GPIO.RISING, callback=self._onHuman) self.HUMANON = False def _set(self, led, state): if state: GPIO.output(led, GPIO.HIGH) else: GPIO.output(led, GPIO.LOW) def _getHumidityTemperature(self): humidity, temperature = Adafruit_DHT.read_retry(self.HumidityTemperature, self.pins['HumidityTemperature']) return humidity, temperature def _getLight(self): reading = self.Light.read_i2c_block_data(self.lightAddress, self.lightMode) def convertToNumber(data): return (data[1] + (256 * data[0]))/1.2 return convertToNumber(reading) def _onPIR(self, *args): self.PIRON = True def _getPIR(self): if self.PIRON: self.PIRON = False return 1 else: return 0 def _onSound(self, *args): self.SOUNDON = True def _getSound(self): if self.SOUNDON: self.SOUNDON = False return 1 else: return 0 def _getTemperature(self): reading = self.Temperature.read_word_data(self.temperatureAddress, 0) & 0xFFFF reading = ((reading << 8) & 0xFF00) + (reading >> 8) return (reading / 32.0) / 8.0 def _onHuman(self, *args): self.HUMANON = True def _getHuman(self): if self.HUMANON: self.HUMANON = False return 1 else: return 0 def update(self, booked=None, occupied=None): if booked: self._set(self.leds['YELLOW'], booked) self._set(self.leds['GREEN'], (not booked)) if occupied: self._set(self.leds['YELLOW'], occupied) self._set(self.leds['GREEN'], (not occupied)) # Sets the appropriate lighting/screen based on the booked and occupied status def download(self): data = {} data['Humidity'], data['Temperature'] = self._getHumidityTemperature() data['Light'] = self._getLight() data['Sound'] = self._getSound() data['PIR'] = self._getPIR() data['Human'] = self._getHuman() print(data) return data
bus.write_byte_data(ADDR, CTRL_REG1, newSetting) # Enable event flags bus.write_byte_data(ADDR, PT_DATA_CFG, 0x07) # Toggel One Shot setting = bus.read_byte_data(ADDR, CTRL_REG1) if (setting & 0x02) == 0: bus.write_byte_data(ADDR, CTRL_REG1, (setting | 0x02)) # Read sensor data print "Waiting for data..." status = bus.read_byte_data(ADDR,0x00) while (status & 0x08) == 0: #print bin(status) status = bus.read_byte_data(ADDR,0x00) time.sleep(0.5) print "Reading sensor data..." p_data = bus.read_i2c_block_data(ADDR,0x01,3) t_data = bus.read_i2c_block_data(ADDR,0x04,2) status = bus.read_byte_data(ADDR,0x00) print "status: "+bin(status) p_msb = p_data[0] p_csb = p_data[1] p_lsb = p_data[2] t_msb = t_data[0] t_lsb = t_data[1] pressure = (p_msb << 10) | (p_csb << 2) | (p_lsb >> 6) p_decimal = ((p_lsb & 0x30) >> 4)/4.0 celsius = t_msb + (t_lsb >> 4)/16.0 fahrenheit = (celsius * 9)/5 + 32 print "Pressure and Temperature at "+time.strftime('%m/%d/%Y %H:%M:%S%z') print str(pressure+p_decimal)+" Pa" print str(celsius)+deg+"C"
class HTAngle: def __init__(self, bus_no, address): self.bus = SMBus(bus_no) self.address = address self.angle = 0 # angle, degrees(datetime.utcnow().strftime('%H-%M-%S.%f')[:-3]0 - 359) self.acc_angle = 0 # accumulated angle, degrees(-2147483648 - 2147483647) self.rpm = 0 # rotations per minute (-1000 to 1000) self.current_data1_bit = False self.current_data2_bit = False self.last_data1_bit = False self.last_data2_bit = False self.update() def set_mode(self, mode): self.bus.write_byte_data(self.address, 0x41, mode) def get_mode(self): return self.bus.read_byte_data(self.address, 0x41) def reset(self): # reset accumulated angle self.set_mode(MODE_RESET) time.sleep(0.1) # calibrate angle self.set_mode(MODE_CALIBRATE) time.sleep(0.1) self.update() def update(self): ######################################################################## ### * ERROR FILTERING! ### ### (1) data = 0xff ### ### (2) data[1]의 최상위 비트 반전 (data[0]의 최상위비트) ### ### (3) data[2]의 최상위 비트 반전 ### ######################################################################## isError = True while isError: try: data = self.bus.read_i2c_block_data(self.address, 0x41, 10) # error filtering (1) if data[1] == data[2] == data[3] == data[4] == data[5] == data[ 6] == data[7] == data[8] == 0xff: isError = True time.sleep(0.0001) continue if data[2] == 0xff: isError = True time.sleep(0.0001) continue # not error else: isError = False except (TypeError, OSError) as e: print("update error: {0}".format(str(e))) isError = True time.sleep(0.0001) # error filtering (3) self.current_data1_bit = True if data[1] & 0x20 == 0x20 else False self.current_data2_bit = True if data[2] & 0x80 == 0x80 else False if self.last_data1_bit and self.last_data2_bit: if self.current_data1_bit and not self.current_data2_bit: data[2] = data[2] | 0x80 self.last_data1_bit = self.current_data1_bit self.last_data2_bit = self.current_data2_bit # angle self.angle = (data[1] & 0x7f) * 2 + (data[2] & 0x01) + ( (data[2] & 0x80) << 1) # error filtering (2) # accumulated angle acc = (((data[3] & 0x7f) + (data[4] & 0x80)) * 0x1000000)\ + (((data[4] & 0x7f) + (data[5] & 0x80)) * 0x10000)\ + (((data[5] & 0x7f) + (data[6] & 0x80)) * 0x100)\ + ((data[6] & 0x7f) + (data[7] & 0x80)) # convert to signed if acc > 0x7fffffff: self.acc_angle = (0x100000000 - acc) * (-1) else: self.acc_angle = acc # rpm rpm = (data[7] & 0x7f) * 0x100 + (data[8] & 0x7f) + (data[9] & 0x80) # convert to signed if rpm > 0x3fff: self.rpm = (0x8000 - rpm) * (-1) else: self.rpm = rpm return (self.angle, self.acc_angle, self.rpm)
class MS5611: """Driver for reading temperature/pressure MS5611 Pressure Sensor.""" def __init__(self, bus = 1, i2c = 0x76, elevation = 0): """Initialize the Driver. Default bus is 1. If you have a Rev 1 RPi then you will need to use bus 0. A bus object can also be passed in if you are sharing it among other modules Arguments (All optional): bus -- 0, 1, or a bus object i2c -- I2C address elevation -- Elevation in meters""" if(bus == 0 or bus == 1): self.bus = SMBus(bus) else: self.bus = bus self.i2c = i2c self.elevation = elevation def setElevation(self, elevation): self.elevation = elevation def setElevationFt(self, elevation): self.elevation = elevation / 3.2808 def setI2c(self, i2c): self.i2c = i2c def read(self): ## Get raw pressure self.bus.write_byte(self.i2c, 0x48) time.sleep(0.05) D1 = self.bus.read_i2c_block_data(self.i2c, 0x00) D1 = D1[0] * 65536 + D1[1] * 256.0 + D1[2] time.sleep(0.05) ## Get raw temperature self.bus.write_byte(self.i2c, 0x58) time.sleep(0.05) D2 = self.bus.read_i2c_block_data(self.i2c, 0x00) D2 = D2[0] * 65536 + D2[1] * 256.0 + D2[2] time.sleep(0.05) ## Read Constants from Sensor if hasattr(self, 'C1'): C1 = self.C1 else: C1 = self.bus.read_i2c_block_data(self.i2c, 0xA2) #Pressure Sensitivity C1 = C1[0] * 256.0 + C1[1] self.C1 = C1 time.sleep(0.05) if hasattr(self, 'C2'): C2 = self.C2 else: C2 = self.bus.read_i2c_block_data(self.i2c, 0xA4) #Pressure Offset C2 = C2[0] * 256.0 + C2[1] self.C2 = C2 time.sleep(0.05) if hasattr(self, 'C3'): C3 = self.C3 else: C3 = self.bus.read_i2c_block_data(self.i2c, 0xA6) #Temperature coefficient of pressure sensitivity C3 = C3[0] * 256.0 + C3[1] self.C3 = C3 time.sleep(0.05) if hasattr(self, 'C4'): C4 = self.C4 else: C4 = self.bus.read_i2c_block_data(self.i2c, 0xA8) #Temperature coefficient of pressure offset C4 = C4[0] * 256.0 + C4[1] self.C4 = C4 time.sleep(0.05) if hasattr(self, 'C5'): C5 = self.C5 else: C5 = self.bus.read_i2c_block_data(self.i2c, 0xAA) #Reference temperature C5 = C5[0] * 256.0 + C5[1] self.C5 = C5 time.sleep(0.05) if hasattr(self, 'C6'): C6 = self.C6 else: C6 = self.bus.read_i2c_block_data(self.i2c, 0xAC) #Temperature coefficient of the temperature C6 = C6[0] * 256.0 + C6[1] self.C6 = C6 time.sleep(0.05) ## These are the calculations provided in the datasheet for the sensor. dT = D2 - C5 * 2**8 TEMP = 2000 + dT * C6 / 2**23 ## Set Values to class to be used elsewhere self.tempC = TEMP/100.0 self.tempF = TEMP/100.0 * 9.0/5 + 32 self.tempK = TEMP/100.0 + 273.15 ## These calculations are all used to produce the final pressure value OFF = C2 * 2**16 + (C4 * dT) / 2**7 SENS = C1 * 2**15 + (C3 * dT) / 2**8 P = (D1 * SENS / 2**21 - OFF) / 2**15 self.pressure = P/100.0 ## Calculate an offset for the pressure. This is required so that the readings are correct. ## Equation can be found here: http://en.wikipedia.org/wiki/Barometric_formula altOffset = math.exp( (-9.80665 * 0.0289644 * self.elevation) / (8.31432 * self.tempK) ) self.pressureAdj = ( P/altOffset ) / 100.0 def getTempC(self): return self.tempC def getTempF(self): return self.tempF def getPressure(self): return self.pressure def getPressureAdj(self): return self.pressureAdj def getBus(self): return self.bus def printResults(self): print "Temperature:", round(self.tempC, 2), "C" print " ", round(self.tempF, 2), "F" print "Pressure Absolute:", round(self.pressure, 2), "hPa" print " Adjusted:", round(self.pressureAdj, 2), "hPa" print " Adjusted:", round(self.convert2In(self.pressureAdj), 2), "in" def convert2In(self, pressure): return pressure * 0.0295301
## Import Libraries that let python talk to I2C devices from smbus import SMBus ## Initialize the bus. (If you have a Rev 2 Raspberry Pi the 0 needs to be changed to a 1) bus = SMBus(0) ## This writes the command to the Sensor to calculate the digital value of pressure. (This is a raw value and will # be used in a calculation later on in the script to get the actual real pressure.) bus.write_byte(0x76, 0x48) time.sleep(0.05) ## This command reads the data that we just calculated on the sensor ## I had to use the read_i2c_block_data rather than the read_word or read_byte because the values being returned by the # sensor were 24 bit and was being truncated by the other read methods. Reading the whole data block was the only way # that I knew to get all of the data. D1 = bus.read_i2c_block_data(0x76, 0x00) time.sleep(0.05) ## This is much like above only it is getting the raw temperature. bus.write_byte(0x76, 0x58) time.sleep(0.05) D2 = bus.read_i2c_block_data(0x76, 0x00) time.sleep(0.05) ## The data being read in blocks are in an array in 8 bit pieces, so we need to convert the first 24 bits into decimal, # which is what this statement does. D1 = D1[0] * 65536 + D1[1] * 256.0 + D1[2] D2 = D2[0] * 65536 + D2[1] * 256.0 + D2[2] ## The MS6511 Sensor stores 6 values in the EPROM memory that we need in order to calculate the actual temperature and pressure ## These values are calculated/stored at the factory when the sensor is calibrated.
class Mpl3115A2(object): #I2C ADDRESS/BITS ADDRESS = (0x60) #REGISTERS REGISTER_STATUS = (0x00) REGISTER_STATUS_TDR = 0x02 REGISTER_STATUS_PDR = 0x04 REGISTER_STATUS_PTDR = 0x08 REGISTER_PRESSURE_MSB = (0x01) REGISTER_PRESSURE_CSB = (0x02) REGISTER_PRESSURE_LSB = (0x03) REGISTER_TEMP_MSB = (0x04) REGISTER_TEMP_LSB = (0x05) REGISTER_DR_STATUS = (0x06) OUT_P_DELTA_MSB = (0x07) OUT_P_DELTA_CSB = (0x08) OUT_P_DELTA_LSB = (0x09) OUT_T_DELTA_MSB = (0x0A) OUT_T_DELTA_LSB = (0x0B) BAR_IN_MSB = (0x14) BAR_IN_LSB = (0x15) WHOAMI = (0x0C) #BITS PT_DATA_CFG = 0x13 PT_DATA_CFG_TDEFE = 0x01 PT_DATA_CFG_PDEFE = 0x02 PT_DATA_CFG_DREM = 0x04 CTRL_REG1 = (0x26) CTRL_REG1_SBYB = 0x01 CTRL_REG1_OST = 0x02 CTRL_REG1_RST = 0x04 CTRL_REG1_OS1 = 0x00 CTRL_REG1_OS2 = 0x08 CTRL_REG1_OS4 = 0x10 CTRL_REG1_OS8 = 0x18 CTRL_REG1_OS16 = 0x20 CTRL_REG1_OS32 = 0x28 CTRL_REG1_OS64 = 0x30 CTRL_REG1_OS128 = 0x38 CTRL_REG1_RAW = 0x40 CTRL_REG1_ALT = 0x80 CTRL_REG1_BAR = 0x00 CTRL_REG2 = (0x27) CTRL_REG3 = (0x28) CTRL_REG4 = (0x29) CTRL_REG5 = (0x2A) REGISTER_STARTCONVERSION = (0x12) def __init__(self): self.bus = SMBus(1) self.verify_device() self.initialize() def verify_device(self): whoami = self.bus.read_byte_data(self.ADDRESS, self.WHOAMI) if whoami != 0xc4: # 0xc4 is a default value, but it can be programmed to other # values. Mine reports 0xee. print "Device not active: %x != %x"%(whoami,0xc4) return False return True def initialize(self): self.bus.write_byte_data( self.ADDRESS, self.CTRL_REG1, self.CTRL_REG1_SBYB | self.CTRL_REG1_OS128 | self.CTRL_REG1_ALT) self.bus.write_byte_data( self.ADDRESS, self.PT_DATA_CFG, self.PT_DATA_CFG_TDEFE | self.PT_DATA_CFG_PDEFE | self.PT_DATA_CFG_DREM) def poll(self,flag=None): if flag is None: flag=self.REGISTER_STATUS_PDR sta = 0 while not (sta & self.REGISTER_STATUS_PDR): sta = self.bus.read_byte_data(self.ADDRESS, self.REGISTER_STATUS) def altitude(): self.bus.write_byte_data( self.ADDRESS, self.CTRL_REG1, self.CTRL_REG1_SBYB | self.CTRL_REG1_OS128 | self.CTRL_REG1_ALT) self.poll() msb, csb, lsb = self.bus.read_i2c_block_data(self.ADDRESS, self.REGISTER_PRESSURE_MSB,3) alt = ((msb<<24) | (csb<<16) | (lsb<<8)) / 65536. # correct sign if alt > (1<<15): alt -= 1<<16 return alt def temperature(self): self.bus.write_byte_data( self.ADDRESS, self.CTRL_REG1, self.CTRL_REG1_SBYB | self.CTRL_REG1_OS128 | self.CTRL_REG1_BAR) self.poll() return self.read_temperature() def read_temperature(self): msb, lsb = self.bus.read_i2c_block_data(self.ADDRESS, self.REGISTER_TEMP_MSB,2) # 12 bit, 2s-complement in degrees C. return ( (msb<<8) | lsb) / 256.0 def pressure(self): self.bus.write_byte_data( self.ADDRESS, self.CTRL_REG1, self.CTRL_REG1_SBYB | self.CTRL_REG1_OS128 | self.CTRL_REG1_BAR) self.poll() return self.read_pressure() def press_temp(self): self.bus.write_byte_data( self.ADDRESS, self.CTRL_REG1, self.CTRL_REG1_SBYB | self.CTRL_REG1_OS128 | self.CTRL_REG1_BAR) self.poll(self.REGISTER_STATUS_PDR|self.REGISTER_STATUS_TDR) press=self.read_pressure() temp=self.read_temperature() return press,temp def read_pressure(self): msb, csb, lsb = self.bus.read_i2c_block_data(self.ADDRESS, self.REGISTER_PRESSURE_MSB,3) return ((msb<<16) | (csb<<8) | lsb) / 64. def calibrate(self): pa = int(self.pressure()/2) self.bus.write_i2c_block_data(self.ADDRESS, self.BAR_IN_MSB, [pa>>8 & 0xff, pa & 0xff])
class HTAngle: def __init__(self, bus_no, address): self.bus = SMBus(bus_no) self.address = address self.angle = 0 # angle, degrees(0 - 359) self.acc_angle = 0 # accumulated angle, degrees(-2147483648 - 2147483647) self.rpm = 0 # rotations per minute (-1000 to 1000) self.update() def set_mode(self, mode): self.bus.write_byte_data(self.address, 0x41, mode) def get_mode(self): return self.bus.read_byte_data(self.address, 0x41) def reset(self): # reset accumulated angle self.set_mode(MODE_RESET) time.sleep(0.1) # calibrate angle self.set_mode(MODE_CALIBRATE) time.sleep(0.1) self.update() def update(self): isError = True while isError: try: data = self.bus.read_i2c_block_data(self.address, 0x41, 10) isError = False except OSError as e: print(e) isError = True # error filtering if data[1] == data[2] == data[3] == data[4] == data[5] == data[6] == data[7] == data[8] == 0xff: return (self.angle, self.acc_angle, self.rpm), True # angle self.angle = (data[1] & 0xff) * 2 + (data[2] & 0x01) + ((data[2] & 0x80) << 1) # accumulated angle acc = (((data[3] & 0x7f) + (data[4] & 0x80)) * 0x1000000)\ + (((data[4] & 0x7f) + (data[5] & 0x80)) * 0x10000)\ + (((data[5] & 0x7f) + (data[6] & 0x80)) * 0x100)\ + ((data[6] & 0x7f) + (data[7] & 0x80)) # convert to signed if acc > 0x7fffffff: self.acc_angle = (0x100000000 - acc) * (-1) else: self.acc_angle = acc # rpm rpm = (data[7] & 0x7f) * 0x100 + (data[8] & 0x7f) + (data[9] & 0x80) # convert to signed if rpm > 0x3fff: self.rpm = (0x8000 - rpm) * (-1) else: self.rpm = rpm return (self.angle, self.acc_angle, self.rpm), False
class Cap1xxx(): supported = [PID_CAP1208, PID_CAP1188, PID_CAP1166] number_of_inputs = 8 number_of_leds = 8 def __init__(self, i2c_addr=DEFAULT_ADDR, i2c_bus=1, alert_pin=-1, reset_pin=-1, on_touch=None, skip_init=False): if on_touch == None: on_touch = [None] * self.number_of_inputs self.async_poll = None self.i2c_addr = i2c_addr self.i2c = SMBus(i2c_bus) self.alert_pin = alert_pin self.reset_pin = reset_pin self._delta = 50 GPIO.setmode(GPIO.BCM) if not self.alert_pin == -1: GPIO.setup(self.alert_pin, GPIO.IN, pull_up_down=GPIO.PUD_UP) if not self.reset_pin == -1: GPIO.setup(self.reset_pin, GPIO.OUT) GPIO.setup(self.reset_pin, GPIO.LOW) GPIO.output(self.reset_pin, GPIO.HIGH) time.sleep(0.01) GPIO.output(self.reset_pin, GPIO.LOW) self.handlers = { 'press' : [None] * self.number_of_inputs, 'release' : [None] * self.number_of_inputs, 'held' : [None] * self.number_of_inputs } self.touch_handlers = on_touch self.last_input_status = [False] * self.number_of_inputs self.input_status = ['none'] * self.number_of_inputs self.input_delta = [0] * self.number_of_inputs self.input_pressed = [False] * self.number_of_inputs self.repeat_enabled = 0b00000000 self.release_enabled = 0b11111111 self.product_id = self._get_product_id() if not self.product_id in self.supported: raise Exception("Product ID {} not supported!".format(self.product_id)) if skip_init: return # Enable all inputs with interrupt by default self.enable_inputs(0b11111111) self.enable_interrupts(0b11111111) # Disable repeat for all channels, but give # it sane defaults anyway self.enable_repeat(0b00000000) self.enable_multitouch(True) self.set_hold_delay(210) self.set_repeat_rate(210) # Tested sane defaults for various configurations self._write_byte(R_SAMPLING_CONFIG, 0b00001000) # 1sample per measure, 1.28ms time, 35ms cycle self._write_byte(R_SENSITIVITY, 0b01100000) # 2x sensitivity self._write_byte(R_GENERAL_CONFIG, 0b00111000) self._write_byte(R_CONFIGURATION2, 0b01100000) self.set_touch_delta(10) atexit.register(self.stop_watching) def get_input_status(self): """Get the status of all inputs. Returns an array of 8 boolean values indicating whether an input has been triggered since the interrupt flag was last cleared.""" touched = self._read_byte(R_INPUT_STATUS) threshold = self._read_block(R_INPUT_1_THRESH, self.number_of_inputs) delta = self._read_block(R_INPUT_1_DELTA, self.number_of_inputs) #status = ['none'] * 8 for x in range(self.number_of_inputs): if (1 << x) & touched: status = 'none' _delta = self._get_twos_comp(delta[x]) #threshold = self._read_byte(R_INPUT_1_THRESH + x) # We only ever want to detect PRESS events # If repeat is disabled, and release detect is enabled if _delta >= threshold[x]: # self._delta: self.input_delta[x] = _delta # Touch down event if self.input_status[x] in ['press','held']: if self.repeat_enabled & (1 << x): status = 'held' if self.input_status[x] in ['none','release']: if self.input_pressed[x]: status = 'none' else: status = 'press' else: # Touch release event if self.release_enabled & (1 << x) and not self.input_status[x] == 'release': status = 'release' else: status = 'none' self.input_status[x] = status self.input_pressed[x] = status in ['press','held','none'] else: self.input_status[x] = 'none' self.input_pressed[x] = False return self.input_status def _get_twos_comp(self,val): if ( val & (1<< (8 - 1))) != 0: val = val - (1 << 8) return val def clear_interrupt(self): """Clear the interrupt flag, bit 0, of the main control register""" main = self._read_byte(R_MAIN_CONTROL) main &= ~0b00000001 self._write_byte(R_MAIN_CONTROL, main) def _interrupt_status(self): if self.alert_pin == -1: return self._read_byte(R_MAIN_CONTROL) & 1 else: return not GPIO.input(self.alert_pin) def wait_for_interrupt(self, timeout=100): """Wait for, interrupt, bit 0 of the main control register to be set, indicating an input has been triggered.""" start = self._millis() while True: status = self._interrupt_status() # self._read_byte(R_MAIN_CONTROL) if status: return True if self._millis() > start + timeout: return False time.sleep(0.005) def on(self, channel=0, event='press', handler=None): self.handlers[event][channel] = handler self.start_watching() return True def start_watching(self): if not self.alert_pin == -1: try: GPIO.add_event_detect(self.alert_pin, GPIO.FALLING, callback=self._handle_alert, bouncetime=1) self.clear_interrupt() except: pass return True if self.async_poll == None: self.async_poll = AsyncWorker(self._poll) self.async_poll.start() return True return False def stop_watching(self): if not self.alert_pin == -1: GPIO.remove_event_detect(self.alert_pin) if not self.async_poll == None: self.async_poll.stop() self.async_poll = None return True return False def set_touch_delta(self, delta): self._delta = delta def auto_recalibrate(self, value): self._change_bit(R_GENERAL_CONFIG, 3, value) def filter_analog_noise(self, value): self._change_bit(R_GENERAL_CONFIG, 4, not value) def filter_digital_noise(self, value): self._change_bit(R_GENERAL_CONFIG, 5, not value) def set_hold_delay(self, ms): """Set time before a press and hold is detected, Clamps to multiples of 35 from 35 to 560""" repeat_rate = self._calc_touch_rate(ms) input_config = self._read_byte(R_INPUT_CONFIG2) input_config = (input_config & ~0b1111) | repeat_rate self._write_byte(R_INPUT_CONFIG2, input_config) def set_repeat_rate(self, ms): """Set repeat rate in milliseconds, Clamps to multiples of 35 from 35 to 560""" repeat_rate = self._calc_touch_rate(ms) input_config = self._read_byte(R_INPUT_CONFIG) input_config = (input_config & ~0b1111) | repeat_rate self._write_byte(R_INPUT_CONFIG, input_config) def _calc_touch_rate(self, ms): ms = min(max(ms,0),560) scale = int((round(ms / 35.0) * 35) - 35) / 35 return int(scale) def _handle_alert(self, pin=-1): inputs = self.get_input_status() self.clear_interrupt() for x in range(self.number_of_inputs): self._trigger_handler(x, inputs[x]) def _poll(self): """Single polling pass, should be called in a loop, preferably threaded.""" if self.wait_for_interrupt(): self._handle_alert() def _trigger_handler(self, channel, event): if event == 'none': return if callable(self.handlers[event][channel]): try: self.handlers[event][channel](CapTouchEvent(channel, event, self.input_delta[channel])) except TypeError: self.handlers[event][channel](channel, event) def _get_product_id(self): return self._read_byte(R_PRODUCT_ID) def enable_multitouch(self, en=True): """Toggles multi-touch by toggling the multi-touch block bit in the config register""" ret_mt = self._read_byte(R_MTOUCH_CONFIG) if en: self._write_byte(R_MTOUCH_CONFIG, ret_mt & ~0x80) else: self._write_byte(R_MTOUCH_CONFIG, ret_mt | 0x80 ) def enable_repeat(self, inputs): self.repeat_enabled = inputs self._write_byte(R_REPEAT_EN, inputs) def enable_interrupts(self, inputs): self._write_byte(R_INTERRUPT_EN, inputs) def enable_inputs(self, inputs): self._write_byte(R_INPUT_ENABLE, inputs) def _write_byte(self, register, value): self.i2c.write_byte_data(self.i2c_addr, register, value) def _read_byte(self, register): return self.i2c.read_byte_data(self.i2c_addr, register) def _read_block(self, register, length): return self.i2c.read_i2c_block_data(self.i2c_addr, register, length) def _millis(self): return int(round(time.time() * 1000)) def _set_bit(self, register, bit): self._write_byte( register, self._read_byte(register) | (1 << bit) ) def _clear_bit(self, register, bit): self._write_byte( register, self._read_byte(register) & ~(1 << bit ) ) def _change_bit(self, register, bit, state): if state: self._set_bit(register, bit) else: self._clear_bit(register, bit) def _change_bits(self, register, offset, size, bits): original_value = self._read_byte(register) for x in range(size): original_value &= ~(1 << (offset+x)) original_value |= (bits << offset) self._write_byte(register, original_value) def __del__(self): self.stop_watching()
bus = 1 address = 0x48 duration = 10 # seconds filename = "test.wav" # Prepare file = wave.open(filename, 'w') file.setnchannels(1) # Mono file.setframerate(860) # Frames per second file.setsampwidth(2) # 2 bytes per frame adc = SMBus(bus) # Reset adc.write_byte(0x00, 0x06) time.sleep(0.5) # Set configuration # 1 101 111 0 = de # 111 0 1 0 00 = e8 adc.write_i2c_block_data(address, 0x01, [0xde, 0xe8]) time.sleep(0.5) # Record input for frame in range(int(duration * 860)): data = adc.read_i2c_block_data(address, 0x00, 2) value = data[0] * 256 + data[1] if value > 32767: value -= 65535 print(value) file.writeframesraw(struct.pack("<h", value)) time.sleep(1 / 860)
#!/usr/bin/python from smbus import SMBus from time import sleep from ctypes import c_short #Pressure and Temprature addr = 0x77 oversampling = 3 # 0..3 bus = SMBus(1); # 0 for R-Pi Rev. 1, 1 for Rev. 2 def get_short(data, index): # return two bytes from data as a signed 16-bit value return c_short((data[index] << 8) + data[index + 1]).value def get_ushort(data, index): # return two bytes from data as an unsigned 16-bit value return (data[index] << 8) + data[index + 1] (chip_id, version) = bus.read_i2c_block_data(addr, 0xD0, 2) #print "Chip Id:", chip_id, "Version:", version #print #print "Reading calibration data..." # Read whole calibration EEPROM data cal = bus.read_i2c_block_data(addr, 0xAA, 22) # Convert byte data to word values ac1 = get_short(cal, 0) ac2 = get_short(cal, 2) ac3 = get_short(cal, 4) ac4 = get_ushort(cal, 6) ac5 = get_ushort(cal, 8) ac6 = get_ushort(cal, 10) b1 = get_short(cal, 12) b2 = get_short(cal, 14) mb = get_short(cal, 16) mc = get_short(cal, 18) md = get_short(cal, 20)
class SHT31D: def __init__(self, i2cAddr): self.address = i2cAddr self.bus = SMBus(1) time.sleep(0.05) def readTemperatureAndHumidity(self): self.writeCommand(SHT31DConstant.SHT31_MEAS_HIGHREP) time.sleep(0.015) TempMSB, TempLSB, TempCRC, HumMSB, HumLSB, HumCRC = self.readData( SHT31DConstant.SHT31_MEAS_HIGHREP) STemp = TempMSB * 16 * 16 + TempLSB SHum = HumMSB * 16 * 16 + HumLSB # print TempCRC if TempCRC != self.CRC8([TempMSB, TempLSB]): TC = "nan" else: TC = -45 + 175 * STemp / float(2**16 - 1) # print HumCRC if HumCRC != self.CRC8([HumMSB, HumLSB]): RH = "nan" else: RH = 100 * SHum / float(2**16 - 1) return (TC, RH) # return def readTemperature(self): (TC, RH) = self.readTemperatureAndHumidity() return TC def readHumidity(self): (TC, RH) = self.readTemperatureAndHumidity() return RH def clearStatus(self): self.writeCommand(SHT31DConstant.SHT31_CLEARSTATUS) def readStatus(self): self.writeCommand(SHT31DConstant.SHT31_READSTATUS) StatusMSB, StatusLSB, StatusCRC = self.readData( SHT31DConstant.SHT31_READSTATUS, 3) if StatusCRC != self.CRC8([StatusMSB, StatusLSB]): return 'nan' else: return StatusMSB << 8 | StatusLSB def heaterEnable(self): self.writeCommand(SHT31DConstant.SHT31_HEATEREN) def heaterDisable(self): self.writeCommand(SHT31DConstant.SHT31_HEATERDIS) def softReset(self): self.writeCommand(SHT31DConstant.SHT31_SOFTRESET) def writeCommand(self, cmd): self.bus.write_word_data(self.address, cmd >> 8, cmd & 0xFF) def readData(self, cmd, numBytes=6): return self.bus.read_i2c_block_data(self.address, cmd, numBytes) def CRC8(self, buffer): """ Polynomial 0x31 (x8 + x5 +x4 +1) """ polynomial = 0x31 crc = 0xFF index = 0 # print buffer for index in range(0, len(buffer)): crc ^= int(buffer[index]) for i in range(8, 0, -1): if crc & 0x80: crc = (crc << 1) ^ polynomial else: crc = (crc << 1) # print crc & 0xFF return crc & 0xFF