Exemplo n.º 1
1
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)
Exemplo n.º 2
0
def get_status():
    """
    Get the humidity, tempetature, led and garage door status by calling the arduino by I2C
    Obtenez l'humidité, la température, l'état des leds et de la porte de garage en appelant l'arduino par I2C
    """

    bus = SMBus(1)

    i2c_data1 = bus.read_i2c_block_data(ARDUINO1_I2C_ADDRESS,0)
    humidity, temperature = struct.unpack("ff", struct.pack("B"*8,*i2c_data1[0:8]))
    leds = i2c_data1[8:13]

    i2c_data2 = bus.read_i2c_block_data(ARDUINO2_I2C_ADDRESS,0)
    garage_door = i2c_data2[0]

    bus.close()

    global last_door_status

    # Display door status on LCD - Affiche le status de la porte sur le LCD
    if garage_door == 1 and last_door_status == False:
        display_message("Garage","Open")
        last_door_status = True
    elif garage_door == 0 and last_door_status == True:
        display_message("Garage","Closed")
        last_door_status = False

    response = {"humidity" : humidity,
                "temperature" : temperature,
                "leds" : leds,
                "garageDoor" : garage_door}
    return jsonify(response)
Exemplo n.º 3
0
def main():

    db = QSqlDatabase.addDatabase("QSQLITE")
    db.setDatabaseName("HtrTest.db")
    if not db.open():
        result = QMessageBox.warning(
            None, 'HtrTest', "Database Error: %s" % db.lastError().text())
        print(result)
        sys.exit(1)

    # create IO object
    io = GPIO_config.io()
    pid = PID()

    # create i2c smbus object
    i2c_bus = SMBus(
        1)  # 0 = /dev/i2c-0 (port I2C0), 1 = /dev/i2c-1 (port I2C1)
    # create MCP9600 T/C readout object
    tc = MCP9600(db, i2c_bus)

    cid = tc.mcp9600_read_id()
    print("chip id = %x" % cid)

    qApp = QtWidgets.QApplication(sys.argv)
    aw = ApplicationWindow(db, tc, io, pid)
    aw.setWindowTitle("%s" % progname)
    aw.show()
    sys.exit(qApp.exec_())
    i2c_bus.close()
Exemplo n.º 4
0
    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
Exemplo n.º 5
0
 def getAngle(self):
     bus = SMBus(self.busnum)
     #return self.bus.read_i2c_block_data(self.address, AS5048B_registers["ANGLMSB_REG"], 8) - self.angle_zero
     val = (bus.read_i2c_block_data(self.address,
                                    AS5048B_registers["ANGLMSB_REG"], 2))
     bus.close()
     return val
Exemplo n.º 6
0
    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
Exemplo n.º 7
0
    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()
Exemplo n.º 8
0
 def __init__(self, addr):
     self.address = addr
     bus = SMBus(1)
     self.VOUT_MODE = bus.read_byte_data(self.address, 0x20)
     bus.close()
     voutN = self.VOUT_MODE & 0b00011111
     self.VOUT_N = self.twos_comp(voutN, 5)
     print("DRQ1250 succesfully connected to PMBus... \n")
Exemplo n.º 9
0
class AK8975:
    def __init__(self, i2c_bus, i2c_addr):
        self._bus = SMBus(i2c_bus)
        self._dev_addr = i2c_addr
        self.xCoeff = self._bus.read_byte_data(self._dev_addr, REG_ASAX)
        self.yCoeff = self._bus.read_byte_data(self._dev_addr, REG_ASAY)
        self.zCoeff = self._bus.read_byte_data(self._dev_addr, REG_ASAZ)
        self._bus.write_byte_data(self._dev_addr, REG_CNTL, CNTL_PWRDWN)
        self.offsets = [0.] * 3
        self.scale = [1.] * 3
        self.last_sin = 0.
        self.last_cos = 0.0
        self.lock_counter = 100

    def setOffset(self, offsets):
        self.offsets = offsets

    def setScale(self, scale):
        self.scale = scale

    def close(self):
        self._bus.close()

    def read_gauss(self):
        self._bus.write_byte_data(self._dev_addr, REG_CNTL, CNTL_MEASURE)
        while (self._bus.read_byte_data(self._dev_addr, REG_ST1)
               & ST1_DRDY) == 0:
            time.sleep(0.001)
        data = self._bus.read_i2c_block_data(self._dev_addr, REG_HXL, 6)
        data = bytes(data)
        fields = struct.unpack('hhh', data)
        x = self.adjustValue(fields[0], self.xCoeff)
        y = self.adjustValue(fields[1], self.yCoeff)
        z = self.adjustValue(fields[2], self.zCoeff)
        return (x, y, z)

    def read_heading(self):
        x, y, z = self.read_gauss()
        x = (x - self.offsets[0]) * self.scale[0]
        y = (y - self.offsets[1]) * self.scale[1]
        z = (z - self.offsets[2]) * self.scale[2]
        #heading = 90+ (math.atan2(y, x) * 180./math.pi)
        #heading  = heading + 90.0 #robot compass not north aligned
        heading = math.atan2(y, x)
        self.last_sin = ALPHA * self.last_sin + (1 - ALPHA) * math.sin(heading)
        self.last_cos = ALPHA * self.last_cos + (1 - ALPHA) * math.cos(heading)
        heading = math.atan2(self.last_sin, self.last_cos) * 180. / math.pi
        heading = heading + 180
        if self.lock_counter == 0:
            return heading
        else:
            self.lock_counter = self.lock_counter - 1
            return None

    def adjustValue(self, value, adj):
        # apply the proper compensation to value.  This equation is taken
        # from the AK8975 datasheet, section 8.3.11
        return (value * ((((adj - 128.0) * 0.5) / 128.0) + 1.0))
Exemplo n.º 10
0
 def getPowerOut(self, fromDRQ):
     if (fromDRQ == True):
         bus = SMBus(1)
         self.powerOut = self.decodePMBus(
             bus.read_word_data(self.address, 0x96))
         bus.close()
     else:
         self.powerOut = self.voltageOut * self.current
     return self.powerOut
Exemplo n.º 11
0
    def _get_regs(self, register, length):

        bus = SMBus(I2CBUS)
        if length == 1:
            resp = bus.read_byte_data(self.i2c_addr, register)
        else:
            resp = bus.read_i2c_block_data(self.i2c_addr, register, length)
        bus.close()
        return resp
Exemplo n.º 12
0
 def get_baseline(self):
     # Looks like on power up, the CCS811 keeps
     # adjusting its baseline possibly bacause
     # the calculated tVOC value is negitive.
     # In effect the chip is auto zeroing itself.
     bus = SMBus(I2CBUS)
     resp = bus.read_i2c_block_data(self.I2Caddr, CCS811_REG_BASELINE, 2)
     bus.close()
     bl = (resp[0] << 8) | resp[1]
     #print "Baseline: 0x%04x" % bl
     return bl
Exemplo n.º 13
0
class MPU6050:
    def __init__(self, address_mpu):
        self.address_mpu = address_mpu
        self.i2c = SMBus()
        self.setup()

    def setup(self):
        # open bus 1
        print('open bus 1')
        self.i2c.open(1)

        # sensor uit sleep modus halen
        print('sensor uit sleep modus halen')
        self.i2c.write_byte_data(self.address_mpu, 0x6B, 1)

        # instellen gyroscoop
        print('gyroscoop instellen')
        self.i2c.write_byte_data(self.address_mpu, 0x1B, 0x00)

    def read_data(self):
        # data inlezen
        raw_data = self.i2c.read_i2c_block_data(self.address_mpu, 0x43, 6)
        # gyro
        x_waarde_gyro = self.registerwaarden_omzetten(raw_data[0], raw_data[1])
        y_waarde_gyro = self.registerwaarden_omzetten(raw_data[2], raw_data[3])
        z_waarde_gyro = self.registerwaarden_omzetten(raw_data[4], raw_data[5])
        x_waarde_gyro_in_graden, y_waarde_gyro_in_graden, z_waarde_gyro_in_graden = self.omzetten_graden_per_seconde(
            x_waarde_gyro, y_waarde_gyro, z_waarde_gyro)

        return x_waarde_gyro_in_graden, y_waarde_gyro_in_graden, z_waarde_gyro_in_graden

    @staticmethod
    def registerwaarden_omzetten(msb, lsb):
        msb = msb << 8

        if bin(msb)[2] == '1':
            msb = msb - 2**16

        waarde = msb | lsb
        waarde = waarde / 340 + 36.53

        return waarde

    @staticmethod
    def omzetten_graden_per_seconde(x_waarde, y_waarde, z_waarde):
        rot_x = x_waarde / 131
        rot_y = y_waarde / 131
        rot_z = z_waarde / 131

        return rot_x, rot_y, rot_z

    def opkuisen(self):
        self.i2c.close()
Exemplo n.º 14
0
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
Exemplo n.º 15
0
class VL53LOX:
    def __init__(self, address):
        self.address = address
        self.i2c = SMBus()
        self.setup()

    def setup(self):
        self.i2c.open(1)

    def read_data(self):
        self.i2c.write_byte(self.address, 0)
        value = self.i2c.read_byte(self.address)
        return value

    def close(self):
        self.i2c.close()
