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 LEDSign: def __init__(self): self.s = SMBus(0) self.lock = Lock() def print_message(self, line, message): if len(message) > 255: message = message[:255] if message[:-1] != "\x00": message = "".join([message, "\x00"]) self.print_message_loop(line, message) def print_message_loop(self, line, message): if message == "": return self.lock.acquire() self.s.write_i2c_block_data(signAddress, line, [ord(x) for x in message[0:payLoadLen]]) self.lock.release() self.print_message_loop(line, message[payLoadLen:]) def get_status(self): self.lock.acquire() labStatus = self.s.read_byte(signAddress) self.lock.release() return labStatus
class PiGlow: i2c_addr = 0x54 # fixed i2c address of SN3218 ic bus = None def __init__(self, i2c_bus=1): self.bus = SMBus(i2c_bus) # first we tell the SN3218 to enable output (turn on) self.write_i2c(CMD_ENABLE_OUTPUT, 0x01) # then we ask it to enable each bank of LEDs (0-5, 6-11, and 12-17) self.write_i2c(CMD_ENABLE_LEDS, [0xFF, 0xFF, 0xFF]) def update_leds(self, values): #print "update pwm" self.write_i2c(CMD_SET_PWM_VALUES, values) self.write_i2c(CMD_UPDATE, 0xFF) # a helper that writes the given value or list of values to the SN3218 IC # over the i2c protocol def write_i2c(self, reg_addr, value): # if a single value is provided then wrap it in a list so we can treat # all writes in teh same way if not isinstance(value, list): value = [value]; # write the data to the SN3218 self.bus.write_i2c_block_data(self.i2c_addr, reg_addr, value)
class mcp(object): """Driver for mcp4725 DAC.""" _ADDRESS = 0x61 _WRITEDAC = 0x40 #Write data directly to DAC. _WRITEDACEEPROM = 0x60 #Write data to DAC and to EEPROM for persistent value accross resets. def __init__( self ): super(mcp, self).__init__() self._i2c = SMBus(1) self._buffer = [0, 0] self.seteprom(0) def set( self, aValue ): ''' Set the DAC to the given value which is only 12 bits in size (0xFFF). ''' self._buffer[0] = aValue >> 4 self._buffer[1] = (aValue & 0xF) << 4 self._i2c.write_i2c_block_data(mcp._ADDRESS, mcp._WRITEDAC, self._buffer) def seteprom( self, aValue ): ''' Set the DAC to the given value which is only 12 bits in size (0xFFF). ''' self._buffer[0] = aValue >> 4 self._buffer[1] = (aValue & 0xF) << 4 self._i2c.write_i2c_block_data(mcp._ADDRESS, mcp._WRITEDACEEPROM, self._buffer)
class motorControlBoard: """Class to allow communication with the motor control board built by me using I2C.""" __board_I2C_address = 0 def __init__(self, board_address): if isinstance(board_address, int): if board_address > 0 and board_address < 0x78: self.__board_I2C_address = board_address else: raise Exception("Board address must be an integer between 0 and 0b1111000 (=120) exclusive.") else: raise Exception("Board address must be an integer.") self.__bus = SMBus(1) # FIXME = have an option to make this zero for the old Raspberry Pis def set_speeds(self, left_speed, right_speed): # Enforce limits due to 8-bit resolution if(left_speed < -0xff): left_speed = -0xff if(left_speed > +0xff): left_speed = +0xff # Enforce limits due to 8-bit resolution if(right_speed < -0xff): right_speed = -0xff if(right_speed > +0xff): right_speed = +0xff direction = 0x00; if(left_speed < 0): direction |= MOTOR_CONTROL_LEFT_BACK elif(left_speed > 0): direction |= MOTOR_CONTROL_LEFT_FORE if(right_speed < 0): direction |= MOTOR_CONTROL_RIGHT_BACK elif(right_speed > 0): direction |= MOTOR_CONTROL_RIGHT_FORE self.__bus.write_i2c_block_data(self.__board_I2C_address, MOTOR_CONTROL_SET_DIR_SPEED_CMD, [direction, abs(left_speed), abs(right_speed)])
class LEDSign: def __init__(self): self.s = SMBus(0) self.lock = Lock() def print_message(self, line, message): if len(message) > 255: message = message[:255] if message[:-1] != "\x00": message = ''.join([message, "\x00"]) self.print_message_loop(line, message) def print_message_loop(self, line, message): if message == "": return self.lock.acquire() self.s.write_i2c_block_data(signAddress, line, [ord(x) for x in message[0:payLoadLen]]) self.lock.release() self.print_message_loop(line, message[payLoadLen:]) def get_status(self): self.lock.acquire() labStatus = self.s.read_byte(signAddress) self.lock.release() return labStatus
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 set_comp(self, t, h): # don't know if a value of 0.0% RH is allowed # so make minimun RH 0.01% if h < 0.1: h = 0.01 if t < -25.0: t = -25.0 rh = h * 2.0 rh_i = int(rh // 1) rh_i &= 0xff #rh_d = int( (rh % 1) * 256 ) # per CC-803-AN rev 6, AMS writes zero to fractional byte rh_d = 0x00 # per datasheet 25 degree offset th = (t + 25) * 2.0 th_i = int(th // 1) th_i &= 0xff #th_d = int( (th % 1) * 256 ) # per CC-803-AN tev 6, AMS writes zero to fractional byte th_d = 0x00 msg = [rh_i, rh_d, th_i, th_d] print "ccs811.set_comp() set T: %.1f RH: %.1f" % (t, h) print "ccs811.set_comp() regs. 0x%02x 0x%02x 0x%02x 0x%02x" % ( th_i, th_d, rh_i, rh_d) bus = SMBus(I2CBUS) bus.write_i2c_block_data(self.I2Caddr, CCS811_REG_ENV_DATA, msg) bus.close() return
class PiGlowService(rpyc.Service): def on_connect(self): pass def on_disconnect(self): pass def exposed_init(self): self.bus = SMBus(1) self.bus.write_byte_data(0x54, 0x00, 0x01) self.bus.write_byte_data(0x54, 0x13, 0xFF) self.bus.write_byte_data(0x54, 0x14, 0xFF) self.bus.write_byte_data(0x54, 0x15, 0xFF) def exposed_colours(self, red, orange, yellow, green, blue, white): try: self.bus.write_i2c_block_data(0x54, 0x01, [red, orange, yellow, green, blue, green, red, orange, yellow, white, white, blue, white, green, blue, yellow, orange, red]) self.bus.write_byte_data(0x54, 0x16, 0xFF) except IOError: pass def exposed_all_off(self): try: self.bus.write_i2c_block_data(0x54, 0x01, [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]) self.bus.write_byte_data(0x54, 0x16, 0xFF) except IOError: pass
def _set_regs(self, register, value): bus = SMBus(I2CBUS) if isinstance(value, int): bus.write_byte_data(self.i2c_addr, register, value) else: bus.write_i2c_block_data(self.i2c_addr, register, value) bus.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)
class rigmi2c(object): def __init__(self): self.bus = SMBus(1) self.addr = 42 def readall(self): try: data = self.bus.read_i2c_block_data(self.addr, 1, 32) rd = [] for i in range(8): rd.append(data[4 * i] | (data[1 + 4 * i] << 8) | (data[2 + 4 * i] << 16) | (data[3 + 4 * i] << 24)) return rd except Exception as e: print(e) try: self.__init__() except Exception as f: pass return None def _writeReg(self, cmd, addr, val): try: addr &= 0xf cmd &= 0xf c = (cmd << 4) | addr d3 = (val >> 24) & 0xff d2 = (val >> 16) & 0xff d1 = (val >> 8) & 0xff d0 = val & 0xff self.bus.write_i2c_block_data(self.addr, c, [d3, d2, d1, d0]) time.sleep(0.30) # necessary to avoid some kind of i2c error return True except Exception as e: print('- Error writing to i2c device.') print(e) try: print('- attempting to restart i2c') self.__init__() print(self.readall()) except Exception as f: pass return False def setWord(self, addr, bits): return self._writeReg(0, addr, bits) def setBits(self, addr, bits): return self._writeReg(1, addr, bits) def clrBits(self, addr, bits): return self._writeReg(2, addr, bits) def tglBits(self, addr, bits): return self._writeReg(3, addr, bits)
class rigmi2c(object): def __init__(self): self.bus = SMBus(1) self.addr = 42 def readall(self): try: data = self.bus.read_i2c_block_data(self.addr, 1, 32) time.sleep(0.050) # necessary to avoid some kind of i2c error rd = [] for i in range(16): rd.append(data[2 * i] | (data[1 + 2 * i] << 8)) return rd except Exception as e: print("Exception while reading.") print(e) self.reset_Ard() return None def _writeReg(self, cmd, addr, val): addr &= 0xf cmd &= 0xf c = (cmd << 4) | addr d1 = (val >> 8) & 0xff d0 = val & 0xff try: self.bus.write_i2c_block_data(self.addr, c, [d1, d0]) except Exception as e: self.reset_Ard() time.sleep(0.050) # necessary to avoid some kind of i2c error def reset_Ard(self): print('Resetting Atmega') GPIO.setmode(GPIO.BOARD) GPIO.setup(7, GPIO.OUT) GPIO.output(7, GPIO.LOW) GPIO.output(7, GPIO.HIGH) time.sleep(0.020) GPIO.output(7, GPIO.LOW) GPIO.setup(7, GPIO.IN) def setWord(self, addr, bits): self._writeReg(0, addr, bits) def setBits(self, addr, bits): self._writeReg(1, addr, bits) def clrBits(self, addr, bits): self._writeReg(2, addr, bits) def tglBits(self, addr, bits): self._writeReg(3, addr, bits)
def StartBootloaderI2C(addr): print("Starting bootloader \n") try: bus = SMBus(1) #startCmd = [0xFE, 0x01, 0xFE] bus.write_i2c_block_data(addr, 0xFE, [0x01, 0xFE]) time.sleep(0.01) #usleep(10000) print("Starting bootloader old firmware\n") bus.write_i2c_block_data(addr, 0xFE, [0x01]) time.sleep(0.01) except: return
def get_status(command, value): status = "" bus = SMBus(i2cBusAddr) BytesToSend = convert_string_to_bytes(value) bus.write_i2c_block_data(arduinoSlaveAddress, ord(command), BytesToSend) time.sleep(0.001) for i in range (0, 11): statusChr = chr(bus.read_byte(arduinoSlaveAddress)) if statusChr != ";": status += statusChr else: break bus.close() return status
def set_baseline(self, hi, lo): msg = [hi, lo] bus = SMBus(I2CBUS) resp = bus.write_i2c_block_data(self.I2Caddr, CCS8_REG_BASELINE, msg) bus.close() return
class I2C: mutex = Lock() @classmethod def start(self): try: self.bus = SMBus(1) sleep(0.5) except Exception as e: Logger.warn("Could not found i2c bus : " + str(e)) @classmethod def write_reg(self, ip, register, data): self.mutex.acquire() try: self.bus.write_byte_data(ip, register, data) except Exception as e: Logger.error("I2C write reg error : " + str(e)) sleep(0.01) # to make sure all the infos are sent self.mutex.release() @classmethod def write_data(self, ip, data): self.mutex.acquire() try: self.bus.write_i2c_block_data(ip, 0, data) except Exception as e: Logger.error("I2C write data error : " + str(e)) self.mutex.release() return 1 sleep(0.01) self.mutex.release() return 0 @classmethod def read_reg(self, ip, register): self.mutex.acquire() try: data = self.bus.read_byte_data(ip, register) except Exception as e: Logger.error("I2C read reg error : " + str(e)) self.mutex.release() return None sleep(0.01) self.mutex.release() return data
class I2CBacklight: """Dimming by I2C / SMBUS.""" def __init__(self, bus: int, address: int, offset: int, values: PercentageMap): """Sets the respective I2C configuration.""" try: self.smbus = SMBus(bus) except FileNotFoundError: raise DoesNotExist() from None self.address = address self.offset = offset self.values = values @property def max(self): """Returns the maximum raw value.""" return max(self.values) @property def raw(self): """Returns the raw set value.""" return self._read(self.offset) @raw.setter def raw(self, value): """Sets the raw value.""" if value in self.values: return self._write(self.offset, value) raise ValueError(value) @property def percent(self): """Returns the current brightness in percent.""" range_ = self.values[self.raw] return sum(range_) / len(range_) @percent.setter def percent(self, percent): """Returns the current brightness in percent.""" if 0 <= percent <= 100: self.raw = self.values.from_percent(percent) else: raise ValueError(f'Invalid percentage: {percent}.') def _read(self, address: int) -> int: """Reads the respective address.""" return self.smbus.read_i2c_block_data( self.address, address, 1)[0] def _write(self, address: int, value: int): """Reads the respective address.""" return self.smbus.write_i2c_block_data( self.address, address, [value])
class I2CBus: def __init__(self, bus_number=1): self.bus = SMBus(bus_number) self.lock = threading.Lock() def write_data(self, address, cmd, data_list): with self.lock: try: self.bus.write_i2c_block_data(address, cmd, data_list) return 1 except OSError as my_error: print("CAN`T WRITE DATA. ERROR: ", my_error) return 0 def read_data(self, address, register, number_of_bytes): with self.lock: try: recieved_data = self.bus.read_i2c_block_data(address, register, number_of_bytes) return recieved_data except OSError as my_error: print("CAN`T READ DATA. ERROR: ", my_error) return 0
class ArduinoCommunicator: def __init__(self, arduino_address): self.address = arduino_address self.bus = SMBus(1) self.write_attempt = 0 self.data_from_arduino = dict.fromkeys(["IMU data"]) self.UPDATE_SEND_REGISTER = 11 self.data_to_arduino_register = { "cone_x": 1, "cone_y": 2 } self.SIZE_OF_ARDUINO_SEND_REGISTERS = 8 def write_float_to_register(self, num, register): """ Writes a float into the Arduino's receive register """ if register < 0 or register > 7: raise Exception("Error in write float: register must be in [0,7]") data = list(bytearray(str(num), 'utf8')) self._write(register, data) def _write(self, register, data): timeout = 10 try: self.bus.write_i2c_block_data(self.address, register, data) self.write_attempt = 0 except Exception as e: self.write_attempt += 1 if self.write_attempt < timeout: print("Failed to write due to Exception " + str(e) + ". Trying again") self._write(register, data) else: print("Timed out writing") traceback.print_exc()
class i2c_interface: def __init__(self, address=0x3c): """ :param address: i2c address of ssd1306 """ self.bus = SMBus(self.bus_id()) self.address = address def __del__(self): self.close_i2c() def close_i2c(self): self.bus.close() def bus_id(self): """ :return: Returns SMBUS id of Raspberry Pi """ revision = [ lines[12:-1] for lines in open('/proc/cpuinfo', 'r').readlines() if "Revision" in lines[:8] ] revision = (revision + ['0000'])[0] return 1 if int(revision, 16) >= 4 else 0 def i2c_read(self, register=0): data = self.bus.read_byte_data(self.address, register) return data def i2c_write(self, register=DISPLAY_START_LINE, data=0): # Write a byte to address, register self.bus.write_byte_data(self.address, register, data) def i2c_write_block(self, register=DISPLAY_START_LINE, data=None): if data is None: data = [40] self.bus.write_i2c_block_data(self.address, register, data)
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)
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)
class sn3218: i2c_addr = 0x54 bus = None values = [0x00] * 18 def __init__(self, i2c_bus=1): self.bus = SMBus(i2c_bus) # Enable output self.write(CMD_ENABLE_OUTPUT, 0x01) # Enable LEDs ( 0-5, 6-11, 12-17 ) self.write(CMD_ENABLE_LEDS, [0xFF, 0xFF, 0XFF]) def setList(self, pins, values): if not isinstance(pins, list) and isinstance(values, list): for i, v in enumerate(values): self.set( (i+pins) % 18, v ) elif isinstance(pins, list) and isinstance(values, list): if len(pins) == len(values): for i, v in enumerate(values): self.set( pins[i], v) else: raise ValueError(TXT_LIST_LEN_MISMATCH) return False elif isinstance(pins, list) and not isinstance(values, list): for i, p in enumerate(pins): self.set( p, values ); return True def set(self, pin, value): if isinstance(value, list) or isinstance(pin, list): return self.setList( pin, value ) if pin > 17 or pin < 0: raise ValueError(TXT_OUT_OF_RANGE) return False if value > 255 or value < 0: raise ValueError(TXT_PWM_INVALID) return False self.values[pin] = value return True def get(self, pin, value): if pin > 17 or pin < 0: raise ValueError(TXT_OUT_OF_RANGE) return False if value > 255 or value < 0: raise ValueError(TXT_PWM_INVALID) return False return self.values[pin] def update(self): self.write(CMD_SET_PWM_VALUES, self.values) self.write(CMD_UPDATE, 0xFF) def write(self, reg_addr, value): # Treat all writes as block writes if not isinstance(value, list): value = [value] self.bus.write_i2c_block_data(self.i2c_addr, reg_addr, value)
from smbus import SMBus import time import datetime import calendar import sys, getopt i2cbus=SMBus(1) def _GetChecksum(data): fcs=0xFF for x in data[:]: fcs=fcs^x return fcs data = [0x55, 0x26, 0xa0, 0x2b] fcs = _GetChecksum(data) d = data[:] d.append(fcs) i2cbus.write_i2c_block_data(0x14, 248, d)
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
class Board: # Methods list # * __init__(gpio_en, gpio_stby, i2cbus = None, gpio_mode_bcm = False) # * power(on = None) # * reset() # * mute(on = None) # Constants list # * DSP - holding instance of DSP control class # * TUNER - holding instance of TUNER control class # Internal variables list # * _gpio_en - GPIO pin connected to the EN pin of the board # * _gpio_stby - GPIO pin connected to the ST-BY pin of the board # * _bus - holding instance of SMBus providing I2C bus for communication with chips on the board # * _state - dictionary holding current setup of the board #* #* Inits class #* @param int gpio_en - GPIO pin connected to the EN pin of board #* @param int gpio_stby - GPIO pin connected to the ST-BY pin of board #* @param int i2cbus - number of i2c bus the board is connected to #* @param bool gpio_mode_bcm - if the mode of GPIO module used for specifying GPIO pins is BCM (True) or BOARD (False) #* def __init__(self, gpio_en, gpio_stby, i2cbus = None, gpio_mode_bcm = False): if i2cbus == None: raise Exception()#TODO auto selection based on RPI board revision self._gpio_en = gpio_en self._gpio_stby = gpio_stby self._bus = SMBus(i2cbus) sleep(0.5) GPIO.setmode(GPIO.BCM if gpio_mode_bcm else GPIO.BOARD) GPIO.setup(self._gpio_en, GPIO.OUT, GPIO.LOW) GPIO.setup(self._gpio_stby, GPIO.OUT, GPIO.LOW) self._state = { "power": False, "mute": True } self.DSP = DSP(self) self.TUNER = TUNER(self) # init GPIOs self.power(False) self.mute(True) # end of method __init__ #* #* Destructor #* def __del__(self): self.power(False) GPIO.cleanup() # end of method __del__ #* #* Turns on-board voltage regulators on or off #* @param bool on - True/False for setting the power state, None to return current state only #* @return bool - if the voltage regulators are on or off (software only) #* def power(self, on = None): if on != None: old_state = self._state["power"] self._state["power"] = bool(on) if not self._state["power"]: self.mute(True) self.DSP.beforePowerOff() self.TUNER.beforePowerOff() sleep(0.2) GPIO.output(self._gpio_en, self._state["power"]) if not old_state and self._state["power"]: sleep(0.5) self.DSP.afterPowerOn() self.TUNER.afterPowerOn() return self._state["power"] # end of method power #* #* Resets board by turning it off and then on after 2 seconds #* def reset(self): self.power(False) sleep(2) self.power(True) # end of method reset #* #* Enables or disables amplifier stand-by mode #* @param bool on - True/False for setting the mute, None to return current state only #* @return bool - if the amplifier is muted or not (software only) #* def mute(self, on = None): if on != None: on = bool(on) if self._state["power"] or on: self._state["mute"] = on GPIO.output(self._gpio_stby, not self._state["mute"]) return self._state["mute"] # end of method mute #* #* Send data over I2C if the Board is powered on #* @param int address - address byte #* @param tuple/list data - data bytes to be sent #* def _i2c_write(self, address, data): if address < 0 or len(data) < 1: return if not self._state["power"]:# send data to board but only if it is powered return if len(data) > 1: self._bus.write_i2c_block_data(address, data[0], data[1:]) else: self._bus.write_byte(address, data[0])
class I2CBus: # The device ids supported # Note: Under linux, the enumeration of the i2c devices is not guaranteed to match the BBB device id, i.e., i2c0 may # not map to /dev/i2c-0. Here is a link on this topic: https://datko.net/2013/11/03/bbb_i2c # What is important from a software perspective is that pins and the device id match since we don't use the linux # device name. That is, we need to use an id, 0, 1, 2, which corresponds to a specific device connected on specific # pins. # Note: I2C device 0 is not enabled by default. There is a way to enable it (see above) but there are also possible # conflicts with existing capes. DEV_I2C_0 = 0 DEV_I2C_1 = 1 DEV_I2C_2 = 2 # The following formatting is taken from struct and maps the character designations to number of bytes in the type __TYPE_SIZES = {'d': 8, # double - 8 bytes 'f': 4, # float - 4 bytes 'L': 4, # uint32 - 4 bytes 'l': 4, # int32 - 4 bytes 'H': 2, # uint16 - 2 bytes 'h': 2, # int16 - 2 bytes 'B': 1, # uint8 - 1 byte 'b': 1 # int8 - 1 byte } def __init__(self, device): try: self._smbus = SMBus(device) except RuntimeError: raise I2CBusError("Unable to open SMBus using {}".format(device)) def _read_multiple_bytes(self, address, offset, num_bytes): return self._smbus.read_i2c_block_data(address, offset, num_bytes) def _write_multiple_bytes(self, address, offset, byte_values): self._smbus.write_i2c_block_data(address, offset, list(byte_values)) def WriteUint8(self, address, offset, value): self._smbus.write_byte_data(address, offset, value) def WriteUint16(self, address, offset, value): self._smbus.write_word_data(address, offset, value) def WriteInt16(self, address, offset, value): self._smbus.write_word_data(address, offset, value) def WriteUint32(self, address, offset, value): bytes = bytearray(struct.pack('L', value)) self._write_multiple_bytes(address, offset, bytes) def WriteFloat(self, address, offset, value): bytes = bytearray(struct.pack('f',value)) self._write_multiple_bytes(address, offset, bytes) def WriteArray(self, address, offset, values, type, endian=sys.byteorder): # Convert each value to its byte representation and place into a bytearray before writing to the bus # Note: struct.pack returns a string representation of the value. For a 1-byte value, it is a # string representation of 1 byte, for a 2 or 4 byte value, it is a 2-byte of 4-byte representation # Therefore, it is necessary to concatentate the strings before converting to a bytearray if endian == 'little': format = '<'+type else: format = '>'+type byte_values = '' for value in values: byte_values += struct.pack(format, value) self._write_multiple_bytes(address, offset, bytearray(byte_values)) def ReadUint8(self, address, offset): return self._smbus.read_byte_data(address, offset) def ReadUint16(self, address, offset): return self._smbus.read_word_data(address, offset) def ReadInt16(self, address, offset): return self._smbus.read_word_data(address, offset) def ReadUint32(self, address, offset): bytes = self._read_multiple_bytes(address, offset, I2CBus.__TYPE_SIZES['L']) return struct.unpack('L', str(bytearray(bytes)))[0] def ReadInt32(self, address, offset): bytes = self._read_multiple_bytes(address, offset, I2CBus.__TYPE_SIZES['l']) return struct.unpack('l', str(bytearray(bytes)))[0] def ReadFloat(self, address, offset): values = self._read_multiple_bytes(address, offset, I2CBus.__TYPE_SIZES['f']) return struct.unpack('f', str(bytearray(values)))[0] def ReadArray(self, address, offset, num_values, type, endian=sys.byteorder): # Create a format specifier based on the number of values requested. # All of the values will be read as the same type, e.g., all floats, all long, etc # The format specifies the number of float values to convert format = '%s%s' % (num_values, type) # Calculate number of bytes to read # - num_values is the number of values to read # - num_bytes is num_values * size of each value num_bytes = num_values * I2CBus.__TYPE_SIZES[type] # It turns out that reading i2c block data is not supported on all Raspberry Pi's (probably a OS/driver difference) # The Pi 2 running Jessie doesn't support i2c (i2cget with no arguments shows no 'i' option) # The Pi 3 running Jessie does support i2c (i2cget with no argument shows 'i' option) # So, we need to support both options bytes = self._read_multiple_bytes(address, offset, num_bytes) # Match the endianess of the request. Default is platform endianess # struct provides a format specifier for endianess if endian == 'little': format = '<'+format else: format = '>'+format return list(struct.unpack(format, str(bytearray(bytes))))
class MPL115A2: # select the SMBus channel (depends on RaspberryPI model) bus = SMBus(0) # the I2C address of the MPL115A2 sensor # default is 0x60 MPL115A2_ADDRESS = (0x60) # the register addresses of the MPL115A2 sensor MPL115A2_REGISTER_PRESSURE_MSB = (0x00) MPL115A2_REGISTER_PRESSURE_LSB = (0x01) MPL115A2_REGISTER_TEMP_MSB = (0x02) MPL115A2_REGISTER_TEMP_LSB = (0x03) MPL115A2_REGISTER_A0_COEFF_MSB = (0x04) MPL115A2_REGISTER_A0_COEFF_LSB = (0x05) MPL115A2_REGISTER_B1_COEFF_MSB = (0x06) MPL115A2_REGISTER_B1_COEFF_LSB = (0x07) MPL115A2_REGISTER_B2_COEFF_MSB = (0x08) MPL115A2_REGISTER_B2_COEFF_LSB = (0x09) MPL115A2_REGISTER_C12_COEFF_MSB = (0x0A) MPL115A2_REGISTER_C12_COEFF_LSB = (0x0B) MPL115A2_REGISTER_STARTCONVERSION = (0x12) # some private variables a0_MSB = -1 a0_LSB = -1 b1_MSB = -1 b1_LSB = -1 b2_MSB = -1 b2_LSB = -1 c12_MSB = -1 c12_LSB = -1 _mpl115a2_a0 = -1 _mpl115a2_b1 = -1 _mpl115a2_b2 = -1 _mpl115a2_c12 = -1 pressure_MSB = -1 pressure_LSB = -1 temp_MSB = -1 temp_LSB = -1 temperature = -1 pressure = -1 def __init__(self, address=0x60, smbus=0, debug=True): self.bus = SMBus(smbus) self.MPL115A2_ADDRESS = address self.debug = debug # one time read factory calibrated coefficients from sensor # Read the calibration data self.read_coefficients() # pass # initiate conversion inside the sensor before metrics reading def start_convert(self): # send conversion command needed for pressure reading self.bus.write_i2c_block_data( self.MPL115A2_ADDRESS, self.MPL115A2_REGISTER_STARTCONVERSION, [0x12]) # # sleep until the conversion is certainly completed time.sleep(0.3) def read_raw_data(self): # prepare sensor for reading self.start_convert() # read pressure AGC units self.pressure_MSB = self.bus.read_byte_data( self.MPL115A2_ADDRESS, self.MPL115A2_REGISTER_PRESSURE_MSB) self.pressure_LSB = self.bus.read_byte_data( self.MPL115A2_ADDRESS, self.MPL115A2_REGISTER_PRESSURE_LSB) # read raw temperature AGC units self.temp_MSB = self.bus.read_byte_data( self.MPL115A2_ADDRESS, self.MPL115A2_REGISTER_TEMP_MSB + 0) self.temp_LSB = self.bus.read_byte_data( self.MPL115A2_ADDRESS, self.MPL115A2_REGISTER_TEMP_LSB + 0) # build self.temperature = (self.temp_MSB << 8 | self.temp_LSB) >> 6 self.pressure = (self.pressure_MSB << 8 | self.pressure_LSB) >> 6 self.debug_output(" Raw temperature: " + str(self.temperature)) self.debug_output(" Raw pressure: " + str(self.pressure)) def read_raw_temperature(self): # read raw temperature AGC units self.temp_MSB = self.bus.read_byte_data( self.MPL115A2_ADDRESS, self.MPL115A2_REGISTER_TEMP_MSB + 0) self.temp_LSB = self.bus.read_byte_data( self.MPL115A2_ADDRESS, self.MPL115A2_REGISTER_TEMP_LSB + 0) # build self.temperature = (self.temp_MSB << 8 | self.temp_LSB) >> 6 # returns Temperature in Celsius Float def read_temperature(self): self.read_raw_temperature() return (self.temperature - 498.0) / -5.35 + 25.0 # returns Pressure reading in Pa Float def read_pressure(self): self.read_raw_data() pressureComp = self._mpl115a2_a0 + \ (self._mpl115a2_b1 + self._mpl115a2_c12 * self.temperature) * \ self.pressure + self._mpl115a2_b2 * self.temperature press = ((65.0 / 1023.0) * pressureComp) + 50.0 return press def read_both(self): self.read_raw_data() pressureComp = self._mpl115a2_a0 + \ (self._mpl115a2_b1 + self._mpl115a2_c12 * self.temperature) * \ self.pressure + self._mpl115a2_b2 * self.temperature temp = (self.temperature - 498.0) / -5.35 + 25.0 press = ((65.0 / 1023.0) * pressureComp) + 50.0 return {'temperature': temp, 'pressure': press} # read the factory coefficients from the sensor def read_coefficients(self): self.a0_MSB = self.bus.read_byte_data( self.MPL115A2_ADDRESS, self.MPL115A2_REGISTER_A0_COEFF_MSB + 0) self.a0_LSB = self.bus.read_byte_data( self.MPL115A2_ADDRESS, self.MPL115A2_REGISTER_A0_COEFF_LSB + 0) self.b1_MSB = self.bus.read_byte_data( self.MPL115A2_ADDRESS, self.MPL115A2_REGISTER_B1_COEFF_MSB + 0) self.b1_LSB = self.bus.read_byte_data( self.MPL115A2_ADDRESS, self.MPL115A2_REGISTER_B1_COEFF_LSB + 0) self.b2_MSB = self.bus.read_byte_data( self.MPL115A2_ADDRESS, self.MPL115A2_REGISTER_B2_COEFF_MSB + 0) self.b2_LSB = self.bus.read_byte_data( self.MPL115A2_ADDRESS, self.MPL115A2_REGISTER_B2_COEFF_LSB + 0) self.c12_MSB = self.bus.read_byte_data( self.MPL115A2_ADDRESS, self.MPL115A2_REGISTER_C12_COEFF_MSB + 0) self.c12_LSB = self.bus.read_byte_data( self.MPL115A2_ADDRESS, self.MPL115A2_REGISTER_C12_COEFF_LSB + 0) # unpack to 10bits full scale self._mpl115a2_a0 = (float)( (self.a0_MSB << 8) | self.a0_LSB) / (2 << 3) self._mpl115a2_b1 = (float)( (self.b1_MSB << 8) | self.b1_LSB) / (2 << 13) self._mpl115a2_b2 = (float)( (self.b2_MSB << 8) | self.b2_LSB) / (2 << 14) self._mpl115a2_c12 = (float)( (self.c12_MSB << 8) | (self.c12_LSB >> 2)) / (2 << 13) def debug_output(self, message): if (self.debug): print "DEBUG: (" + inspect.stack()[1][3] +")" + str(message)
# 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 def mcp_irq(pin): global oldState x = bus.read_i2c_block_data(addr, INTCAPA, 4) newState = x[2] | (x[3] << 8) for i in range(16): bit = 1 << i lvl = newState & bit if lvl != (oldState & bit): ui.write(e.EV_KEY, key[i], 0 if lvl else 1)
global _on_move _on_move = handler return register def airwheel(): ''' Bind an action to the "airhweel" gesture Point your finger at the Skywriter and spin it in a wheel The handler will receive a rotation delta in degrees ''' def register(handler): global _on_airwheel _on_airwheel = handler return register def _exit(): stop_poll() if GPIO != None: GPIO.cleanup() atexit.register(_exit) reset() i2c.write_i2c_block_data(SW_ADDR, 0xa1, [0b00000000, 0b00011111, 0b00000000, 0b00011111]) start_poll()
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
#!/bin/env/python # File: eeprom_setup.py # # Setup test data on the I2C EEPROM # # Date: 6/28/18 # Platform: Raspberry Pi 3 Model B # # Python Version: 2.7.9 from smbus import SMBus # For I2C operations vals = [0, 0, 5, 0, 1, 0, 245, 0, 2, 1, 245, 0, 3, 2, 244, 0, 4, 4, 244, 0, 5, 3, 243] bus = SMBus(1) # Declare "Bus" Object bus.write_i2c_block_data(0x50, 0, vals) # Write data to EEPROM print "Finished"
class PiGlow: def __init__(self): if rpi.RPI_REVISION == 1: i2c_bus = 0 elif rpi.RPI_REVISION == 2: i2c_bus = 1 elif rpi.RPI_REVISION == 3: i2c_bus = 1 else: print "Unable to determine Raspberry Pi revision." exit self.bus = SMBus(i2c_bus) self.bus.write_i2c_block_data(0x54, 0x00, [0x01]) self.bus.write_byte_data(0x54, 0x13, 0xFF) self.bus.write_byte_data(0x54, 0x14, 0xFF) self.bus.write_byte_data(0x54, 0x15, 0xFF) def white(self, value): self.bus.write_byte_data(0x54, 0x0A, value) self.bus.write_byte_data(0x54, 0x0B, value) self.bus.write_byte_data(0x54, 0x0D, value) self.bus.write_byte_data(0x54, 0x16, 0xFF) def blue(self, value): self.bus.write_byte_data(0x54, 0x05, value) self.bus.write_byte_data(0x54, 0x0C, value) self.bus.write_byte_data(0x54, 0x0F, value) self.bus.write_byte_data(0x54, 0x16, 0xFF) def green(self, value): self.bus.write_byte_data(0x54, 0x06, value) self.bus.write_byte_data(0x54, 0x04, value) self.bus.write_byte_data(0x54, 0x0E, value) self.bus.write_byte_data(0x54, 0x16, 0xFF) def yellow(self, value): self.bus.write_byte_data(0x54, 0x09, value) self.bus.write_byte_data(0x54, 0x03, value) self.bus.write_byte_data(0x54, 0x10, value) self.bus.write_byte_data(0x54, 0x16, 0xFF) def orange(self, value): self.bus.write_byte_data(0x54, 0x08, value) self.bus.write_byte_data(0x54, 0x02, value) self.bus.write_byte_data(0x54, 0x11, value) self.bus.write_byte_data(0x54, 0x16, 0xFF) def red(self, value): self.bus.write_byte_data(0x54, 0x07, value) self.bus.write_byte_data(0x54, 0x01, value) self.bus.write_byte_data(0x54, 0x12, value) self.bus.write_byte_data(0x54, 0x16, 0xFF) def all(self, value): v = value self.bus.write_i2c_block_data( 0x54, 0x01, [v, v, v, v, v, v, v, v, v, v, v, v, v, v, v, v, v, v]) self.bus.write_byte_data(0x54, 0x16, 0xFF) def arm(self, arm, value): if arm == 1: self.bus.write_byte_data(0x54, 0x07, value) self.bus.write_byte_data(0x54, 0x08, value) self.bus.write_byte_data(0x54, 0x09, value) self.bus.write_byte_data(0x54, 0x06, value) self.bus.write_byte_data(0x54, 0x05, value) self.bus.write_byte_data(0x54, 0x0A, value) self.bus.write_byte_data(0x54, 0x16, 0xFF) elif arm == 2: self.bus.write_byte_data(0x54, 0x0B, value) self.bus.write_byte_data(0x54, 0x0C, value) self.bus.write_byte_data(0x54, 0x0E, value) self.bus.write_byte_data(0x54, 0x10, value) self.bus.write_byte_data(0x54, 0x11, value) self.bus.write_byte_data(0x54, 0x12, value) self.bus.write_byte_data(0x54, 0x16, 0xFF) elif arm == 3: self.bus.write_byte_data(0x54, 0x01, value) self.bus.write_byte_data(0x54, 0x02, value) self.bus.write_byte_data(0x54, 0x03, value) self.bus.write_byte_data(0x54, 0x04, value) self.bus.write_byte_data(0x54, 0x0F, value) self.bus.write_byte_data(0x54, 0x0D, value) self.bus.write_byte_data(0x54, 0x16, 0xFF) else: print "Unknown number, expected only 1, 2 or 3" def arm1(self, value): self.bus.write_byte_data(0x54, 0x07, value) self.bus.write_byte_data(0x54, 0x08, value) self.bus.write_byte_data(0x54, 0x09, value) self.bus.write_byte_data(0x54, 0x06, value) self.bus.write_byte_data(0x54, 0x05, value) self.bus.write_byte_data(0x54, 0x0A, value) self.bus.write_byte_data(0x54, 0x16, 0xFF) def arm2(self, value): self.bus.write_byte_data(0x54, 0x0B, value) self.bus.write_byte_data(0x54, 0x0C, value) self.bus.write_byte_data(0x54, 0x0E, value) self.bus.write_byte_data(0x54, 0x10, value) self.bus.write_byte_data(0x54, 0x11, value) self.bus.write_byte_data(0x54, 0x12, value) self.bus.write_byte_data(0x54, 0x16, 0xFF) def arm3(self, value): self.bus.write_byte_data(0x54, 0x01, value) self.bus.write_byte_data(0x54, 0x02, value) self.bus.write_byte_data(0x54, 0x03, value) self.bus.write_byte_data(0x54, 0x04, value) self.bus.write_byte_data(0x54, 0x0F, value) self.bus.write_byte_data(0x54, 0x0D, value) self.bus.write_byte_data(0x54, 0x16, 0xFF) def colour(self, colour, value): if colour == 1 or colour == "white": self.bus.write_byte_data(0x54, 0x0A, value) self.bus.write_byte_data(0x54, 0x0B, value) self.bus.write_byte_data(0x54, 0x0D, value) self.bus.write_byte_data(0x54, 0x16, 0xFF) elif colour == 2 or colour == "blue": self.bus.write_byte_data(0x54, 0x05, value) self.bus.write_byte_data(0x54, 0x0C, value) self.bus.write_byte_data(0x54, 0x0F, value) self.bus.write_byte_data(0x54, 0x16, 0xFF) elif colour == 3 or colour == "green": self.bus.write_byte_data(0x54, 0x06, value) self.bus.write_byte_data(0x54, 0x04, value) self.bus.write_byte_data(0x54, 0x0E, value) self.bus.write_byte_data(0x54, 0x16, 0xFF) elif colour == 4 or colour == "yellow": self.bus.write_byte_data(0x54, 0x09, value) self.bus.write_byte_data(0x54, 0x03, value) self.bus.write_byte_data(0x54, 0x10, value) self.bus.write_byte_data(0x54, 0x16, 0xFF) elif colour == 5 or colour == "orange": self.bus.write_byte_data(0x54, 0x08, value) self.bus.write_byte_data(0x54, 0x02, value) self.bus.write_byte_data(0x54, 0x11, value) self.bus.write_byte_data(0x54, 0x16, 0xFF) elif colour == 6 or colour == "red": self.bus.write_byte_data(0x54, 0x07, value) self.bus.write_byte_data(0x54, 0x01, value) self.bus.write_byte_data(0x54, 0x12, value) self.bus.write_byte_data(0x54, 0x16, 0xFF) else: print "Only colours 1 - 6 or color names are allowed" def led(self, led, value): leds = [ "0x00", "0x07", "0x08", "0x09", "0x06", "0x05", "0x0A", "0x12", "0x11", "0x10", "0x0E", "0x0C", "0x0B", "0x01", "0x02", "0x03", "0x04", "0x0F", "0x0D"] self.bus.write_byte_data(0x54, int(leds[led], 16), value) self.bus.write_byte_data(0x54, 0x16, 0xFF) def led1(self, value): self.bus.write_byte_data(0x54, 0x07, value) self.bus.write_byte_data(0x54, 0x16, 0xFF) def led2(self, value): self.bus.write_byte_data(0x54, 0x08, value) self.bus.write_byte_data(0x54, 0x16, 0xFF) def led3(self, value): self.bus.write_byte_data(0x54, 0x09, value) self.bus.write_byte_data(0x54, 0x16, 0xFF) def led4(self, value): self.bus.write_byte_data(0x54, 0x06, value) self.bus.write_byte_data(0x54, 0x16, 0xFF) def led5(self, value): self.bus.write_byte_data(0x54, 0x05, value) self.bus.write_byte_data(0x54, 0x16, 0xFF) def led6(self, value): self.bus.write_byte_data(0x54, 0x0A, value) self.bus.write_byte_data(0x54, 0x16, 0xFF) def led7(self, value): self.bus.write_byte_data(0x54, 0x12, value) self.bus.write_byte_data(0x54, 0x16, 0xFF) def led8(self, value): self.bus.write_byte_data(0x54, 0x11, value) self.bus.write_byte_data(0x54, 0x16, 0xFF) def led9(self, value): self.bus.write_byte_data(0x54, 0x10, value) self.bus.write_byte_data(0x54, 0x16, 0xFF) def led10(self, value): self.bus.write_byte_data(0x54, 0x0E, value) self.bus.write_byte_data(0x54, 0x16, 0xFF) def led11(self, value): self.bus.write_byte_data(0x54, 0x0C, value) self.bus.write_byte_data(0x54, 0x16, 0xFF) def led12(self, value): self.bus.write_byte_data(0x54, 0x0B, value) self.bus.write_byte_data(0x54, 0x16, 0xFF) def led13(self, value): self.bus.write_byte_data(0x54, 0x01, value) self.bus.write_byte_data(0x54, 0x16, 0xFF) def led14(self, value): self.bus.write_byte_data(0x54, 0x02, value) self.bus.write_byte_data(0x54, 0x16, 0xFF) def led15(self, value): self.bus.write_byte_data(0x54, 0x03, value) self.bus.write_byte_data(0x54, 0x16, 0xFF) def led16(self, value): self.bus.write_byte_data(0x54, 0x04, value) self.bus.write_byte_data(0x54, 0x16, 0xFF) def led17(self, value): self.bus.write_byte_data(0x54, 0x0F, value) self.bus.write_byte_data(0x54, 0x16, 0xFF) def led18(self, value): self.bus.write_byte_data(0x54, 0x0D, value) self.bus.write_byte_data(0x54, 0x16, 0xFF)
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)
# # MAIN # readCoefficients() # # unpack to 10bits full scale _mpl115a2_a0 = (float)( (a0_MSB<<8) | a0_LSB ) / (2<<3) _mpl115a2_b1 = (float)( (b1_MSB<<8) | b1_LSB ) / (2<<13) _mpl115a2_b2 = (float)( (b2_MSB<<8) | b2_LSB ) / (2<<14) _mpl115a2_c12 = (float)( (c12_MSB<<8) | (c12_LSB >>2) ) / (2<<13) # # send conversion command bus.write_i2c_block_data(MPL115A2_ADDRESS,MPL115A2_REGISTER_STARTCONVERSION,[0x12]) # # sleep until the conversion is certainly completed time.sleep(0.5); # # pressure AGC units pressure_MSB = bus.read_byte_data(MPL115A2_ADDRESS,MPL115A2_REGISTER_PRESSURE_MSB); pressure_LSB = bus.read_byte_data(MPL115A2_ADDRESS,MPL115A2_REGISTER_PRESSURE_LSB); # # temperatture AGC units temp_MSB = bus.read_byte_data(MPL115A2_ADDRESS,MPL115A2_REGISTER_TEMP_MSB+0); temp_LSB = bus.read_byte_data(MPL115A2_ADDRESS,MPL115A2_REGISTER_TEMP_LSB+0);
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 WeatherHat(threading.Thread): def __init__(self): if rpi.RPI_REVISION == 1: i2c_bus = 0 else: i2c_bus = 1 self.bus = SMBus(i2c_bus) self.bus.write_i2c_block_data(0x54, 0x00, [0x01]) self.bus.write_byte_data(0x54, 0x13, 0xFF) self.bus.write_byte_data(0x54, 0x14, 0xFF) self.bus.write_byte_data(0x54, 0x15, 0xFF) self.sun1 = gpiozero.PWMLED(4) self.sun2 = gpiozero.PWMLED(17) self.sun3 = gpiozero.PWMLED(27) def update(self): self.bus.write_byte_data(0x54, 0x16, 0xFF) def cleanup(self): self.bus.write_i2c_block_data(0x54, 0x00, [0x00]) def rain1(self, value): self.bus.write_byte_data(0x54, 0x12, value) self.update() def rain2(self, value): self.bus.write_byte_data(0x54, 0x11, value) self.update() def rain3(self, value): self.bus.write_byte_data(0x54, 0x10, value) self.update() def rain4(self, value): self.bus.write_byte_data(0x54, 0x04, value) self.update() def rain5(self, value): self.bus.write_byte_data(0x54, 0x02, value) self.update() def rain6(self, value): self.bus.write_byte_data(0x54, 0x01, value) self.update() def storm1(self, value): self.bus.write_byte_data(0x54, 0x05, value) self.update() def storm2(self, value): self.bus.write_byte_data(0x54, 0x08, value) self.update() def storm3(self, value): self.bus.write_byte_data(0x54, 0x0A, value) self.update() def storm4(self, value): self.bus.write_byte_data(0x54, 0x06, value) self.update() def storm5(self, value): self.bus.write_byte_data(0x54, 0x09, value) self.update() def storm6(self, value): self.bus.write_byte_data(0x54, 0x0B, value) self.update() def cloud1(self, value): self.bus.write_byte_data(0x54, 0x0F, value) self.update() def cloud2(self, value): self.bus.write_byte_data(0x54, 0x0D, value) self.update() def cloud3(self, value): self.bus.write_byte_data(0x54, 0x0E, value) self.update() def cloud4(self, value): self.bus.write_byte_data(0x54, 0x0C, value) self.update() def cloud5(self, value): self.bus.write_byte_data(0x54, 0x07, value) self.update() def cloud6(self, value): self.bus.write_byte_data(0x54, 0x03, value) self.update() def sunled(self, part, value): if ( part == 1 ): self.sun1.value = value elif ( part == 2 ): self.sun2.value = value else: self.sun3.value = value def rainrun(self): while self.rainrunning == 1: k = 70 j = 20 for i in range(100,1,-1): if j == 1: j = 80 if k == 1: k = 90 self.rain3(j) self.rain2(i) sleep(0.005) self.rain5(i) sleep(0.005) sleep(0.005) self.rain4(j) self.rain1(k) sleep(0.005) self.rain6(k) k = k-1 j = j-1 self.rain1(0) self.rain2(0) self.rain3(0) self.rain4(0) self.rain5(0) self.rain6(0) def raining(self,action): if action == "start": self.rainrunning = 1 threading.Thread(target = self.rainrun).start() if action == "stop": self.rainrunning = 0 def cloudrun(self): while self.cloudrunning == 1: k = 70 j = 20 for i in range(60,1,-1): if j == 1: j = 20 if k == 1: k = 50 self.cloud1(j) self.cloud2(i) sleep(0.005) self.cloud3(i) sleep(0.005) sleep(0.005) self.cloud4(j) self.cloud5(k) sleep(0.005) self.cloud6(k) k = k-1 j = j-1 self.cloud1(0) self.cloud2(0) self.cloud3(0) self.cloud4(0) self.cloud5(0) self.cloud6(0) def cloud(self,action): if action == "start": self.cloudrunning = 1 threading.Thread(target = self.cloudrun).start() if action == "stop": self.cloudrunning = 0 def stormrun(self): while self.stormrunning == 1: for i in range(255,1,-1): self.storm6(i) self.storm5(i-20) self.storm4(i-40) self.storm3(i-60) self.storm2(i-80) self.storm1(i-100) sleep(0.005) self.storm1(0) self.storm2(0) self.storm3(0) self.storm4(0) self.storm5(0) self.storm6(0) def storm(self,action): if action == "start": self.stormrunning = 1 threading.Thread(target = self.stormrun).start() if action == "stop": self.stormrunning = 0 def sunrun(self): while self.sunrunning == 1: for i in frange(0.4,0.2,-0.1): self.sunled(3,i) self.sunled(1,i*2) self.sunled(2,i*1.5) sleep(0.1) self.sunled(1,0.0) self.sunled(2,0.0) self.sunled(3,0.0) def sun(self,action): if action == "start": self.sunrunning = 1 threading.Thread(target = self.sunrun).start() if action == "stop": self.sunrunning = 0 def rainbow(self,action): if action == "start": panel.setPixelColor(0,Color(0,255,0)) panel.setPixelColor(1,Color(50,255,0)) panel.setPixelColor(2,Color(255,255,0)) panel.setPixelColor(3,Color(255,0,0)) panel.setPixelColor(4,Color(0,0,255)) panel.setPixelColor(5,Color(0,255,50)) panel.setPixelColor(6,Color(0,255,255)) panel.show() if action == "stop": panel.setPixelColor(0,Color(0,0,0)) panel.setPixelColor(1,Color(0,0,0)) panel.setPixelColor(2,Color(0,0,0)) panel.setPixelColor(3,Color(0,0,0)) panel.setPixelColor(4,Color(0,0,0)) panel.setPixelColor(5,Color(0,0,0)) panel.setPixelColor(6,Color(0,0,0)) panel.show()
class PyGlow: def __init__(self, i2c_bus=1): self.bus = SMBus(i2c_bus) self.current = self._zerolist() def init(self): self.write_i2c(CMD_ENABLE_OUTPUT, 0x01) self.write_i2c(CMD_ENABLE_LEDS, [0xFF, 0xFF, 0xFF]) self.all_off() def write_i2c(self, reg, value): if not isinstance(value, list): value = [value] self.bus.write_i2c_block_data(I2C_ADDR, reg, value) def update_leds(self, values): self.write_i2c(CMD_SET_PWM_VALUES, values) self.update() def update(self): self.bus.write_byte_data(I2C_ADDR, CMD_UPDATE, 0xFF) def set(self, leds, intensity=DEFAULT_INTENSITY): if not isinstance(leds, list): leds = [leds] for led in leds: self.bus.write_byte_data(I2C_ADDR, LED_ADDRS[led], intensity) def all_off(self): self.current = self._zerolist() self.update_leds(self.current) def turn_off(self, leds): self.set(leds, 0x00) self.update() def light(self, leds, intensity=DEFAULT_INTENSITY): if not isinstance(leds, list): leds = [leds] self.all_off() self.set(leds, intensity) self.update() def fade_in(self, leds, intensity=DEFAULT_INTENSITY, speed=DEFAULT_FADE_SPEED, step=DEFAULT_FADE_STEP): cur_inten = 0x00 while cur_inten <= intensity: self.light(leds, cur_inten) cur_inten += step if cur_inten > 0xFF: break time.sleep(speed) def fade_out(self, leds, intensity=DEFAULT_INTENSITY, speed=DEFAULT_FADE_SPEED, step=DEFAULT_FADE_STEP): while intensity >= 0x00: self.light(leds, intensity) intensity -= step if intensity < 0x00: self.turn_off(leds) break time.sleep(speed) def crossfade(self, leds_start, leds_end, intensity=DEFAULT_INTENSITY, speed=DEFAULT_FADE_SPEED, step=DEFAULT_FADE_STEP): cur_inten_up = 0x00 cur_inten_down = intensity while cur_inten_up < intensity: cur_inten_down -= step cur_inten_up += step if cur_inten_down <= 0x00: self.turn_off(leds_start) break if cur_inten_up >= 0xFF: self.set(leds_end, 0xFF) self.update() break self.set(leds_start, cur_inten_down) self.set(leds_end, cur_inten_up) self.update() time.sleep(speed) def _zerolist(self): return [0x00 for x in range(18)]
print "Microchip" else: print "Unknown" def FindChip(jedec_id): for chip in FlashDevices: if (chip.jedec_id == jedec_id): return chip return None # uint8_t GetManufacturerId(uint32_t jedec_id) def GetManufacturerId(jedec_id): return jedec_id >> 16 print "Enter ISP?" bus.write_i2c_block_data(0x4a,0x6f, [0x80]) # uint32_t jedec_id = SPICommonCommand(E_CC_READ, 0x9f, 3, 0, 0); print "Send SPI command" jedec_id = SPICommonCommand(E_CC_READ, 0x9f, 3, 0, 0); print jedec_id #jedec_id=jedec_id[0] # printf("JEDEC ID: 0x%02x\n", jedec_id); print "JEDEC ID: 0x{:02X}\n".format(jedec_id); chip = FindChip(jedec_id); if jedec_id == 15675411: print "flash matches!" else: print "what is this flash chip?" exit(0)