示例#1
0
    def __init__(self, loop):
        # once pressed, and released; keys show up in this queue
        self._changes = Queue(24)
        self.key_pressed = ''

        self.debug = 0  # 0..2

        self.last_event_time = utime.ticks_ms()
示例#2
0
    def __init__(self, loop):
        # once pressed, and released; keys show up in this queue
        self._changes = Queue(24)
        self.key_pressed = ''
        self._disabled = False

        self.debug = 0  # 0..2
        self.repeat_delay = 450  # (ms) time to wait before first key-repeat

        self.last_event_time = utime.ticks_ms()
示例#3
0
    def __init__(self, loop):
        # once pressed, and released; keys show up in this queue
        self._changes = Queue(24)
        self.key_pressed = ''
        self._disabled = False

        # hook needed for IRQ
        global _singleton
        assert not _singleton
        _singleton = self

        self.cols = [Pin(i) for i in ('COL0', 'COL1', 'COL2')]
        self.rows = [Pin(i) for i in ('ROW0', 'ROW1', 'ROW2', 'ROW3')]
        self.pins = self.cols + self.rows

        # Lots of tuning here:
        # - higher CTPH (high pulse length) helps w/ sensitivity and reliability
        # - decrease prescale to speed up acq, but to a point.
        # - CTPH+CTPL has big impact on overal sample time
        # - larger pulse prescale => more noise margin, MAYBE; but too slow to do own averaging
        #
        self.tsc = touch.Touch(channels=self.pins,
                               caps=['CS0', 'CS1', 'CS2'],
                               handler=self.irq,
                               float_unused=0,
                               CTPH=12,
                               CTPL=12,
                               pulse_prescale=4,
                               max_count=16383)

        self.debug = 0  # 0..2
        self.sensitivity = 1  # 0..2: 0=sensitive, 2=less-so
        self.baseline = None
        self.count = 0
        self.levels = array.array('I', (0 for i in range(NUM_PINS)))
        self.prev_levels = array.array('I', (0 for i in range(NUM_PINS)))
        self.scan_pin = 0

        self.last_event_time = utime.ticks_ms()

        self.trigger_baseline = False

        # Scan in random order, because tempest.
        # But Tempest? Scan order, when we scan completely, everytime,
        # doesn't reveal anything, and the difference between touch
        # vs no touch is a few millivolts anyway... but harmless?
        self.scan_order = list(range(7))
        shuffle(self.scan_order)

        # begin scanning sequence
        self.loop = loop
        self.start()
示例#4
0
    def __init__(self):

        self.queue = Queue()
        self.msub = {}
        self.mpub = []
        self.run = False
        self.m_addr = "MQTT->"
        self.msg_sz = len(self.m_addr)
    def __init__(self) -> None:
        """
        MQTT Service for the tlvlp.iot project
        Handles the connection and communication with the server via an MQTT broker

        Currently it is using a blocking MQTT client with asynchronous co-routines. This results in blocking all the
        other coros for the duration of the connection (usually around 2-3s and the timeout is 15s)

        Tested on ESP32 MCUs
        """

        print("MQTT service - Initializing service")
        self.mqtt_client = None
        self.connection_in_progress = False
        self.message_queue_incoming = Queue(config.mqtt_queue_size)
        self.message_queue_outgoing = Queue(config.mqtt_queue_size)
        # Add scheduled tasks
        loop = asyncio.get_event_loop()
        loop.create_task(self.connection_checker_loop())
        loop.create_task(self.incoming_message_checker_loop())
        loop.create_task(self.outgoing_message_sender_loop())
        print("MQTT service - Service initialization complete")
示例#6
0
    def __init__(self, config, status_led=None, layout=TEL_12_KEY):
        """Initialise/Reinitialise the instance."""

        self.queue = Queue(maxsize=7)

        self.running = False

        self.led = status_led

        self.code_buffer = []

        self.config = config

        self.keys = layout

        self.key_state = [self.KEY_UP] * 16

        # Pins
        self.rows = [ 2, 3, 4, 5 ]
        self.cols = [ 34, 35, 36, 39 ]

        self.row_pins = [ Pin(pin_num, Pin.OUT) for pin_num in self.rows ]
        self.col_pins = [ Pin(pin_num, Pin.IN, Pin.PULL_DOWN) for pin_num in self.cols ]