Exemplo n.º 16
0
    def setUVLimit(self, uvLimit):

        if (uvLimit > 32):
            uvWarnLimit = float(uvLimit) + 2
            uvFaultLimit = float(uvLimit)
        else:
            uvWarnLimit = 34.0
            uvFaultLimit = 32.0

        bus = SMBus(1)
        #bus.write_byte_data(self.address, 0x10, int(0b00000000))
        bus.write_word_data(self.address, 0x59,
                            int(uvFaultLimit))  #This causes an error
        bus.write_word_data(
            self.address, 0x58, int(uvWarnLimit)
        )  #The error shows up here or if this is commented out it shows up on under the getTempurature method
        bus.close()
Exemplo n.º 17
0
    def run(self):
        while True:
            bus = SMBus(1)
            i2c_data1 = bus.read_i2c_block_data(ARDUINO1_I2C_ADDRESS,0)
            humidity, temperature = struct.unpack("ff", struct.pack("B"*8,*i2c_data1[0:8]))
            bus.close()

            data = {"timestamp" : str(datetime.now()),
                    "humidity" : humidity,
                    "temperature" : temperature}

            with open("dataHistory.json","a+") as f:
                f.write(json.dumps(data) + "\n")
            
            self.elements.append(data)

            if len(self.elements) > self.number_elements:
                self.elements.pop(0)

            time.sleep(self.interval)
Exemplo n.º 18
0
 def kill(self, bf):
     bus = SMBus(1)
     range_sensor = LidarLiteV3(bus)
     range_sensor.begin(0, 0x62)
     dest = range_sensor.get_distance(False, 0x62)
     print "#########################Distance: {}############################".format(
         dest)
     if dest < 160:
         print "Killing"
         laser = Laser()
         laser.trigger(1)
         time.sleep(
             2
         )  #MAKE SURE THE switch_off gets called!! either by timeout or manually calling switch_off()
         print("Laser test done")
         bus.close()
         time.sleep(5)
         im, balloon_list = bf.find_balloons()
         if len(balloon_list) > 0:
             return False
         return True
     return False
Exemplo n.º 19
0
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)
Exemplo n.º 20
0
def detect_device():
    for busNum in range(20):
        if not os.path.exists('/dev/i2c-' + str(busNum)):
            if busNum == 20 - 1:
                print("device not found.")
                return -1
            continue
        bus = SMBus(busNum)
        print("Bus #{} open. Searching...".format(busNum))
        response = bus.read_byte(addr)
        if response >= 0:
            #print("On bus {} a device {} found with response of {}".format(busNum, hex(dev_addr), hex(response)))
            if bus.read_byte_data(addr, 0x00) == 2:
                M = bus.read_byte(addr)
                m = bus.read_byte(addr)
                print(
                    "Bus:{} Addr:{} Reg:0x00 query returns {}.{}.\nPossible AsRock AURA device with FW nu50_{}.{} detected."
                    .format(busNum, hex(addr), M, m, M, m))
                if M != 1 and m != 10:
                    print(
                        "This FW is NOT supported, yet. Try with your own risk!"
                    )
                return bus
        bus.close()
Exemplo n.º 21
0
 def zero_magnitude(self):
     bus = SMBus(self.busnum)
     self.magnitude_zero = bus.read_i2c_block_data(self.address, AS5048B_registers["MAGNMSB_REG"], 8)
     bus.close()
Exemplo n.º 22
0
    class LinuxI2cBus:
        """A Linux I²C device, which is itself an I²C bus.

        Should not be instantiated directly; use `LinuxI2c.find_devices`
        instead.

        This type mimics the `smbus.SMBus` read/write/close APIs.  However,
        `open` does not take any parameters, and not all APIs are available.
        """

        # note: this is not a liquidctl BaseBus, as that would cause
        # find_liquidctl_devices to try to directly instantiate it

        def __init__(self, i2c_dev):
            self._i2c_dev = i2c_dev
            self._smbus = None

            try:
                assert i2c_dev.name.startswith('i2c-')
                self._number = int(i2c_dev.name[4:])
            except:
                raise ValueError(f'cannot infer bus number')

        def find_devices(self, drivers, **kwargs):
            """Probe drivers and find compatible devices in this bus."""
            for drv in drivers:
                yield from drv.probe(self, **kwargs)

        def open(self):
            """Open the I²C bus."""
            if not self._smbus:
                try:
                    self._smbus = SMBus(self._number)
                except FileNotFoundError:
                    if Path('/sys/class/i2c-dev').exists():
                        raise
                    raise OSError('kernel module i2c-dev not loaded') from None

        def read_byte(self, address):
            """Read a single byte from a device."""
            value = self._smbus.read_byte(address)
            _LOGGER.debug('read byte @ 0x%02x: 0x%02x', address, value)
            return value

        def read_byte_data(self, address, register):
            """Read a single byte from a designated register."""
            value = self._smbus.read_byte_data(address, register)
            _LOGGER.debug('read byte data @ 0x%02x:0x%02x: 0x%02x', address,
                          register, value)
            return value

        def read_word_data(self, address, register):
            """Read a single 2-byte word from a given register."""
            value = self._smbus.read_word_data(address, register)
            _LOGGER.debug('read word data @ 0x%02x:0x%02x: 0x%04x', address,
                          register, value)
            return value

        def read_block_data(self, address, register):
            """Read a block of up to  32 bytes from a given register."""
            data = self._smbus.read_block_data(address, register)
            _LOGGER.debug('read block data @ 0x%02x:0x%02x: %r', address,
                          register, LazyHexRepr(data))
            return data

        def write_byte(self, address, value):
            """Write a single byte to a device."""
            _LOGGER.debug('writing byte @ 0x%02x: 0x%02x', address, value)
            return self._smbus.write_byte(address, value)

        def write_byte_data(self, address, register, value):
            """Write a single byte to a designated register."""
            _LOGGER.debug('writing byte data @ 0x%02x:0x%02x: 0x%02x', address,
                          register, value)
            return self._smbus.write_byte_data(address, register, value)

        def write_word_data(self, address, register, value):
            """Write a single 2-byte word to a designated register."""
            _LOGGER.debug('writing word data @ 0x%02x:0x%02x: 0x%04x', address,
                          register, value)
            return self._smbus.write_word_data(address, register, value)

        def write_block_data(self, address, register, data):
            """Write a block of byte data to a given register."""
            _LOGGER.debug('writing block data @ 0x%02x:0x%02x: %r', address,
                          register, LazyHexRepr(data))
            return self._smbus.write_block_data(address, register, data)

        def close(self):
            """Close the I²C connection."""
            if self._smbus:
                self._smbus.close()
                self._smbus = None

        def load_eeprom(self, address):
            """Return EEPROM name and data in `address`, or None if N/A."""

            # uses kernel facilities to avoid directly reading from the EEPROM
            # or managing its pages, also avoiding the need for unsafe=smbus

            dev = f'{self._number}-{address:04x}'
            try:
                name = self._i2c_dev.joinpath(dev, 'name').read_text().strip()
                eeprom = self._i2c_dev.joinpath(dev, 'eeprom').read_bytes()
                return LinuxEeprom(name, eeprom)
            except Exception as err:
                return None

        @property
        def name(self):
            return self._i2c_dev.name

        @property
        def description(self):
            return self._try_sysfs_read('name')

        @property
        def parent_vendor(self):
            return self._try_sysfs_read_hex('device/vendor')

        @property
        def parent_device(self):
            return self._try_sysfs_read_hex('device/device')

        @property
        def parent_subsystem_vendor(self):
            return self._try_sysfs_read_hex('device/subsystem_vendor')

        @property
        def parent_subsystem_device(self):
            return self._try_sysfs_read_hex('device/subsystem_device')

        @property
        def parent_driver(self):
            try:
                return Path(
                    os.readlink(self._i2c_dev.joinpath('device/driver'))).name
            except FileNotFoundError:
                return None

        def __str__(self):
            if self.description:
                return f'{self.name}: {self.description}'
            return self.name

        def __repr__(self):
            def hexid(maybe):
                if maybe is not None:
                    return f'{maybe:#06x}'
                return 'None'

            return f'{self.__class__.__name__}: name: {self.name!r}, ' \
                   f'description: {self.description!r}, ' \
                   f'parent_vendor: {hexid(self.parent_vendor)}, ' \
                   f'parent_device: {hexid(self.parent_device)}, ' \
                   f'parent_subsystem_vendor: {hexid(self.parent_subsystem_vendor)}, ' \
                   f'parent_subsystem_device: {hexid(self.parent_subsystem_device)}, ' \
                   f'parent_driver: {self.parent_driver!r}'

        def _try_sysfs_read(self, *sub, default=None):
            try:
                return self._i2c_dev.joinpath(*sub).read_text().rstrip()
            except FileNotFoundError:
                return default

        def _try_sysfs_read_hex(self, *sub, default=None):
            try:
                return int(self._i2c_dev.joinpath(*sub).read_text(), base=16)
            except FileNotFoundError:
                return default
