Beispiel #1
0
class GroveAlphanumDisplay(object):
    def __init__(self,
                 address=0x71,
                 brightness=BRIGHT_DEFAULT,
                 display_type=FOUR_TUBES):
        """
        Constructor

        Args:
            address: I2C address, default is 0x71
            brightness: Startup brightness, value between 0 and 15
            display_type: Display type, can be one of 0: FOUR_TUBES and 1: TWO_TUBES
        """
        self.address = address
        self.display_type = display_type
        self.font = display_font4 if display_type == FOUR_TUBES else display_font2
        self.first_dot = False
        self.second_dot = False

        self.bus = Bus()
        self.data = [0] * 4 if self.display_type == FOUR_TUBES else 2

        self.bus.write_i2c_block_data(self.address, REG_INIT, [])
        self.bus.write_i2c_block_data(self.address, DISP_ON, [])
        self.set_brightness(brightness)

    def clear(self):
        """
        Clear display
        """
        self.data = [0] * 4 if self.display_type == FOUR_TUBES else 2
        self.first_dot = False
        self.second_dot = False
        self._show()

    def show(self, data):
        """
        Show a string on the display

        Args:
            data: String to show. If it is longer than the display size (2 or 4),
                  the string is trimmed to display length.
        """
        if type(data) is str:
            self.data = [0] * 4 if self.display_type == FOUR_TUBES else 2
            length = min(len(data), len(self.data))
            for i in range(length):
                self.data[i] = self.font.get(data[i], 0)
        else:
            raise ValueError('Not support {}'.format(type(data)))
        self._show()

    def _show(self):
        """
        Internal function to show the display data.
        First, create the I2C data to write to the display controller and then send it.
        """
        wire_bytes = [0, 0]
        byte_10 = 0
        byte_11 = 0

        if self.display_type == FOUR_TUBES:
            for d in self.data:
                wire_bytes += [d & 0xFF, (d >> 8) & 0xFF]
            for i, d in enumerate(self.data):
                if i == 0:
                    byte_10 |= (1 if (d & 0x02) else 0) << 4
                    byte_10 |= (1 if (d & 0x04) else 0) << 3
                elif i == 1:
                    byte_10 |= (1 if (d & 0x02) else 0) << 6
                    byte_11 |= (1 if (d & 0x04) else 0) << 6
                elif i == 2:
                    byte_10 |= (1 if (d & 0x02) else 0) << 5
                    byte_11 |= (1 if (d & 0x04) else 0) << 1
                else:
                    byte_11 |= (1 if (d & 0x02) else 0) << 2
                    byte_11 |= (1 if (d & 0x04) else 0) << 0

            if self.first_dot:
                byte_10 |= self.font['first_dot'] & 0xFF
                byte_11 |= (self.font['first_dot'] >> 8) & 0xFF
            if self.second_dot:
                byte_10 |= self.font['second_dot'] & 0xFF
                byte_11 |= (self.font['second_dot'] >> 8) & 0xFF

        else:
            for i in [1, 0]:
                value = self.data[i]
                if i == 1 and self.first_dot:
                    value |= self.font['dot']
                if i == 0 and self.second_dot:
                    value |= self.font['dot']
                wire_bytes += [(value >> 8) & 0xFF, value & 0xFF]

            wire_bytes += [0] * 4

        wire_bytes += [byte_10, byte_11]

        self.bus.write_i2c_block_data(self.address, 0, wire_bytes)

    def set_brightness(self, brightness):
        """
        Sets the LED brightness.

        Args:
            brightness: Brightness as integer, value between 0 and 15
        """
        if brightness > BRIGHT_HIGHEST or brightness < 0:
            brightness = BRIGHT_HIGHEST

        self.bus.write_byte(self.address, REG_BRIGHT | brightness)

    def set_blink_type(self, blink_type):
        """
        Configures the blinking of the display, can be one of:
            - 0: No blinking
            - 1: Blink with 2 Hz
            - 2: Blink with 1 Hz

        Args:
            blink_type: Blinking type
        """
        if 0 <= blink_type <= 2:
            self.bus.write_byte(self.address, 0x81 | (blink_type << 1))

    def set_dots(self, first, second):
        """
        Sets the dots in the display.

        Args:
            first: If set, the first/upper dot is on
            second: If set, the second/lower dot is on
        """
        self.first_dot = first
        self.second_dot = second
        self._show()