示例#7
0
class NumpadBase:

    KEYS = '0123456789xy'

    # this signals a need to stop user interaction and re-look at ux stack
    ABORT_KEY = '\xff'

    def __init__(self, loop):
        # once pressed, and released; keys show up in this queue
        self._changes = Queue(24)
        self.key_pressed = ''
        self._disabled = False

        self.debug = 0  # 0..2
        self.repeat_delay = 450  # (ms) time to wait before first key-repeat

        self.last_event_time = utime.ticks_ms()

    @property
    def disabled(self):
        return self._disabled

    async def get(self):
        # Get keypad events. Single-character strings.
        return await self._changes.get()

    def get_nowait(self):
        # Poll if anything ready: not async!
        return self._changes.get_nowait()

    def empty(self):
        return self._changes.empty()

    def capture_baseline(self):
        # call this at a time when we feel no keys are pressed (during boot up)
        pass

    def stop(self):
        # Stop scanning
        self._disabled = True

    def abort_ux(self):
        # pretend a key was pressed, in order to unblock things
        self.inject(self.ABORT_KEY)

    def inject(self, key):
        # fake a key press and release
        if not self._changes.full():
            self.key_pressed = ''
            self._changes.put_nowait(key)
            self._changes.put_nowait('')

    def _key_event(self, key):
        if key != self.key_pressed:
            # annouce change
            self.key_pressed = key

            if self._changes.full():
                # no space, but do a "all up" and the new event
                print('Q overflow')
                self._changes.get_nowait()
                self._changes.get_nowait()
                if key != '':
                    self._changes.put_nowait('')

            self._changes.put_nowait(key)

            self.last_event_time = utime.ticks_ms()