Exemplo n.º 23
0
def main():
  # Read arguments
  parser = argparse.ArgumentParser(description='Change SuperMicro X8 Fan Control.')
  parser.add_argument('-m', '--mode', type=str, choices=['smart', 'cruise'], help='Set the fan mode: smart or cruise. smart: to use Smart Fan mode. cruise: to use Thermal Cruise mode.')
  parser.add_argument('-p', '--pwm', type=str, help='Set Fan Duty (in percentage).')
  parser.add_argument('-t', '--temp', type=str, help='Set Temperature (in Celsius) associated to pwm.')
  parser.add_argument('-H', '--hystersis', type=int, help='Set Hystersis value in degree (0-15)')
  args = parser.parse_args()

  # Open SMBus
  try:
    bus = SMBus(0)
  except:
    print("Failed to open i2c bus (/dev/i2d-0). Make sure i2c-dev module is loaded.")
    return
  #Check if we have the right device.
  try:
    vendor = w83795_read(bus, 0xfd)
    chipid = w83795_read(bus, 0xfe)
    #debug("vendor %s, chipid %s" % (vendor, chipid))
    if vendor != NUVOTON_VENDOR_ID or chipid != CHIP_ID:
      print("unexpected vendor %s, chipid %s" % (vendor, chipid))
      return

    # Check if Smarts Fan Control is enabled
    if args.mode == 'smart':
        # Check arguments
        if not args.pwm or not args.temp:
          print('pwm and temp are required')
          return
        pwm = args.pwm.split(',')
        temp = args.temp.split(',')
        if len(pwm) != len(temp):
          print("pwm and temp must have the same number of values")
          return

        # Change Smart Fan Control value
        for i in range(0,7):
          p = pwm[i] if i < len(pwm) else pwm[-1]
          tt = temp[i] if i < len(temp) else temp[-1]
          print("Set Smart Fan Control %s%% - %sC" % (p, tt))
          for t in TEMPS:
            w83795_write(bus, W83795_REG_SFIV_DCPWM(t)[i], from_perc(p))
            w83795_write(bus, W83795_REG_SFIV_TEMP(t)[i], from_degree(tt))

        # Change Minimum PWM
        for f in FANS:
          w83795_write(bus, W83795_REG_FONV(f), from_perc(pwm[0]))
        # Change critical Temp
        for t in TEMPS:
          w83795_write(bus, W83795_REG_CTFS(t), from_degree(temp[-1]))

        # Set Smart Fan Control Mode T6FC - T1FC
        w83795_write(bus, W83795_REG_FCMS1, 0x0)
        w83795_write(bus, W83795_REG_FCMS2, 0x3f)

    elif args.mode == 'cruise':
        
        # Check arguments
        if not args.temp:
          print('temp is required')
          return
        temp = int(args.temp)

        print("Set Thermal Cruise %sC" % (temp,))
        for t in TEMPS:
          w83795_write(bus, W83795_TTTI(t), from_degree(temp))

        # Change critical Temp
        for t in TEMPS:
          w83795_write(bus, W83795_REG_CTFS(t), from_degree(80))

        # Set Thermal Cruise Mode.
        w83795_write(bus, W83795_REG_FCMS1, 0x0)
        w83795_write(bus, W83795_REG_FCMS2, 0x0)

    # Set hystersis
    if args.hystersis:
      ht = max(min(args.hystersis,15),0)
      print("Set hystersis %sC" % ht)
      # Change Smart Fan Control value
      for t in range(0,6):
        w83795_write(bus, W83795_REG_HT(t), ht)

    if args.mode or args.pwm or args.temp or args.hystersis:
      return

    # Check if Smarts Fan Control is enabled
    fcms1 = w83795_read(bus, W83795_REG_FCMS1)
    fcms2 = w83795_read(bus, W83795_REG_FCMS2) & 0xff

    # Default to show all data.
    for t in TEMPS:
      print("Temp%s to Fan mapping Relationships (T%sFMR)" % (t+1, t+1))
      tfmr = w83795_read(bus, W83795_REG_TFMR(t))
      fans= [i+1 for i in FANS if tfmr & (0x1<<i)]
      print(' '.join(['Fan%s' % i for i in fans]))

      print("Smart Fan Control Table (SFIV)")
      temp = w83795_read(bus, W83795_REG_SFIV_TEMP(t))
      print(''.join([("%sC" % to_degree(v)).rjust(6) for v in temp]))

      dcpwm = w83795_read(bus, W83795_REG_SFIV_DCPWM(t))
      print(''.join([("%s%%" % to_perc(v)).rjust(6) for v in dcpwm]))

      ttti = w83795_read(bus, W83795_TTTI(t))
      print("Thermal Cruise (TTTI): %sC" % (ttti,))

      ctfs = w83795_read(bus, W83795_REG_CTFS(t))
      print("Critical Temperature (T%sCTFS): %sC" % (t, to_degree(ctfs)))

      ht = w83795_read(bus, W83795_REG_HT(t)) & 0b1111
      print("Hysteresis (HT%s): %sC" % (t, ht))

      tmp = w83795_read(bus, W83795_REG_TEMP_READ[t])
      print("Current Temperature (TEMP%s): %sC" % (t, to_degree(tmp),))

      print('---')

    for f in FANS:
      fonv = w83795_read(bus, W83795_REG_FONV(f))
      print("Fan%s Output Nonstop Value (F%sONV): %s%%" % (f+1, f+1, to_perc(fonv)))

    #for f in range(0,6):
    #  w83795_write(bus, W83795_REG_FONV(f), 50)
    #w83795_write(bus, W83795_REG_SFIV_DCPWM(0)[0], 50)
    #w83795_write(bus, W83795_REG_SFIV_TEMP(0)[0], 85)
    #w83795_write(bus, W83795_REG_SFIV_TEMP(1)[0], 85)

  finally:
    bus.close()
Exemplo n.º 24
0
 def zero_angle(self):
     bus = SMBus(self.busnum)
     self.angle_zero = bus.read_i2c_block_data(self.address, AS5048B_registers["ANGLMSB_REG"], 8)
     bus.close()
Exemplo n.º 25
0
class DeviceConnection(object):
    def __init__(self,
                 mode='uart_usb',
                 address=I2C_ADDRESS,
                 port=UART_PORT,
                 bus=I2C_BUS):
        """Initialize UART or I2C connection to slave microcontroller"""

        self._mode = mode
        self.address = address
        self.port = port

        if mode == 'uart_usb':
            self._con = serial.Serial(
                port=self.port,
                baudrate=UART_BAUDRATE,
                bytesize=serial.EIGHTBITS,
                stopbits=serial.STOPBITS_ONE,
                parity=serial.PARITY_NONE,
                rtscts=False,
                dsrdtr=False,
                timeout=UART_TIMEOUT_MS / 1000,
                write_timeout=5,
            )
        else:
            self._con = SMBus(bus)
            time.sleep(1)

    def disconnect(self):
        """Disconnect UART or I2C connection"""

        self._con.close()

    def get_register(self, register_address, format_bytes=False):
        """Get single register from slave microcontroller"""

        if format_bytes:
            return self.get_registers(register_address,
                                      register_len=1,
                                      format_bytes=format_bytes)
        else:
            return self.get_registers(register_address,
                                      register_len=1,
                                      format_bytes=format_bytes)[0]

    def get_registers(self,
                      register_address,
                      register_len=1,
                      format_bytes=False):
        """Get multiple registers from slave microcontroller"""

        if COMM_DEBUG:
            print("request register '%02x' len '%i'" %
                  (register_address, register_len * 2))

        if self._mode == 'uart_usb':

            self._con.write(b'R%02x%02x\n' %
                            (register_address, register_len * 2))
            response = self._con.read_until(
                terminator=serial.LF).decode('ascii').strip()

            if COMM_DEBUG:
                print("raw response '%s'" % response)

            if not response.startswith('ACK'):
                raise Exception("response error")

            response = response.split('ACK')[1]

            registers = []
            if not format_bytes:
                registers = [
                    int(response[i:i + 4], 16)
                    for i in range(0, len(response), 4)
                ]
            else:
                registers = [
                    int(response[i:i + 2], 16)
                    for i in range(0, len(response), 2)
                ]

            if COMM_DEBUG:
                print("decoded response '%s'" % registers)

            return registers

        else:
            response = self._con.read_i2c_block_data(self.address,
                                                     register_address,
                                                     register_len * 2)

            if COMM_DEBUG:
                print("raw response '%s'" % response)

            registers = []
            for i in range(0, register_len * 2, 2):
                registers.append((response[i] << 8) + response[i + 1])

            if COMM_DEBUG:
                print("decoded response '%s'" % registers)

            return registers

    def set_register(self, register_address, register_value):
        """Set single register on slave microcontroller"""

        return self.set_registers(register_address, [register_value])

    def set_registers(self,
                      register_address,
                      register_values,
                      format_bytes=False):
        """Set multiple registers on slave microcontroller"""

        if self._mode == 'uart_usb':

            out_str = ""
            if format_bytes:
                for register_value in register_values:
                    out_str += str("%02x" % register_value)
            else:
                for register_value in register_values:
                    out_str += str("%04x" % register_value)

            if COMM_DEBUG:
                print("set registers raw '%02x - %s'" %
                      (register_address, out_str))

            self._con.write(b'W%02x%s\n' %
                            (register_address, out_str.encode('ascii')))
            response = self._con.read_until(
                terminator=serial.LF).decode('ascii').strip()

            if COMM_DEBUG:
                print("raw response '%s'" % response)

            if not response.startswith('ACK'):
                raise Exception("response error")

            return response

        else:
            out_bytes = []
            if format_bytes:
                out_bytes = register_values
            else:
                for register_value in register_values:
                    out_bytes.extend([(register_value & 0xFF00) >> 8,
                                      (register_value & 0x00FF)])

            if COMM_DEBUG:
                print("set registers raw '%02x - %s'" %
                      (register_address, out_bytes))

            self._con.write_i2c_block_data(self.address, register_address,
                                           out_bytes)