Beispiel #2
0
class ButtonTypedI2c(Button):
    '''
    I2C Button/Switch Array Class

    provide event checking ability to derived class,
    should not use directly by end-user.
    The checking events include:

      - Button.EV_SINGLE_CLICK
      - Button.EV_DOUBLE_CLICK
      - Button.EV_LONG_PRESS
      - Button.EV_LEVEL_CHANGED

    Args:
        address(int): optional, the I2C address of the connected device.
        evt_en(bool): optional, default True

            True:  provide event checking ability.

            False: used in poll environment, manually call :class:`ButtonTypedI2c.read`.
    '''
    def __init__(self, address=0x03, evt_en=True):
        super(ButtonTypedI2c, self).__init__(0)

        self.bus = Bus()
        self._addr = address

        # Initialise the I2C button device
        self.dev_id = 0
        self._probe_uid()
        self._version = 0
        self.version()
        self._size = self.size()

        self._set_mode(True)

        self.__last_evt = None
        self.__last_evt = self.read()

        self.key_names = _grove_5way_tactile_keys
        if self._size == 6:
            self.key_names = _grove_6pos_dip_switch_keys

        self.__thrd_exit = False
        self.__thrd = None
        if not evt_en:
            return

        if self.__thrd is None or not self.__thrd.is_alive():
            self.__thrd = threading.Thread( \
                    target = ButtonTypedI2c.__thrd_chk_evt, \
                    args = (self,))
            self.__thrd.setDaemon(True)
            self.__thrd.start()

    def __del__(self):
        if not self.__thrd:
            return

        self.__thrd_exit = True
        while self.__thrd.isAlive():
            time.sleep(_CYCLE_PERIOD / _CYCLE_UNIT)
        self.__thrd.join()

    # Thread to check events
    def __thrd_chk_evt(self):
        self.__last_time = time.time()
        while not self.__thrd_exit:
            # or self.__state != self.KEY_STATE_IDLE:
            t = time.time()
            dt, self.__last_time = t - self.__last_time, t

            evt = self.read()
            if not evt[0]:
                time.sleep(_CYCLE_PERIOD)
                continue

            for i in range(0, self.size()):
                if evt[i + 1] & ~self.EV_RAW_STATUS:
                    pressed = bool(evt[i + 1] & self.EV_RAW_STATUS)
                    self._index = i
                    self._send_event(evt[i + 1], pressed, t)
            time.sleep(_CYCLE_PERIOD)

    def _probe_uid(self):
        ID_LEN = 4
        for tr in range(4):
            v = self.bus.read_i2c_block_data(self._addr, _CMD_GET_DEV_ID,
                                             ID_LEN)
            # print("GET_DEV_ID = {}".format(v))
            did = 0
            for i in range(ID_LEN):
                did = (did >> 8) | (int(v[i]) << 24)
            # print("DEV_ID = {:8X}".format(did))
            if (did >> 16) == VID_MULTI_SWITCH:
                self.dev_id = did
                return self.dev_id
            self.bus.read_byte(self._addr, True)

    def version(self):
        '''
        Get the device firmware version.

        Returns:
            (int): firmware version, the first version is 1
        '''
        VER_LEN = 10
        if not self.dev_id:
            return 0
        v = self.bus.read_i2c_block_data(self._addr, _CMD_TEST_GET_VER,
                                         VER_LEN)
        # print("GET_VER = {}".format(str(v)))
        version = v[6] - ord('0')
        version = version * 10 + (v[8] - ord('0'))
        # print("version = {}".format(version))
        self._version = version
        return self._version

    def size(self):
        '''
        Get the button count the device have.

        Returns:
            (int): button count
        '''
        if (self.dev_id >> 16) != VID_MULTI_SWITCH:
            return 0
        if (self.dev_id & 0xFFFF) == PID_5_WAY_TACTILE_SWITCH:
            return 5
        if (self.dev_id & 0xFFFF) == PID_6_POS_DIP_SWITCH:
            return 6
        return 0

    def name(self, index=None):
        '''
        Get the device name or specified button name

        Args:
            index(int): optional, the index number of button to get name.
                        if not specified, return the device name.

        Returns:
            (string): the name of the device or pecified button
        '''
        if (self.dev_id >> 16) != VID_MULTI_SWITCH:
            return "Invalid dev"
        if not index is None:
            if index < 0 or index >= self._size:
                return "Invalid index"
            return self.key_names[index]

        if (self.dev_id & 0xFFFF) == PID_5_WAY_TACTILE_SWITCH:
            return NAME_5_WAY_SWITCH
        if (self.dev_id & 0xFFFF) == PID_6_POS_DIP_SWITCH:
            return NAME_6_POS_DIP_SWITCH
        return "Invalid dev"

    def _set_mode(self, enable):
        if not self.dev_id:
            return None
        v = _CMD_BLOCK_DET_MODE
        if enable:
            v = _CMD_EVENT_DET_MODE
        self.bus.write_byte(self._addr, v)
        return True

    def read(self):
        '''
        Get the button array status

        Returns:
            (list): a list has the size button count + 1
                    item [0] indicate if there is a event (bit 0x80).
                        bit 0x80 set if one or more the switches have event.
                        bit 0x80 clear if no one has event.
                    item [ 1 + `index` ] indicate the event of button specified
                        by index, be bits combination of

                              -  Button.EV_LEVEL_CHANGED
                              -  Button.EV_SINGLE_CLICK
                              -  Button.EV_DOUBLE_CLICK
                              -  Button.EV_LONG_PRESS

        '''
        EVT_LEN = 4
        if not self.dev_id:
            return None
        size = EVT_LEN + self._size
        v = self.bus.read_i2c_block_data(self._addr, _CMD_GET_DEV_EVENT, size)

        if self._version > 1 or self.__last_evt is None:
            return v[EVT_LEN - 1:]

        # Fix: v0.1 will miss event BTN_EV_LEVEL_CHANGED
        #      if this API called frequently.
        for i in range(self._size):
            if (v[EVT_LEN + i] ^ self.__last_evt[1 + i]) & self.EV_RAW_STATUS:
                v[EVT_LEN + i] |= Button.EV_LEVEL_CHANGED
                v[EVT_LEN - 1] |= 0x80
        self.__last_evt = v[EVT_LEN - 1:]
        return v[EVT_LEN - 1:]

    def is_pressed(self, index=0):
        '''
        Get the button status if it's being pressed ?

        :class:`ButtonTypedI2c.read` must be called before this api call
        when used with poll method object (created with evt_en = False).

        Args:
            index(int): optional, the index number of button to be checked.
                        must be specified for this device.

        Returns:
            (bool):
                True if the button is being pressed.
                False if not.
        '''
        return not bool(self.__last_evt[index + 1] & self.EV_RAW_STATUS)