示例#8
0
class Numpad:

    KEYS = '0123456789xy'

    # (row, col) => keycode
    DECODER = {
        (3, 2): '1',
        (3, 1): '2',
        (3, 0): '3',
        (2, 2): '4',
        (2, 1): '5',
        (2, 0): '6',
        (1, 2): '7',
        (1, 1): '8',
        (1, 0): '9',
        (0, 2): 'x',
        (0, 1): '0',
        (0, 0): 'y',
    }

    #ENCODER = dict((v, k) for k,v in DECODER.items())

    # this signals a need to stop user interaction and re-look at ux stack
    ABORT_KEY = '\xff'

    def __init__(self, loop):
        # once pressed, and released; keys show up in this queue
        self._changes = Queue(24)
        self.key_pressed = ''
        self._disabled = False

        # hook needed for IRQ
        global _singleton
        assert not _singleton
        _singleton = self

        self.cols = [Pin(i) for i in ('COL0', 'COL1', 'COL2')]
        self.rows = [Pin(i) for i in ('ROW0', 'ROW1', 'ROW2', 'ROW3')]
        self.pins = self.cols + self.rows

        # Lots of tuning here:
        # - higher CTPH (high pulse length) helps w/ sensitivity and reliability
        # - decrease prescale to speed up acq, but to a point.
        # - CTPH+CTPL has big impact on overal sample time
        #
        self.tsc = touch.Touch(channels=self.pins,
                               caps=['CS0', 'CS1', 'CS2'],
                               handler=self.irq,
                               float_unused=0,
                               CTPH=2,
                               CTPL=2,
                               pulse_prescale=8,
                               max_count=16383)

        self.debug = 0  # or 1 or 2
        self.baseline = None
        self.count = 0
        self.levels = array.array('I', (0 for i in range(NUM_PINS)))
        self.scan_pin = 0

        self.last_event_time = utime.ticks_ms()

        self.trigger_baseline = False

        # Scan in random order, because tempest.
        # But Tempest? Scan order, when we scan completely, everytime,
        # doesn't reveal anything, and the difference between touch
        # vs no touch is a few millivolts anyway... but harmless?
        self.scan_order = list(range(7))
        shuffle(self.scan_order)

        # begin scanning sequence
        self.loop = loop
        self.start()

    @property
    def disabled(self):
        return self._disabled

    async def get(self):
        # Get keypad events. Single-character strings.
        return await self._changes.get()

    def get_nowait(self):
        # Poll if anything ready: not async!
        return self._changes.get_nowait()

    def empty(self):
        return self._changes.empty()

    def capture_baseline(self):
        # call this at a time when we feel no keys are pressed (during boot up)
        self.trigger_baseline = True

    @staticmethod
    def irq(tsc):
        # done sampling a Row or Column; store result and continue scan
        self = _singleton
        assert tsc == self.tsc

        val = tsc.finished()
        if val == 0:
            # serious hardware fault? How to report it?
            # also seeing as noise signal when microsd runs
            print("maxcount on %r" % self.scan_pin)
        else:
            self.levels[self.scan_pin] = val

        # must let lines dischange for 1ms
        self.tsc.discharge()

        # do next step, after 1ms delay
        self.loop.call_later_ms(1, self.irq_step2)

    def irq_step2(self):
        # Sample next pin / maybe look at results.
        if self._disabled:
            return

        # move to next pin
        self.scan_idx += 1
        if self.scan_idx == NUM_PINS:
            self.scan_idx = 0

            # been around once now; we have some data
            self.calc()

        self.scan_pin = self.scan_order[self.scan_idx]

        # start the next scan
        self.tsc.start_sample(self.pins[self.scan_pin])

    def stop(self):
        # Stop scanning
        self._disabled = True

    def start(self):
        # Begin scanning for events
        self._disabled = False

        self.scan_idx = 0
        self.scan_pin = self.scan_order[0]

        # prime the irq pump
        self.tsc.start_sample(self.pins[self.scan_pin])

    def abort_ux(self):
        # pretend a key was pressed, in order to unblock things
        self.inject(self.ABORT_KEY)

    def inject(self, key):
        # fake a key press and release
        if not self._changes.full():
            self.key_pressed = ''
            self._changes.put_nowait(key)
            self._changes.put_nowait('')

    def calc(self):
        # average history, apply threshold to know which are "down"
        if self.debug == 1:
            print('\x1b[H\x1b[2J\n')
            LABELS = [('col%d' % n) for n in range(3)] + [('row%d' % n)
                                                          for n in range(4)]
        if self.debug == 2:
            from main import dis
            dis.clear()

        pressed = set()
        now = []
        diffs = []
        for idx in range(NUM_PINS):
            avg = self.levels[idx]  # not an average anymore
            now.append(avg)

            if self.baseline:
                diff = self.baseline[idx] - avg

                # the critical "threshold" .. remember, values below this are
                # might be "light" touches or proximity.
                if diff > THRESHOLD:
                    pressed.add(idx)

                if self.debug == 1:
                    print('%s: %5d   %4d   %d' %
                          (LABELS[idx], avg, diff, idx in pressed))
                    diffs.append(diff)

                if self.debug == 2:
                    from main import dis
                    y = (idx * 6) + 3

                    if 0:
                        x = int((avg * 128) / 16384.)
                        bx = int((self.baseline[idx] * 128) / 16384.)

                        for j in range(4):
                            dis.dis.line(0, y + j, 128, y + j, 0)

                        dis.dis.pixel(x, y, 1)
                        dis.dis.pixel(bx, y + 1, 1)

                    dx = 64 + int(diff / 8)
                    dx = min(max(0, dx), 127)
                    dis.dis.pixel(dx, y + 2, 1)
                    dis.dis.pixel(dx, y + 3, 1)

                    if idx == 0:
                        dx = 64 + int(THRESHOLD / 8)
                        dis.dis.vline(dx, 60, 64, 1)

                    dis.show()

        if self.debug == 1:
            print('\n')
            if diffs:
                print('min_diff = %d' % min(diffs))
                print('avg_diff = %d' % (sum(diffs) / len(diffs)))

        # should we remember this as a reference point (of no keys pressed)
        if self.trigger_baseline:
            self.baseline = now.copy()
            self.trigger_baseline = False
            pressed.clear()

        if self.debug == 2: return

        # Consider only single-pressed here; we can detect
        # many 2-key combo's but no plan to support that so they
        # are probably noise from that PoV.
        col_down = [i for i in range(3) if i in pressed]
        row_down = [i - 3 for i in range(3, 7) if i in pressed]

        if len(col_down) == 1 and len(row_down) == 1:
            # determine what key
            key = self.DECODER[(row_down[0], col_down[0])]
        else:
            # not sure, or all up
            key = ''

        if key != self.key_pressed:
            # annouce change
            self.key_pressed = key

            if self._changes.full():
                # no space, but do a "all up" and the new event
                print('numpad Q overflow')
                self._changes.get_nowait()
                self._changes.get_nowait()
                if key != '':
                    self._changes.put_nowait('')

            self._changes.put_nowait(key)

            self.last_event_time = utime.ticks_ms()