Exemplo n.º 26
0
print "PLL Select: (0: RF or 1: VCO)"
vco = raw_input()

user.vco = bool(int(vco))

print bcolors.WARNING + "Loading PLL" + bcolors.ENDC
pll = si5338POST(0x70, user.vco, bus, VCOREGS, PINS["INTERRUPT"], GPIO)
time.sleep(0.5)
if pll.check():
    print bcolors.FAIL + "Exiting..." + bcolors.ENDC
    exit()
else:
    print bcolors.OKGREEN + "PLL Ready" + bcolors.ENDC


bus.close()

print "Enable Test Signal: (0: Disable or 1: Enable)"
testSignal = raw_input()
print "Select SCROD: (A or B)"
scrod = raw_input()
print "Input bunchMarkerA: (0 - 5280)"
bma = raw_input()
print "Input bunchMarkerB: (0 - 5280)"
bmb = raw_input()

print bin(int(bma))
print bin(int(bmb))

user.testSignal = bool(int(testSignal))
user.scrod = scrod
Exemplo n.º 27
0
class Monster():
    """Monster class.  Should only be used with a context manager!

    All GPIOs are BCM GPIO numbers.
    """

    I2C_BUS_NUM = 0
    SERVO_I2C_ADDR = 0xa

    SERVO_CMD_OPEN = 1
    SERVO_CMD_CLOSE = 2
    SERVO_CMD_TWITCH = 3

    DISTANCE_UPDATE_SECONDS = .2

    def __init__(self, solenoid_gpio_num=17,
                 echo_trigger_gpio_num=24, echo_gpio_num=25):
        self._gpios = {
            'solenoid': solenoid_gpio_num,
            'echo_trigger': echo_trigger_gpio_num,
            'echo': echo_gpio_num,
        }
        self._rangefinder_settled = False
        self._distance_lock = threading.Lock()
        self._distance = 999999999

    def __enter__(self):
        PWM.set_loglevel(PWM.LOG_LEVEL_ERRORS)
        GPIO.setup(self._gpios['solenoid'], GPIO.OUT)
        GPIO.setup(self._gpios['echo_trigger'], GPIO.OUT)
        GPIO.setup(self._gpios['echo'], GPIO.IN)
        self._i2c_bus = SMBus()
        self._i2c_bus.open(Monster.I2C_BUS_NUM)
        self.close_door()
        return self

    def __exit__(self, exc_type, exc_value, traceback):
        self._cm_active = False
        self._i2c_bus.close()
        GPIO.cleanup()

    def activate_solenoid(self):
        GPIO.output(self._gpios['solenoid'], True)

    def deactivate_solenoid(self):
        GPIO.output(self._gpios['solenoid'], False)

    def fire_ball(self, active_time=.3):
        """Activate the solenoid for `active_time' seconds."""
        self.activate_solenoid()
        time.sleep(active_time)
        self.deactivate_solenoid()

    def i2c_write(self, cmd, max_iters):
        for i in range(max_iters):
            try:
                self._i2c_bus.write_byte(Monster.SERVO_I2C_ADDR, cmd)
                return
            except IOError:
                time.sleep(.5)
                pass
        print "I2C Contention! Couldn't send command:", cmd

    def close_door(self):
        self.i2c_write(Monster.SERVO_CMD_CLOSE, 10)

    def open_door(self):
        self.i2c_write(Monster.SERVO_CMD_OPEN, 10)

    def twitch_door(self):
        self.i2c_write(Monster.SERVO_CMD_TWITCH, 10)

    def toggle_door(self, time_open=.8):
        self.open_door()
        time.sleep(time_open)
        self.close_door()

    def ball_and_door(self):
        self.twitch_door()
        time.sleep(1)
        self.fire_ball()
        time.sleep(1)
        self.fire_ball()

    # based on http://www.modmypi.com/blog/hc-sr04-ultrasonic-range-sensor-on-the-raspberry-pi
    def measure_distance(self):
        """Returns the distance (in meters) to the object being looked at.

        Probably should only happen in a thread due to all the sleeping
        """
        if not self._rangefinder_settled:
            # let the sensor settle
            GPIO.output(self._gpios['echo_trigger'], False)
            time.sleep(2)
            self._rangefinder_settled = True

        # 10 us pulse
        GPIO.output(self._gpios['echo_trigger'], True)
        time.sleep(0.00001)
        GPIO.output(self._gpios['echo_trigger'], False)
        # interrupt might be better?
        pulse_start = time.time()
        cnt = 0
        while not GPIO.input(self._gpios['echo']):
            pulse_start = time.time() # maybe pass would be better? might actually more cpu though...
            cnt += 1
            if cnt > 20000:
                return 999999999
        # we got a pulse, measure it's width by polling until it goes low
        # again.
        cnt = 0
        pulse_end = time.time()
        while GPIO.input(self._gpios['echo']):
            pulse_end = time.time()
            cnt += 1
            if cnt > 20000:
                return 999999999

        pulse_duration = pulse_end - pulse_start
        sound_mps = 343.0         # speed of sound: 343 m/s
        distance = sound_mps * pulse_duration
        # and the pulse width is actually the time it takes to get to the
        # object *and back*, so we need to divide by two to get just the
        # distance:
        distance /= 2.0
        # Because the datasheet says:
        #
        #   we suggest to use over 60ms measurement cycle, in order to
        #   prevent trigger signal to the echo signal.
        #
        # We'll use 80ms to be safe
        time.sleep(.08)
        return distance

    def print_distance(self):
        print 'Distance: ', self.measure_distance(), ' meters'

    def monitor_distance(self, iters=10):
        iters = int(iters)      # we pass strings from the command line below...
        for i in xrange(iters):
            self.print_distance()
            sys.stdin.flush()

    def set_distance(self, distance):
        with self._distance_lock:
            self._distance = distance

    def get_distance(self):
        with self._distance_lock:
            return self._distance

    def watch_distance(self):
        while self._keep_watching:
            distance = self.measure_distance()
            self.set_distance(distance)
            time.sleep(Monster.DISTANCE_UPDATE_SECONDS)
        print 'done watching distance'

    def monster_loop(self, trigger_threshold_meters=1.0,
                     come_closer_meters=2.0):
        loop_sound('background.mp3')
        self._keep_watching = True
        dist_thread = threading.Thread(target=self.watch_distance)
        dist_thread.start()
        try:
            last_come_closer = 0
            distances = [0, 0, 0] # simple moving average...
            while True:
                distances.insert(0, self.get_distance())
                distances.pop()
                distance = sum(distances) / 3.0
                print 'distances, distance:', distances, distance
                if distance < come_closer_meters and \
                   distance > trigger_threshold_meters and \
                   time.time() - last_come_closer > 12:
                    print 'come closer...'
                    play_sound('come-closer.mp3')
                    last_come_closer = time.time()
                elif distance < trigger_threshold_meters:
                    play_sound('vocal-leave-now-happy-halloween.mp3')
                    time.sleep(1)
                    print 'FIRE!'
                    self.ball_and_door()
                    time.sleep(10)
                time.sleep(.3)
        except KeyboardInterrupt:
            print "Interrupt received. Exiting loop."
        except SystemExit:
            print "Exiting loop."
        self._keep_watching = False
        print 'waiting for threads to exit...'
        dist_thread.join()
        print "ok, we're outta here"

    def sayhi(self, sleep_s=0.5, reps=5):
        for i in xrange(reps):
            self.open_door()
            time.sleep(sleep_s)
            self.close_door()
            time.sleep(sleep_s)