Beispiel #3
0
class DHT(object):
    DHT_TYPE = {'DHT11': '11', 'DHT22': '22', 'DHT10': '10'}

    DEFAULT_ADDR = 0x38
    RESET_REG_ADDR = 0xba
    MAX_CNT = 320
    PULSES_CNT = 41

    def __init__(self, dht_type, pin=12, bus_num=1):
        if dht_type != self.DHT_TYPE['DHT11'] and dht_type != self.DHT_TYPE[
                'DHT22'] and dht_type != self.DHT_TYPE['DHT10']:
            print('ERROR: Please use 11|22|10 as dht type.')
            exit(1)
        self.dht_type = dht_type
        if dht_type == self.DHT_TYPE['DHT10']:
            self.bus = Bus(bus_num)
            self.addr = self.DEFAULT_ADDR
            self._dht10_init()
        else:
            self.pin = GPIO(pin, GPIO.OUT)
            self._last_temp = 0.0
            self._last_humi = 0.0

    @property
    def dht_type(self):
        return self._dht_type

    @dht_type.setter
    def dht_type(self, type):
        self._dht_type = type

    ######################## dht10 ############################

    def _dht10_start_mess(self):
        reg_set = [0x33, 0x00]
        self.bus.write_i2c_block_data(self.addr, 0xac, reg_set)

    def _dht10_reset(self):
        self.bus.write_byte(self.addr, self.RESET_REG_ADDR)

    def _dht10_set_system_cfg(self):
        reg_set = [0x08, 0x00]
        self.bus.write_i2c_block_data(self.addr, 0xe1, reg_set)

    def _dht10_read_status(self):
        return self.bus.read_byte_data(self.addr, 0)

    def _dht10_init(self):

        time.sleep(.5)
        self._dht10_reset()
        # delay is needed after reset
        time.sleep(.3)

        self._dht10_set_system_cfg()
        status = self._dht10_read_status()
        # we must check the calibrate flag, bit[3] : 1 for calibrated ok,0 for Not calibrated.
        while status & 0x08 != 0x08:
            print("try calibrated again!n\n")
            self._dht10_reset()
            time.sleep(.5)
            self.bus.dth10_set_system_cfg()
            status = self._dht10_read_status()
            time.sleep(.5)

    #########################################################
    def _read(self):
        if self.dht_type == self.DHT_TYPE['DHT10']:
            t = 0
            h = 0
            self._dht10_start_mess()
            time.sleep(.075)
            # we must check the device busy flag, bit[7] : 1 for busy ,0 for idle.
            while (self._dht10_read_status() & 0x80) != 0:
                time.sleep(.5)
                print("wait for device not busy")
            from smbus2 import SMBus, i2c_msg, SMBusWrapper
            with SMBusWrapper(1) as bus:
                msg = i2c_msg.read(self.addr, 6)
                data = bus.i2c_rdwr(msg)
            data = list(msg)
            t = (t | data[1]) << 8
            t = (t | data[2]) << 8
            t = (t | data[3]) >> 4

            h = (h | data[3]) << 8
            h = (h | data[4]) << 8
            h = (h | data[5]) & 0xfffff

            t = t * 100.0 / 1024 / 1024
            h = h * 200.0 / 1024 / 1024 - 50
            return t, h
        # Send Falling signal to trigger sensor output data
        # Wait for 20ms to collect 42 bytes data
        else:
            self.pin.dir(GPIO.OUT)

            self.pin.write(1)
            time.sleep(.2)

            self.pin.write(0)
            time.sleep(.018)

            self.pin.dir(GPIO.IN)
            # a short delay needed
            for i in range(10):
                pass

            # pullup by host 20-40 us
            count = 0
            while self.pin.read():
                count += 1
                if count > self.MAX_CNT:
                    # print("pullup by host 20-40us failed")
                    return None, "pullup by host 20-40us failed"

            pulse_cnt = [0] * (2 * self.PULSES_CNT)
            fix_crc = False
            for i in range(0, self.PULSES_CNT * 2, 2):
                while not self.pin.read():
                    pulse_cnt[i] += 1
                    if pulse_cnt[i] > self.MAX_CNT:
                        # print("pulldown by DHT timeout %d" % i)
                        return None, "pulldown by DHT timeout %d" % i

                while self.pin.read():
                    pulse_cnt[i + 1] += 1
                    if pulse_cnt[i + 1] > self.MAX_CNT:
                        # print("pullup by DHT timeout %d" % (i + 1))
                        if i == (self.PULSES_CNT - 1) * 2:
                            # fix_crc = True
                            # break
                            pass
                        return None, "pullup by DHT timeout %d" % i

            total_cnt = 0
            for i in range(2, 2 * self.PULSES_CNT, 2):
                total_cnt += pulse_cnt[i]

            # Low level ( 50 us) average counter
            average_cnt = total_cnt / (self.PULSES_CNT - 1)
            # print("low level average loop = %d" % average_cnt)

            data = ''
            for i in range(3, 2 * self.PULSES_CNT, 2):
                if pulse_cnt[i] > average_cnt:
                    data += '1'
                else:
                    data += '0'

            data0 = int(data[0:8], 2)
            data1 = int(data[8:16], 2)
            data2 = int(data[16:24], 2)
            data3 = int(data[24:32], 2)
            data4 = int(data[32:40], 2)

            if fix_crc and data4 != ((data0 + data1 + data2 + data3) & 0xFF):
                data4 = data4 ^ 0x01
                data = data[0:self.PULSES_CNT - 2] + ('1' if data4
                                                      & 0x01 else '0')

            if data4 == ((data0 + data1 + data2 + data3) & 0xFF):
                if self._dht_type == self.DHT_TYPE['DHT11']:
                    humi = int(data0)
                    temp = int(data2)
                elif self._dht_type == self.DHT_TYPE['DHT22']:
                    humi = float(int(data[0:16], 2) * 0.1)
                    temp = float(
                        int(data[17:32], 2) * 0.2 * (0.5 - int(data[16], 2)))
            else:
                # print("checksum error!")
                return None, "checksum error!"

            return humi, temp

    def read(self, retries=15):
        for i in range(retries):
            humi, temp = self._read()
            if not humi is None:
                break
        if humi is None:
            return self._last_humi, self._last_temp
        self._last_humi, self._last_temp = humi, temp
        return humi, temp