示例#9
0
class NumpadBase:

    KEYS = '0123456789xy'

    # this signals a need to stop user interaction and re-look at ux stack
    ABORT_KEY = '\xff'

    def __init__(self, loop):
        # once pressed, and released; keys show up in this queue
        self._changes = Queue(24)
        self.key_pressed = ''

        self.debug = 0  # 0..2

        self.last_event_time = utime.ticks_ms()

    async def get(self):
        # Get keypad events. Single-character strings.
        return await self._changes.get()

    def get_nowait(self):
        # Poll if anything ready: not async!
        return self._changes.get_nowait()

    def empty(self):
        return self._changes.empty()

    def abort_ux(self):
        # pretend a key was pressed, in order to unblock things
        self.inject(self.ABORT_KEY)

    def inject(self, key):
        # fake a key press and release
        if not self._changes.full():
            self.key_pressed = ''
            self._changes.put_nowait(key)
            self._changes.put_nowait('')

    def _key_event(self, key):
        if key != self.key_pressed:
            # annouce change
            self.key_pressed = key

            if self._changes.full():
                # no space, but do a "all up" and the new event
                print('Q overflow')
                self._changes.get_nowait()
                self._changes.get_nowait()
                if key != '':
                    self._changes.put_nowait('')

            self._changes.put_nowait(key)

            self.last_event_time = utime.ticks_ms()
示例#10
0
 def __init__(self):
     self.queue = Queue()
     self.msub = {}
     self.mpub = []
     self.sid = 0
示例#11
0
# aqtest.py Demo/test program for MicroPython library micropython-uasyncio.queues
# Author: Peter Hinch
# Copyright Peter Hinch 2017 Released under the MIT license

try:
    import asyncio_priority as asyncio
except ImportError:
    import uasyncio as asyncio

from uasyncio.queues import Queue

q = Queue()


async def slow_process():
    await asyncio.sleep(2)
    return 42


async def bar():
    print('Waiting for slow process.')
    result = await slow_process()
    print('Putting result onto queue')
    await q.put(result)  # Put result on q


async def foo():
    print("Running foo()")
    result = await (q.get())
    print('Result was {}'.format(result))