Exemplo n.º 28
0
class PM2:
    '''Handle display'''

    # Translation value from String to Display
    digits = {
        '': 0,
        '1': 96,
        '2': 167,
        '3': 227,
        '4': 106,
        '5': 203,
        '6': 207,
        '7': 224,
        '8': 239,
        '9': 235,
        '0': 237
    }

    buffer = [0 for i in xrange(20)]  # Buffer for device RAM

    def __init__(self,
                 defaultBus=PI_DEFAULT_BUS,
                 defaultAddr=PM2_DEFAULT_ADDRESS):
        self.bus = SMBus(defaultBus)
        self.busNum = defaultBus
        self.defaultAddr = defaultAddr
        self.bus.close()
        self.bus.open(self.busNum)
        self.bus.write_byte(self.defaultAddr, PM2_MODE_SET)
        self.clear()
        self.set_mode('normal')
        self.top_right('00')
        self.middle('000')
        self.top_left('0000')
        self.bottom_left('0000')

    def write_bit(self, addr, position, value):
        '''write one bit to buffer
           @addr : buffer address -> int
           @position : bit position -> int
           @value : bit value -> boolean
        '''
        mask = ~(1 << position)
        value = value << position
        self.buffer[addr] = (self.buffer[addr] & mask) | value

    def write_digit(self, addr, value):
        '''write single/multiple digit(s) to buffer
           @addr : buffer address -> int
           @value : single/mutiple digit -> string
        '''
        i = addr
        for x in reversed(value):
            intVal = self.digits[x]
            mask = 1 << 4  # Preserve DP bit
            self.buffer[i] = (self.buffer[i] & mask) | intVal
            i += 1

    def set_mode(self, mode):
        '''Toggle between different possible mode :
            -normal
            -cal/hr
            -watts
            -heart rate
        '''
        if (mode == 'normal'):
            """Time, /500m, Distance"""
            self.set_segment_colon_top_left(False)
            self.set_segment_colon_top_right(True)
            self.set_segment_dp_top(False)
            self.set_segment_time_top(True)
            self.set_segment_meters_top(False)
            self.set_segment_spm_top(True)
            self.set_segment_int_top(False)
            self.set_segment_1_middle(False)
            self.set_segment_colon_middle(True)
            self.set_segment_500m_middle(True)
            self.set_segment_calhr_middle(False)
            self.set_segment_watts_middle(False)
            self.set_segment_rest_time_middle(False)
            self.set_segment_int_middle(False)
            self.set_segment_colon_bottom_left(False)
            self.set_segment_colon_bottom_right(False)
            self.set_segment_dp_bottom(False)
            self.set_segment_ave_bottom(False)
            self.set_segment_500m_bottom(False)
            self.set_segment_watts_bottom(False)
            self.set_segment_split_bottom(False)
            self.set_segment_cal_bottom(False)
            self.set_segment_proj_bottom(False)
            self.set_segment_time_bottom(False)
            self.set_segment_meters_bottom(True)
            self.set_segment_dragfactor_bottom(False)
        elif (mode == 'watts'):
            """Time, Watts, Distance"""
            self.set_segment_colon_top_left(False)
            self.set_segment_colon_top_right(True)
            self.set_segment_dp_top(False)
            self.set_segment_time_top(True)
            self.set_segment_meters_top(False)
            self.set_segment_spm_top(True)
            self.set_segment_int_top(False)
            self.set_segment_1_middle(False)
            self.set_segment_colon_middle(False)
            self.set_segment_500m_middle(False)
            self.set_segment_calhr_middle(False)
            self.set_segment_watts_middle(True)
            self.set_segment_rest_time_middle(False)
            self.set_segment_int_middle(False)
            self.set_segment_colon_bottom_left(False)
            self.set_segment_colon_bottom_right(False)
            self.set_segment_dp_bottom(False)
            self.set_segment_ave_bottom(True)
            self.set_segment_500m_bottom(False)
            self.set_segment_watts_bottom(True)
            self.set_segment_split_bottom(False)
            self.set_segment_cal_bottom(False)
            self.set_segment_proj_bottom(False)
            self.set_segment_time_bottom(False)
            self.set_segment_meters_bottom(False)
            self.set_segment_dragfactor_bottom(False)
        elif (mode == 'heart rate'):
            self.set_segment_colon_middle(isHeartRate)

    def set_segment_colon_top_left(self, enabled):
        '''Set first : segment at the top from the left'''
        self.write_bit(13, 5, enabled)

    def set_segment_colon_top_right(self, enabled):
        '''Set 2nd : segment at the top from the left'''
        self.write_bit(18, 1, enabled)

    def set_segment_int_top(self, enabled):
        '''Set INT segment in the top right corner'''
        self.write_bit(19, 0, enabled)

    def set_segment_spm_top(self, enabled):
        '''Set SPM segment in the top right corner'''
        self.write_bit(14, 4, enabled)

    def set_segment_meters_top(self, enabled):
        '''Set METERS segment in at the top'''
        self.write_bit(19, 4, enabled)

    def set_segment_time_top(self, enabled):
        '''Set TIME segment in at the top'''
        self.write_bit(0, 4, enabled)

    def set_segment_dp_top(self, enabled):
        '''Set DP segment (decimal point) in at the top'''
        self.write_bit(1, 4, enabled)

    def set_segment_calhr_middle(self, enabled):
        '''Set CAL/HR segment in the middle'''
        self.write_bit(19, 7, enabled)

    def set_segment_500m_middle(self, enabled):
        '''Set /500M segment in the middle'''
        self.write_bit(19, 5, enabled)

    def set_segment_int_middle(self, enabled):
        '''Set INT segment in the middle'''
        self.write_bit(19, 2, enabled)

    def set_segment_watts_middle(self, enabled):
        '''Set WATTS segment in the middle'''
        self.write_bit(19, 6, enabled)

    def set_segment_colon_middle(self, enabled):
        '''Set : segment in the middle'''
        self.write_bit(19, 1, enabled)

    def set_segment_1_middle(self, enabled):
        '''Set '1' segment in the middle'''
        self.write_bit(13, 6, enabled)

    def set_segment_rest_time_middle(self, enabled):
        '''Set REST TIME segment in the middle'''
        self.write_bit(10, 4, enabled)

    def set_segment_ave_bottom(self, enabled):
        '''Set AVE segment in the bottom'''
        self.write_bit(13, 7, enabled)

    def set_segment_500m_bottom(self, enabled):
        '''Set /500M segment in the bottom'''
        self.write_bit(13, 4, enabled)

    def set_segment_watts_bottom(self, enabled):
        '''Set WATTS segment in the bottom'''
        self.write_bit(12, 4, enabled)

    def set_segment_split_bottom(self, enabled):
        '''Set SPLIT segment in the bottom'''
        self.write_bit(11, 4, enabled)

    def set_segment_cal_bottom(self, enabled):
        '''Set CAL segment in the bottom'''
        self.write_bit(9, 4, enabled)

    def set_segment_proj_bottom(self, enabled):
        '''Set PROJ segment in the bottom'''
        self.write_bit(8, 4, enabled)

    def set_segment_dp_bottom(self, enabled):
        '''Set DP segment (decimal point) in the bottom'''
        self.write_bit(6, 4, enabled)

    def set_segment_time_bottom(self, enabled):
        '''Set TIME segment in the bottom'''
        self.write_bit(7, 4, enabled)

    def set_segment_meters_bottom(self, enabled):
        '''Set METERS segment in the bottom'''
        self.write_bit(13, 0, enabled)

    def set_segment_dragfactor_bottom(self, enabled):
        '''Set DRAG FACTOR segment in the bottom'''
        self.write_bit(18, 0, enabled)

    def set_segment_heartrate_bottom(self, enabled):
        '''Set HEART RATE segment in the bottom'''
        self.write_bit(17, 4, enabled)

    def set_segment_colon_bottom_left(self, enabled):
        '''Set 1st : segment at the bottom from the left'''
        self.write_bit(18, 5, enabled)

    def set_segment_colon_bottom_right(self, enabled):
        '''Set 2nd : segment at the bottom from the left'''
        self.write_bit(13, 1, enabled)

    def top_right(self, value):
        '''Display value to the top rigth corner of the screen'''
        startAddr = 14
        if (int(value) <= 99):
            self.write_digit(startAddr, value)
            self.refresh()
            return True
        else:
            return False

    def middle(self, value):
        '''Display value to the middle of the screen'''
        startAddr = 10
        if (int(value) <= 999):
            self.write_digit(startAddr, value)
            self.refresh()
            return True
        elif (int(value) > 999 & int(value) <= 1999):
            self.set_segment_middle_1(True)
            self.write_digit(startAddr, value)
            self.refresh()
        else:
            return False

    def bottom_right(self, value):
        '''Display value to the bottom right corner of the screen'''
        startAddr = 17
        if (int(value) <= 399):
            self.write_digit(startAddr, value)
            self.refrsh()
            return True
        else:
            return False

    def top_left(self, value):
        '''Display value to the top left corner of the screen'''
        startAddr = 0
        if (int(value) <= 99999):
            self.write_digit(startAddr, value)
            self.refresh()
            return True
        else:
            return False

    def bottom_left(self, value):
        '''Display value to the bottom left corner of the screen'''
        startAddr = 5
        if (int(value) <= 99999):
            self.write_digit(startAddr, value)
            self.refresh()
            return True
        else:
            return False

    def refresh(self):
        '''Push buffer content to device RAM at once for display'''
        # Do nothing special execpt avoiding an I2C communication error
        self.bus.write_byte(self.defaultAddr, 0b01100000)
        self.bus.write_i2c_block_data(self.defaultAddr, 0, self.buffer)
        # Do nothing special execpt avoiding an I2C communication error
        self.bus.write_byte(self.defaultAddr, 0b01100000)

    def clear(self):
        '''Clear screen'''
        self.buffer = [0 for x in xrange(20)]
        self.refresh()

    def display_all(self):
        '''Display all possible character on the screen'''
        self.buffer = [255 for x in xrange(20)]
        self.refresh()

    def loop(self):
        self.bus.write_byte_data(self.defaultAddr, 0, 255)
        for x in range(2, 40, 2):
            self.bus.write_byte_data(self.defaultAddr, x - 2, 0)
            self.bus.write_byte_data(self.defaultAddr, x, 255)
            sleep(1)
            if (x > 36):
                self.bus.write_byte(self.defaultAddr, 0b01100000)