Beispiel #4
0
class ButtonTypedI2c(Button):
    def __init__(self, address=0x03):
        self.bus = Bus()
        self.addr = address
        self.dev_id = 0
        self.val = 0
        self.probeDevID()
        self.get_val()
        self.send_Byte(0x02)
        app1 = self.status_read()
        while 1:
            self.status_read()
            time.sleep(1.0)
            continue

    def set_devID(self, reg, size):
        self.bus.write_byte_data(self.addr, reg, size)

    def send_Byte(self, reg):
        self.bus.write_byte(self.addr, reg)

    def get_devID(self, data):
        return self.bus.read_byte(self.addr, data)

    def get_data(self, reg, len):
        return self.bus.read_i2c_block_data(self.addr, reg, len)

    def probeDevID(self):
        for i in range(4):
            id = self.get_data(0x00, 4)
            did = 0
            for j in range(4):
                did = (did >> 8) | (int(id[j]) << 24)
            #print("DEV_ID = {:8X}".format(did))
            if (did >> 16) == 0x2886:
                self.dev_id = did
                return self.dev_id
            self.get_devID(True)

    def get_val(self):
        if (self.dev_id & 0xFFFF) == 0x0002:
            self.val = 5
            print("Grove 5_way tactile Switch Insert")
            self.key_names = grove_5way_tactile_keys
            return self.val
        elif (self.dev_id & 0xFFFF) == 0x0003:
            self.val = 6
            print("Grove 6_pos dip Switch Insert")
            self.key_names = grove_6pos_dip_switch_keys
            return self.val

    def status_read(self):
        app = self.get_data(0x01, 4 + self.val)
        #print("get event ={}".format(app))
        for i in range(0, self.val):
            print("{} : RAW- ".format(self.key_names[i]), end='')
            print("{} ".format(app[i + 4] & 1 and "HIGH" or "LOW"))
            if (self.dev_id & 0xFFFF) == 0x0002:
                print("{} ".format(app[i + 4] & 1 and "RELEASEND"
                                   or "PRESSED"))
            elif (self.dev_id & 0xFFFF) == 0x0003:
                print("{} ".format(app[i + 4] & 1 and "OFF" or "ON"))
        for i in range(0, self.val):
            if app[i + 4] & ~1:
                print("{} ".format(self.key_names[i]))
                print(": EVENT - ")
            if app[i + 4] & (1 << 1):
                print("SINGLE-CLICK")
            if app[i + 4] & (1 << 2):
                print("DOUBLE-CLICL")
            if app[i + 4] & (1 << 3):
                print("LONG-PRESS")
            if app[i + 4] & (1 << 4):
                print("LEVEL-CHANGED")

            print("")
        return app