class MqttService:
    def __init__(self) -> None:
        """
        MQTT Service for the tlvlp.iot project
        Handles the connection and communication with the server via an MQTT broker

        Currently it is using a blocking MQTT client with asynchronous co-routines. This results in blocking all the
        other coros for the duration of the connection (usually around 2-3s and the timeout is 15s)

        Tested on ESP32 MCUs
        """

        print("MQTT service - Initializing service")
        self.mqtt_client = None
        self.connection_in_progress = False
        self.message_queue_incoming = Queue(config.mqtt_queue_size)
        self.message_queue_outgoing = Queue(config.mqtt_queue_size)
        # Add scheduled tasks
        loop = asyncio.get_event_loop()
        loop.create_task(self.connection_checker_loop())
        loop.create_task(self.incoming_message_checker_loop())
        loop.create_task(self.outgoing_message_sender_loop())
        print("MQTT service - Service initialization complete")

    async def start_service(self) -> None:
        print("MQTT service - Starting service")
        self.connection_in_progress = True
        await self.init_client()
        await self.set_callback()
        await self.set_last_will()
        await self.connect_to_broker()
        await self.subscribe_to_topics()
        shared_flags.mqtt_is_connected = True
        self.connection_in_progress = False
        print("MQTT service - Service is running")

    # Startup methods

    async def init_client(self) -> None:
        print("MQTT service - Initializing client")
        self.mqtt_client = MQTTClient(config.mqtt_unit_id,
                                      config.mqtt_server,
                                      config.mqtt_port,
                                      config.mqtt_user,
                                      config.mqtt_password,
                                      ssl=config.mqtt_use_ssl,
                                      keepalive=config.mqtt_keepalive_sec)
        await asyncio.sleep(0)

    async def set_callback(self) -> None:
        print("MQTT service - Setting callback")
        self.mqtt_client.set_callback(self.callback)
        await asyncio.sleep(0)

    def callback(self, topic_bytes: bytes, payload_bytes: bytes) -> None:
        """ All incoming messages are handled by this method """
        message = MqttMessage(topic_bytes.decode(), payload_bytes.decode())
        asyncio.get_event_loop().create_task(
            self.add_incoming_message_to_queue(message))

    async def set_last_will(self) -> None:
        print("MQTT service - Setting last will")
        self.mqtt_client.set_last_will(config.mqtt_topic_inactive,
                                       config.mqtt_checkout_payload,
                                       qos=config.mqtt_qos)
        await asyncio.sleep(0)

    async def connect_to_broker(self) -> None:
        print("MQTT service - Connecting to broker")
        connected = False
        while not connected:
            try:
                self.mqtt_client.connect()
                connected = True
                print("MQTT service - Connected to broker")
            except OSError:
                if not shared_flags.wifi_is_connected:
                    # If the network connection is lost while trying to connect to the broker
                    machine.reset()
                await asyncio.sleep(0)
        await asyncio.sleep(0)

    async def subscribe_to_topics(self) -> None:
        print("MQTT service - Subscribing to topics")
        for topic in config.mqtt_subscribe_topics:
            self.mqtt_client.subscribe(topic, qos=config.mqtt_qos)
        await asyncio.sleep(0)

    # Interface methods

    async def add_incoming_message_to_queue(self,
                                            message: MqttMessage) -> None:
        """ Takes an MqttMessage and adds it to the queue to be processed """
        if self.message_queue_incoming.full():
            return  # filter out message flood
        await self.message_queue_incoming.put(message)

    async def add_outgoing_message_to_queue(self,
                                            message: MqttMessage) -> None:
        """ Takes an MqttMessage and adds it to the queue to be processed """
        if self.message_queue_outgoing.full():
            return  # prevent message flood
        await self.message_queue_outgoing.put(message)

    # Scheduled loops

    async def connection_checker_loop(self) -> None:
        """ Periodically checks the connection status and reconnects if necessary """
        while True:
            if not shared_flags.mqtt_is_connected and not self.connection_in_progress and shared_flags.wifi_is_connected:
                await self.start_service()
            await asyncio.sleep(config.mqtt_connection_check_interval_sec)

    async def outgoing_message_sender_loop(self) -> None:
        """ Processes the outgoing message queue"""
        while True:
            message = await self.message_queue_outgoing.get()
            topic = message.get_topic()
            payload = message.get_payload()
            try:
                while not shared_flags.mqtt_is_connected:
                    await asyncio.sleep(0)
                self.mqtt_client.publish(topic, payload, qos=config.mqtt_qos)
                print(
                    "MQTT service - Message published to topic:{} with payload: {}"
                    .format(topic, payload))
            except OSError:
                print(
                    "MQTT service - Error in publishing message to topic:{} with payload: {}"
                    .format(topic, payload))
                shared_flags.mqtt_is_connected = False

    async def incoming_message_checker_loop(self) -> None:
        """ Periodically checks for new messages at the broker. Messages will be handled via the callback method """
        while True:
            if shared_flags.mqtt_is_connected:
                try:
                    self.mqtt_client.check_msg()
                except OSError:
                    print(
                        "MQTT service - Error! Messages cannot be retrieved from the MQTT broker. Connection lost."
                    )
                    shared_flags.mqtt_is_connected = False
            await asyncio.sleep_ms(config.mqtt_message_check_interval_ms)