Exemplo n.º 29
0
 def _readBytePMBus(self, cmd, pecByte=True):
     bus = SMBus(self.busID)
     bus.pec = pecByte
     data = bus.read_byte_data(self.address, cmd)
     bus.close()
     return data
Exemplo n.º 30
0
def sigint_handle(signal_recieved, frame):
    running = False


signal(SIGINT, sigint_handle)

# Create I2C bus
bus = SMBus(1)

INIT_SIGNAL = 0x01  #init signal fori2c
while (running):

    # NOTE: May need to move [D040] <= 0x06 inside the loop here, but I don't think you do

    sleep(SENSOR_MEASUREMENT_WAIT_TIME)

    # Tell the sensor we want to read the flow value [D051/D052] => Read Compensated Flow value
    answer = bus.read_word_data(PRESSURE_SENSOR_ADDRESS, INIT_SIGNAL)

    #bit  shift to get the full value
    answer = float((((answer & 0x00FF) << 8) + ((answer & 0xFF00) >> 8)))

    pressure = (answer - SENSOR_COUNT_MIN) * (
        SENSOR_PRESSURE_MAX - SENSOR_PRESSURE_MIN) / (
            SENSOR_COUNT_MAX - SENSOR_COUNT_MIN) + SENSOR_PRESSURE_MIN
    # Output for the user
    print(f"Sensor Reading {pressure:.3f} psi" + " " * 20, end='\r')

print("Exiting program...")
bus.close()
Exemplo n.º 31
0
 def _writeBytePMBus(self, cmd, byte, pecByte=True):
     bus = SMBus(self.busID)
     bus.pec = pecByte
     bus.write_byte_data(self.address, cmd, byte)
     bus.close()
Exemplo n.º 32
0
 def _writeWordPMBus(self, cmd, word, pecByte=True):
     bus = SMBus(self.busID)
     bus.pec = pecByte
     bus.write_word_data(self.address, cmd, word)
     bus.close()
Exemplo n.º 33
0
 def getCurrent(self):
     bus = SMBus(1)
     self.current = self._decodePMBus(self._readWordPMBus(0x8C))
     bus.close()
     return self.current
