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()
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()
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()
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")
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 ]
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()
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()
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()
def __init__(self): self.queue = Queue() self.msub = {} self.mpub = [] self.sid = 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)
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))
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)
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)
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)