示例#13
0
async def main_task(loop):

    # initialize features
    connect()  # TOOD: write seperate function for wlan
    ntptime.settime()  # set time
    #config_num = init_dip_button()
    config_num = 5
    i2c = init_i2c()
    lan = init_lan()
    init_fan()

    print(config_num)

    # configs
    display_config = {
        'pin_r': 16,
        'pin_l': 17,
        'num_leds': 14,
        'update_rate': 1.5
    }
    sps30_config = {'i2c': i2c, 'lock': None, 'update_rate': 1.5}
    sht31_config = {'i2c': i2c, 'lock': None, 'update_rate': 1.5}
    logic_config = {'logic_pin': 33}
    mqtt_config = {'broker': '192.168.50.100'}

    f = open('config.json', 'r')
    configs = ujson.load(f)["config"]
    f.close()

    mode = configs[config_num]["mode"]
    thres = configs[config_num]["thres"]

    # initialize queues
    main_queue = Queue()
    display_queue = Queue()
    mqtt_queue = Queue()
    logic_queue = Queue()

    # initialize tasks
    display_instance = display_task(display_queue, display_config)
    mqtt_instance = mqtt_task(mqtt_queue, mqtt_config)
    sps30_instance = sps30_task(main_queue, sps30_config)
    sht31_instance = sht31_task(main_queue, sht31_config)
    logic_instance = logic_task(logic_queue, logic_config)

    # starting tasks
    loop.create_task(display_instance)
    loop.create_task(mqtt_instance)
    loop.create_task(sps30_instance)
    loop.create_task(sht31_instance)
    loop.create_task(logic_instance)

    print("Config: " + str(config_num))
    await display_queue.put(
        ('percent', config_num / 8))  # TODO: change config_num
    time.sleep(2)

    pm10_percent = 0
    co2_percent = 0
    voc_percent = 0

    while True:
        msg = await main_queue.get()
        data = msg[1]
        if msg[0] == 'sps30_info':
            #print(data)
            pass
        elif msg[0] == 'sps30_data':
            pm10_percent = data["pm10_mass"] / thres["pm10"]
            print("PM10: " + str(data["pm10_mass"]))
            await mqtt_queue.put(('pm', data))
        elif msg[0] == 'sht31_info':
            print(data)
        elif msg[0] == 'sht31_data':
            print(data)
        else:
            print('unkown message: ' + msg[0])

        display_percent = max(pm10_percent, co2_percent, voc_percent)
        if display_percent >= 1.0:
            await logic_queue.put(('on', ''))
        else:
            await logic_queue.put(('off', ''))
        await display_queue.put(('percent_smooth', display_percent))
示例#14
0
    def init(self,
             queue_size=QUEUE_SIZE_DEFAULT,
             start=START_DEFAULT,
             long_keypress_count=LONG_KEYPRESS_COUNT_DEFAULT):
        """Initialise/Reinitialise the instance."""

        ## Create the queue to push key events to.
        self.queue = Queue(maxsize=queue_size)

        self.running = start
        self.long_keypress_count = long_keypress_count

        ## The chars on the keypad
        keys = [
            '1',
            '2',
            '3',
            'A',
            '4',
            '5',
            '6',
            'B',
            '7',
            '8',
            '9',
            'C',
            '*',
            '0',
            '#',
            'D',
        ]

        ## The chars to display/return when the key is pressed down for a long time.
        self.chars_long = [
            'm',
            'i',
            'e',
            'a',
            'n',
            'j',
            'f',
            'b',
            'o',
            'k',
            'g',
            'c',
            'p',
            'l',
            'h',
            'd',
        ]

        ## Initialise all keys to the UP state.
        self.keys = [{
            'char': key,
            'state': self.KEY_UP,
            'down_count': 0
        } for key in keys]

        ## Pin names for rows and columns.
        self.rows = ['PD1', 'PD3', 'PD5', 'PD7']
        self.cols = ['PD9', 'PD11', 'PD13', 'PD15']

        ## Initialise row pins as outputs.
        self.row_pins = [Pin(pin_name, mode=Pin.OUT) for pin_name in self.rows]

        ## Initialise column pins as inputs.
        self.col_pins = [
            Pin(pin_name, mode=Pin.IN, pull=Pin.PULL_DOWN)
            for pin_name in self.cols
        ]

        self.row_scan_delay_ms = 40 // len(self.rows)