Exemplo n.º 34
0
class BerryIMUClient(object):
    """Client for using the BerryIMU from Python.

    Settings can be applied by sending in a dict at initialisation.
    The following keys and corresponding valid values govern the settings, where
    values in <> denotes default values.

    Accelerometer:

    * 'data_rate' [0, 3.125, 6.25, 12.5, 25, 50, 100, <200>, 400, 800, 1600]
    * 'continuous_update': [True, <False>],
    * 'enabled_x': [<True>, False],
    * 'enabled_y': [<True>, False],
    * 'enabled_z': [<True>, False],
    * 'anti_alias': [<773>, 194, 362, 50],
    * 'full_scale': [2, 4, 6, <8>, 16],
    * 'self_test': [<0>, 1, -1, 'X']

    Gyroscope:

    * 'data_rate' [95, <190>, 380, 760]
    * 'bandwidth_level': [<0>, 1, 2, 3],
    * 'powerdown_mode': [True, <False>],
    * 'enabled_x': [<True>, False],
    * 'enabled_y': [<True>, False],
    * 'enabled_z': [<True>, False],
    * 'continuous_update': [True, <False>],
    * 'little_endian': [True, <False>],
    * 'full_scale': [245, <500>, 2000],
    * 'self_test': [<0>, 1, -1]

    Magnetometer:

    * 'data_rate' [3.125, 6.25, 12.5, 25, <50>, 100]
    * 'full_scale': [2, 4, 8, <12>],
    * 'sensor_mode': [<0>, 1, -1]
    * 'lowpower_mode': [True, <False>],
    * 'high_resolution': [<True>, False],
    * 'enabled_temp': [<True>, False]

    Read more about these settings in the
    `LSM9DS0 data sheet <http://ozzmaker.com/wp-content/uploads/2014/12/LSM9DS0.pdf>`_.

    For the barometric pressure sensor BMP180, docstring will be written.
    `BMP180 data sheet <http://ozzmaker.com/wp-content/uploads/2015/01/BMP180-DS000-09.pdf>`_

    """

    def __init__(self, bus=1, settings=None):
        """Constructor for BerryIMUClient"""

        self._bus = None
        self._calibration_object = BerryIMUCalibration()

        # Init time settings.
        self._bus_no = bus
        self._acc_setup = self._create_accelerometer_settings_dict(
            settings.get('accelerometer', {}) if settings is not None else {})
        self._gyro_setup = self._create_gyroscope_settings_dict(
            settings.get('gyroscope', {}) if settings is not None else {})
        self._mag_setup = self._create_magnetometer_settings_dict(
            settings.get('magnetometer', {}) if settings is not None else {})

        # BMP180 calibration values.
        self.__ac1 = None
        self.__ac2 = None
        self.__ac3 = None
        self.__ac4 = None
        self.__ac5 = None
        self.__ac6 = None
        self.__b1 = None
        self.__b2 = None
        self.__mb = None
        self.__mc = None
        self.__md = None

    @property
    def bus(self):
        if self._bus is not None:
            return self._bus
        else:
            self.open()
            return self.bus

    @property
    def calibration_object(self):
        return self._calibration_object

    @calibration_object.setter
    def calibration_object(self, new_calibration):
        # TODO: Check if calibration and current client share vital settings such as full scales.
        self._calibration_object = new_calibration

    def open(self):
        try:
            self._bus = SMBus(self._bus_no)
        except IOError as e:
            if str(e) == '2':
                raise PyBerryIMUError("/dev/i2c-{0} not found. (IOError 2)".format(self._bus_no))
            elif str(e) == '5':
                raise PyBerryIMUError("I2C Input/Output error. (IOError 5)".format(self._bus_no))
            elif str(e) == '13':
                raise PyBerryIMUError("Permission to read and/or write to "
                                      "/dev/i2c-{0} missing. (IOError 13)".format(self._bus_no))
            else:
                raise PyBerryIMUError('Unhandled IOError: {0}'.format(e))
        except Exception as e:
            raise PyBerryIMUError('Unhandled {0}: {1}'.format(type(e), e))
        else:
            self._init_accelerometer()
            self._init_gyroscope()
            self._init_magnetometer()
            self._init_barometric_pressure_sensor()

    def close(self):
        if self._bus is not None:
            try:
                self._bus.close()
            except Exception as e:
                # TODO: Test what errors can occur and handle these better.
                print("Exception at closing of i2c bus: {0}".format(e))

    def __enter__(self):
        self.open()
        return self

    def __exit__(self, exc_type, exc_val, exc_tb):
        self.close()

    # Initialisation methods

    def _create_accelerometer_settings_dict(self, setup_dict):
        return {
            'data_rate': setup_dict.get('data_rate', 200),
            'continuous_update': setup_dict.get('continuous_update', False),
            'enabled_z': setup_dict.get('enabled_z', True),
            'enabled_y': setup_dict.get('enabled_y', True),
            'enabled_x': setup_dict.get('enabled_x', True),
            'anti_alias': setup_dict.get('anti_alias', 773),
            'full_scale': setup_dict.get('full_scale', 8),
            'self_test': setup_dict.get('self_test', 0)
        }

    def _init_accelerometer(self):
        """Initialize the accelerometer according to the settings document sent in."""
        # TODO: Better init handling!

        reg1_value = (
            LSM9DS0.get_accelerometer_data_rate_bits(self._acc_setup.get('data_rate')) +
            ('0' if self._acc_setup.get('continuous_update') else '1') +
            ('1' if self._acc_setup.get('enabled_z') else '0') +
            ('1' if self._acc_setup.get('enabled_y') else '0') +
            ('1' if self._acc_setup.get('enabled_x') else '0')
        )
        # Write data rate, enabled axes and block data update.
        self._write(LSM9DS0.ACC_ADDRESS, LSM9DS0.CTRL_REG1_XM, int(reg1_value, 2))

        reg2_value = (
            LSM9DS0.get_accelerometer_anti_alias_filter_bits(self._acc_setup.get('anti_alias')) +
            LSM9DS0.get_accelerometer_full_scale_bits(self._acc_setup.get('full_scale')) +
            LSM9DS0.get_accelerometer_self_test_bits(self._acc_setup.get('self_test')) +
            '0'  # SPI Serial Interface Mode selection
        )
        # Write anti-alias filter bandwidth, acceleration full scale and self-test mode.
        self._write(LSM9DS0.ACC_ADDRESS, LSM9DS0.CTRL_REG2_XM, int(reg2_value, 2))

    def _create_gyroscope_settings_dict(self, setup_dict):
        return {
            'data_rate': setup_dict.get('data_rate', 190),
            'bandwidth_level': setup_dict.get('bandwidth_level', 0),
            'powerdown_mode': setup_dict.get('powerdown_mode', False),
            'enabled_z': setup_dict.get('enabled_z', True),
            'enabled_y': setup_dict.get('enabled_y', True),
            'enabled_x': setup_dict.get('enabled_x', True),
            'continuous_update': setup_dict.get('continuous_update', False),
            'little_endian': setup_dict.get('little_endian', False),
            'full_scale': setup_dict.get('full_scale', 500),
            'self_test': setup_dict.get('self_test', 0)
        }

    def _init_gyroscope(self):
        """Initialize the gyroscope according to the settings document sent in."""
        # TODO: Better init handling!

        reg1_value = (
            LSM9DS0.get_gyroscope_data_rate_bits(self._gyro_setup.get('data_rate')) +
            LSM9DS0.get_gyroscope_bandwidth_bits(self._gyro_setup.get('bandwidth_level')) +
            ('0' if self._gyro_setup.get('powerdown_mode') else '1') +
            ('1' if self._gyro_setup.get('enabled_z') else '0') +
            ('1' if self._gyro_setup.get('enabled_y') else '0') +
            ('1' if self._gyro_setup.get('enabled_x') else '0')
        )
        self._write(LSM9DS0.GYR_ADDRESS, LSM9DS0.CTRL_REG1_G, int(reg1_value, 2))

        # TODO: Add setup for high-pass filter, LSM9DS0.CTRL_REG2_G and LSM9DS0.CTRL_REG5_G

        reg4_value = (
            ('0' if self._gyro_setup.get('continuous_update') else '1') +
            ('1' if self._gyro_setup.get('little_endian') else '0') +
            LSM9DS0.get_gyroscope_full_scale_bits(self._gyro_setup.get('full_scale')) +
            '0' +  # Unused bit.
            LSM9DS0.get_gyroscope_self_test_bits(self._gyro_setup.get('self_test')) +
            '0'  # SPI Serial Interface Mode selection
        )
        self._write(LSM9DS0.GYR_ADDRESS, LSM9DS0.CTRL_REG4_G, int(reg4_value, 2))

    def _create_magnetometer_settings_dict(self, setup_dict):
        return {
            'enabled_temp': setup_dict.get('enabled_temp', True),
            'data_rate': setup_dict.get('data_rate', 50),
            'full_scale': setup_dict.get('full_scale', 12),
            'sensor_mode': setup_dict.get('sensor_mode', 0),
            'lowpower_mode': setup_dict.get('lowpower_mode', False),
            'high_resolution': setup_dict.get('high_resolution', True)
        }

    def _init_magnetometer(self):
        """Initialize the magnetometer according to the settings document sent in."""
        reg5_value = (
            ('1' if self._mag_setup.get('enabled_temp') else '0') +
            ('11' if self._mag_setup.get('high_resolution') else '00') +
            LSM9DS0.get_magnetometer_data_rate_bits(self._mag_setup.get('data_rate')) +
            '00'  # Latch interrupts disabled right.
        )
        self._write(LSM9DS0.MAG_ADDRESS, LSM9DS0.CTRL_REG5_XM, int(reg5_value, 2))

        reg6_value = (
            '0' +  # Unused bits
            LSM9DS0.get_magnetometer_full_scale_bits(self._mag_setup.get('full_scale')) +
            '00000'  # Unused bits
        )
        self._write(LSM9DS0.MAG_ADDRESS, LSM9DS0.CTRL_REG6_XM, int(reg6_value, 2))

        reg7_value = (
            '00' +  # Accelerometer high-pass filter disabled.
            '0' +  # Filtered acceleration data selection bypassed.
            '00' +  # Unused bits
            ('1' if self._mag_setup.get('lowpower_mode') else '0') +
            LSM9DS0.get_magnetometer_sensor_mode_bits(self._mag_setup.get('sensor_mode'))
        )
        self._write(LSM9DS0.MAG_ADDRESS, LSM9DS0.CTRL_REG7_XM, int(reg7_value, 2))

    def _init_barometric_pressure_sensor(self):
        """Initialize the Barometric Pressure Sensor."""
        self._set_bmp180_calibration_values()
        # TODO: Better init handling!
        self.__OVERSAMPLING = 3  # 0..3

    def get_settings(self):
        settings = {
            'accelerometer': {
                'reg1': "{0:08b}".format(self.bus.read_byte_data(LSM9DS0.ACC_ADDRESS, LSM9DS0.CTRL_REG1_XM)),
                'reg2': "{0:08b}".format(self.bus.read_byte_data(LSM9DS0.ACC_ADDRESS, LSM9DS0.CTRL_REG2_XM)),
            },
            'gyroscope': {
                'reg1': "{0:08b}".format(self.bus.read_byte_data(LSM9DS0.GYR_ADDRESS, LSM9DS0.CTRL_REG1_G)),
                'reg4': "{0:08b}".format(self.bus.read_byte_data(LSM9DS0.GYR_ADDRESS, LSM9DS0.CTRL_REG4_G)),
            },
            'magnetometer': {
                'reg5': "{0:08b}".format(self.bus.read_byte_data(LSM9DS0.MAG_ADDRESS, LSM9DS0.CTRL_REG5_XM)),
                'reg6': "{0:08b}".format(self.bus.read_byte_data(LSM9DS0.MAG_ADDRESS, LSM9DS0.CTRL_REG6_XM)),
                'reg7': "{0:08b}".format(self.bus.read_byte_data(LSM9DS0.MAG_ADDRESS, LSM9DS0.CTRL_REG7_XM)),
            }
        }
        settings['accelerometer'].update(self._acc_setup)
        settings['gyroscope'].update(self._gyro_setup)
        settings['magnetometer'].update(self._mag_setup)
        return settings

    # BMP180 specific methods.

    def get_bmp180_chip_id_and_version(self):
        """Gets Chip ID and version for the BMP180 sensor.

        :return: Chip ID and Version number
        :rtype: tuple

        """
        return self.bus.read_i2c_block_data(BMP180.ADDRESS, BMP180.CHIP_ID_REG, 2)

    def _set_bmp180_calibration_values(self):
        """Read, parse and store calibration EEPROM data to attributes."""

        bmp180_calibration = self.bus.read_i2c_block_data(BMP180.ADDRESS, BMP180.CALIB_DATA_REG, 22)
        vals = [msb + lsb for msb, lsb in zip(map(lambda x: x << 8, bmp180_calibration[::2]),
                                              bmp180_calibration[1::2])]
        for i in [0, 1, 2, 6, 7, 8, 9, 10]:
            if vals[i] > 2 ** 15 - 1:
                vals[i] -= 2 ** 16

        self.__ac1 = vals[0]
        self.__ac2 = vals[1]
        self.__ac3 = vals[2]
        self.__ac4 = vals[3]
        self.__ac5 = vals[4]
        self.__ac6 = vals[5]
        self.__b1 = vals[6]
        self.__b2 = vals[7]
        self.__mb = vals[8]
        self.__mc = vals[9]
        self.__md = vals[10]

    # Methods for writing to BerryIMU.

    def _write(self, address, register, value):
        self.bus.write_byte_data(address, register, value)
        return -1

    # Methods for reading from BerryIMU.

    def _read(self, address, register_low_bit, register_high_bit):
        value = (self.bus.read_byte_data(address, register_low_bit) |
                 (self.bus.read_byte_data(address, register_high_bit) << 8))

        return value if value < 32768 else value - 65536

    @property
    def timestamp(self):
        """Timestamp right now Epoch time.

        :return: Epoch timestamp
        :rtype: float

        """
        # TODO: Make timezone independent...
        return time.time()

    def read_accelerometer(self):
        """Method for reading values from the accelerometer.

        :return: The X, Y, and Z values of the accelerometer.
        :rtype: tuple

        """
        return self.calibration_object.transform_accelerometer_values(
            (self._read(LSM9DS0.ACC_ADDRESS, LSM9DS0.OUT_X_L_A, LSM9DS0.OUT_X_H_A),
             self._read(LSM9DS0.ACC_ADDRESS, LSM9DS0.OUT_Y_L_A, LSM9DS0.OUT_Y_H_A),
             self._read(LSM9DS0.ACC_ADDRESS, LSM9DS0.OUT_Z_L_A, LSM9DS0.OUT_Z_H_A)))

    def read_gyroscope(self):
        """Method for reading values from the gyroscope.

        :return: The X, Y, and Z values of the gyroscope.
        :rtype: tuple

        """
        return self.calibration_object.transform_gyroscope_values(
            (self._read(LSM9DS0.GYR_ADDRESS, LSM9DS0.OUT_X_L_G, LSM9DS0.OUT_X_H_G),
             self._read(LSM9DS0.GYR_ADDRESS, LSM9DS0.OUT_Y_L_G, LSM9DS0.OUT_Y_H_G),
             self._read(LSM9DS0.GYR_ADDRESS, LSM9DS0.OUT_Z_L_G, LSM9DS0.OUT_Z_H_G)))

    def read_magnetometer(self):
        """Method for reading values from the magnetometer.

        :return: The X, Y, and Z values of the magnetometer.
        :rtype: tuple

        """
        return self.calibration_object.transform_magnetometer_values(
            (self._read(LSM9DS0.MAG_ADDRESS, LSM9DS0.OUT_X_L_M, LSM9DS0.OUT_X_H_M),
             self._read(LSM9DS0.MAG_ADDRESS, LSM9DS0.OUT_Y_L_M, LSM9DS0.OUT_Y_H_M),
             self._read(LSM9DS0.MAG_ADDRESS, LSM9DS0.OUT_Z_L_M, LSM9DS0.OUT_Z_H_M)))

    def read_temperature_LSM9DS0(self):
        """Method for reading temperature values from the LSM9DS0 chip.

        Temperature value is stored as a 12-bit, right justified value, hence the
        bit mask on the high bit.

        :return: Temperature value.
        :rtype: int

        """
        value = (self.bus.read_byte_data(LSM9DS0.MAG_ADDRESS, LSM9DS0.OUT_TEMP_L_XM) | (
            (self.bus.read_byte_data(LSM9DS0.MAG_ADDRESS, LSM9DS0.OUT_TEMP_H_XM) & 0b00001111) << 8))
        value = value if value < 2048 else value - 4096

        # Convert to degrees Celsius according to data sheet specs: 8 LSB/deg C
        return value / 8

    def read_temperature(self):
        """Method for reading temperature values from the barometric pressure sensor.

        Reference for reading to temperature calculations:
        `BMP180 reference sheet
        <http://ozzmaker.com/wp-content/uploads/2015/01/BMP180-DS000-09.pdf>`_

        :return: The temperature value.
        :rtype: int

        """
        self._write(BMP180.ADDRESS, BMP180.WRITE_REG, 0x2E)
        time.sleep(0.005)
        msb, lsb = self.bus.read_i2c_block_data(BMP180.ADDRESS, BMP180.READ_REG, 2)
        ut = (msb << 8) + lsb

        x1 = ((ut - self.__ac6) * self.__ac5) >> 15
        x2 = (self.__mc << 11) // (x1 + self.__md)
        b5 = x1 + x2
        t = (b5 + 8) >> 4
        return t / 10.0

    def read_pressure(self):
        """Method for reading pressure value from the barometric pressure sensor.

        Reference for reading to pressure calculations:
        `BMP180 reference sheet
        <http://ozzmaker.com/wp-content/uploads/2015/01/BMP180-DS000-09.pdf>`_


        :return: The pressure value.
        :rtype: int

        """
        self._write(BMP180.ADDRESS, BMP180.WRITE_REG, 0x2E)
        time.sleep(0.005)
        msb, lsb = self.bus.read_i2c_block_data(BMP180.ADDRESS, BMP180.READ_REG, 2)
        ut = (msb << 8) + lsb

        self._write(BMP180.ADDRESS, BMP180.WRITE_REG, 0x34 + (self.__OVERSAMPLING << 6))
        time.sleep(0.04)
        msb, lsb, xsb = self.bus.read_i2c_block_data(BMP180.ADDRESS, BMP180.READ_REG, 3)
        up = ((msb << 16) + (lsb << 8) + xsb) >> (8 - self.__OVERSAMPLING)

        x1 = ((ut - self.__ac6) * self.__ac5) >> 15
        x2 = (self.__mc << 11) // (x1 + self.__md)
        b5 = x1 + x2

        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 += (x1 + x2 + 3791) >> 4

        return p / 100.0
Exemplo n.º 35
0
Arquivo: lcd.py Projeto: smokerbag/lcd
class Lcd:

    # Modes
    MODE_4BIT = 0x00
    MODE_8BIT = 0x10

    # Commands
    FUNCTION_SET = 0x20
    DISPLAY      = 0x08
    CLEAR        = 0x01
    ENTRY_MODE   = 0x04

    # Function set
    LINES_1     = 0x00
    LINES_2     = 0x08
    FONT_5x8    = 0x00
    FONT_5x10   = 0x04

    # Display
    DISPLAY_ON  = 0x04
    DISPLAY_OFF = 0x00
    CURSOR_ON   = 0x02
    CURSOR_OFF  = 0x00
    BLINK_ON    = 0x01
    BLINK_OFF   = 0x00

    # Entry mode
    ENTRY_RIGHT = 0x00
    ENTRY_LEFT  = 0x02
    ENTRY_SHIFT_INCREMENT = 0x01
    ENTRY_SHIFT_DECREMENT = 0x00

    # Data modes
    COMMAND = 0

    # Enable bit
    ENABLE = 0b00000100

    # Backlight
    BACKLIGHT_OFF = 0x00
    BACKLIGHT_ON  = 0x08
    
    # Timing
    MS_5 = 0.005
    MS_60 = 0.06
    US_160 = 0.00016
    CLEAR_TIME = 2

    # Constructor
    def __init__(self, address = 0x27, bus = 1, lines = 2, font = 0):
        self.address = address
        self.bus = bus
        self.lines = self.LINES_1 if lines < 2 else self.LINES_2
        self.mode = self.MODE_8BIT
        self.font = font
        self.backlight_state = self.BACKLIGHT_OFF
        print 'Addess: %s' % hex(self.address)
        print 'Lines: %s' % hex(self.lines)
        print 'Font: %s' % hex(self.font)
        print 'Bus: %s' % self.bus
        print 'Backlight state: %s' % hex(self.backlight_state)
        self.open()
        self.__initialize()

    # Open bus
    def open(self):
        print 'Open bus connection to %s' % self.bus
        self.bus = SMBus(self.bus)

    # Close bus
    def close(self):
        print 'Close bus connection'
        self.bus.close()

    # Run the command
    def command(self, command):
        print 'Running command %s' % hex(command)
        self.__send(command, self.COMMAND)

    # Clear
    def clear(self):
        print 'Clearing'
        self.command(self.CLEAR)
        time.sleep(self.CLEAR_TIME)

    # Turn backlight on
    def backlight_on(self):
        print 'Turn backlight on'
        self.backlight_state = self.BACKLIGHT_ON
        self.command(self.BACKLIGHT_ON)

    # Initialize LCD in 4 bit mode. We are in 8 bit mode until we
    # switch to 4 bit mode
    def __initialize(self):
        print 'Initializing LCD'
        # In 8 bit mode
        self.__send(0x3)
        time.sleep(self.MS_5) 
        self.__send(0x3)
        time.sleep(self.US_160)
        self.__send(0x3)
        time.sleep(self.US_160)
        self.__send(0x2) # This enables 4 bit mode
        time.sleep(self.US_160)
        # We are now in 4 bit mode
        print '4 bit mode enabled'
        self.mode = self.MODE_4BIT
        # Function set
        self.__send(self.FUNCTION_SET | self.mode | self.lines | self.font)
        time.sleep(self.MS_60)
        print 'Function set'
        # Turn display on with no cursor or blinking
        self.__configure_display(self.DISPLAY_ON | self.CURSOR_OFF | self.BLINK_OFF)
        # Clear display
        self.clear()
        # Set default text direction
        self.__configure_entry_mode(self.ENTRY_LEFT | self.ENTRY_SHIFT_DECREMENT)
        # Backlight on
        self.backlight_on()

    # Configure display
    def __configure_display(self, flags):
        print 'Configuring display'
        print 'Flags: %s' % self.__to_byte(flags)
        self.__send(self.DISPLAY | flags)

    # Configure entry mode
    def __configure_entry_mode(self, flags):
        print 'Configuring entry mode'
        print 'Flags: %s' % self.__to_byte(flags)
        self.__send(self.ENTRY_MODE | flags)

    # Send data to LCD
    def __send(self, data, mode = 0):
        print 'Sending data: %s' % hex(data)
        print 'Byte: %s' % self.__to_byte(data)

        if (self.mode == self.MODE_8BIT):
            print 'In 8 bit mode'
            self.__write_4(mode | (data & 0x0F))
        else:
            print 'In 4 bit mode'
            self.__write_4(mode | (data >> 4))
            self.__write_4(mode | (data & 0x0F))

    # Write 4 bits
    def __write_4(self, data):
        data = data | self.backlight_state
        print 'Writing 4 bits: %s' % self.__to_nibble(data)
        self.__pulse_enable(data)

    # Pulse enable
    def __pulse_enable(self, data):
        print 'Pulsing enable'
        data = data | self.ENABLE
        print 'ENABLE: %s' % self.__to_nibble(data)
        self.__i2c_write_byte(data)
        data = data & ~self.ENABLE
        print 'DISABLE: %s' % self.__to_nibble(data)
        self.__i2c_write_byte(data)

    # I2C write byte
    def __i2c_write_byte(self, data):
        print 'Writing %s to bus' % self.__to_byte(data)

    # Convert to 4 bit string
    def __to_nibble(self, val):
        return bin(val)[2:].zfill(4)
    
    # Convert to 8 bit string
    def __to_byte(self, val):
        return bin(val)[2:].zfill(8)