示例#15
0
class Keypad_uasyncio():
    """Class to scan a Keypad matrix (e.g. 16-keys as 4x4 matrix) and report
       key presses.
    """

    ## Key states/events
    KEY_UP = 0
    KEY_DOWN = 1
    KEY_DOWN_LONG = 2
    KEY_UP_LONG = 3  ## an event only, not a state.

    #-------------------------------------------------------------------------

    def __init__(self,
                 queue_size=QUEUE_SIZE_DEFAULT,
                 start=START_DEFAULT,
                 long_keypress_count=LONG_KEYPRESS_COUNT_DEFAULT):
        """Constructor."""

        self.init(queue_size=queue_size,
                  start=start,
                  long_keypress_count=long_keypress_count)

    #-------------------------------------------------------------------------

    def init(self,
             queue_size=QUEUE_SIZE_DEFAULT,
             start=START_DEFAULT,
             long_keypress_count=LONG_KEYPRESS_COUNT_DEFAULT):
        """Initialise/Reinitialise the instance."""

        ## Create the queue to push key events to.
        self.queue = Queue(maxsize=queue_size)

        self.running = start
        self.long_keypress_count = long_keypress_count

        ## The chars on the keypad
        keys = [
            '1',
            '2',
            '3',
            'A',
            '4',
            '5',
            '6',
            'B',
            '7',
            '8',
            '9',
            'C',
            '*',
            '0',
            '#',
            'D',
        ]

        ## The chars to display/return when the key is pressed down for a long time.
        self.chars_long = [
            'm',
            'i',
            'e',
            'a',
            'n',
            'j',
            'f',
            'b',
            'o',
            'k',
            'g',
            'c',
            'p',
            'l',
            'h',
            'd',
        ]

        ## Initialise all keys to the UP state.
        self.keys = [{
            'char': key,
            'state': self.KEY_UP,
            'down_count': 0
        } for key in keys]

        ## Pin names for rows and columns.
        self.rows = ['PD1', 'PD3', 'PD5', 'PD7']
        self.cols = ['PD9', 'PD11', 'PD13', 'PD15']

        ## Initialise row pins as outputs.
        self.row_pins = [Pin(pin_name, mode=Pin.OUT) for pin_name in self.rows]

        ## Initialise column pins as inputs.
        self.col_pins = [
            Pin(pin_name, mode=Pin.IN, pull=Pin.PULL_DOWN)
            for pin_name in self.cols
        ]

        self.row_scan_delay_ms = 40 // len(self.rows)

    #-------------------------------------------------------------------------

    def start(self):
        """Start keypad scanning."""

        self.running = True

    #-------------------------------------------------------------------------

    def stop(self):
        """Stop the timer."""

        self.running = False

    #-------------------------------------------------------------------------

    def get_key(self):
        """Get last key pressed."""

        key = self.queue.get()
        return key

    #-------------------------------------------------------------------------

    def key_process(self, key_code, col_pin):
        """Process a key press or release."""

        key = self.keys[key_code]
        key_event = None

        if col_pin.value():
            ## key pressed down
            if key['state'] == self.KEY_UP:
                ## just pressed (up => down)
                key_event = self.KEY_DOWN
                key['state'] = key_event
            elif key['state'] == self.KEY_DOWN:
                ## key still down
                key['down_count'] += 1
                if key['down_count'] >= self.long_keypress_count:
                    key_event = self.KEY_DOWN_LONG
                    key['state'] = key_event
        else:
            ## key not pressed (up)
            if key['state'] == self.KEY_DOWN:
                ## just released (down => up)
                key_event = self.KEY_UP if key[
                    'down_count'] < self.long_keypress_count else self.KEY_UP_LONG
            key['state'] = self.KEY_UP
            key['down_count'] = 0

        return key_event

    #-------------------------------------------------------------------------

    async def scan_coro(self):
        """A coroutine to scan each row and check column for key events."""

        while self.running:
            key_code = 0
            for row, row_pin in enumerate(self.row_pins):
                ## Assert row.
                row_pin.value(1)

                ## Delay between processing each row.
                await asyncio.sleep_ms(self.row_scan_delay_ms)

                ## Check for key events for each column of current row.
                for col, col_pin in enumerate(self.col_pins):
                    ## Process pin state.
                    key_event = self.key_process(key_code=key_code,
                                                 col_pin=col_pin)
                    ## Process key event.
                    if key_event == self.KEY_UP:
                        key_char = self.keys[key_code]['char']
                        await self.queue.put(key_char)
                    elif key_event == self.KEY_DOWN_LONG:
                        key_char = self.chars_long[key_code]
                        await self.queue.put(key_char)

                    key_code += 1

                ## Deassert row.
                row_pin.value(0)
示例#16
0
import pyb
import network

import led36
from lsm9ds1 import LSM9DS1

import uasyncio
from uasyncio.websocket.server import WSReader, WSWriter
from uasyncio.queues import Queue

import picoweb

import os

measurement_queue = Queue()


if pyb.SDCard().present():
    os.mount(pyb.SDCard(), '/sd')
    print("Mounted SD Card")
    print("/sd:", os.listdir("/sd/"))
    print("/sd/web:", os.listdir("/sd/web"))
else:
    print("No SD Card present!")


def init_led_tile():
    led36.brightness(100)
    led36.illu(0, 0, 0)