I've made some progress on this, but interested in comments from uasyncio afficianadoes. Am I doing it right? Here's what the program does:
- Handle interrupts and post events to a shared event queue.
- Read a socket and post received messages to a shared event queue.
- Post 'ping' events to a shared event queue.
- Post adc events to a shared event queue.
- Consume the shared event queue and write events to the same socket in the main loop.
Code: Select all
from machine import Pin, Timer, ADC
import uasyncio as asyncio
from ucollections import namedtuple
import micropython
import utime
import urandom
import network
import usocket
import uerrno
##============================================
def get_sock(ip, port):
sock = usocket.socket(usocket.AF_INET, usocket.SOCK_DGRAM)
sock.setsockopt(usocket.SOL_SOCKET, usocket.SO_REUSEADDR,1)
sock.settimeout(1)
sock.bind((ip, port))
return sock
class Board(object):
def __init__(self):
self.wlan_ = network.WLAN(network.AP_IF)
self.wlan_ .active(True) # must be true before using .config
self.wlan_.config(essid='ZZZ', password='ZZZ')
ifconf = self.wlan_.ifconfig()
print('ifconfig = {}'.format(ifconf))
self.ip_ = self.wlan_.ifconfig()[0]
self.port_ = 20001
def deactivate(self):
self.wlan_.active(False)
def host(self):
return self.ip_
def port(self):
return self.port_
##============================================
Event = namedtuple("Event", ("events", "flag", "value"))
##============================================
last_value_change_ms = 0
def debounce():
global last_value_change_ms
cur_time = utime.ticks_ms()
diff = cur_time - last_value_change_ms
bounce = diff < 500
last_value_change_ms = utime.ticks_ms()
return bounce
def add_button_event(event):
event.events.insert(0, 'B:{}'.format(event.value))
event.flag.set()
def get_button_handler(events, flag):
def handler(pin):
if debounce():
return
event = Event(events, flag, pin)
micropython.schedule(add_button_event, event)
return handler
# ==============================================================
board = Board()
sock = get_sock(board.host(), board.port())
sock.settimeout(0)
async def get_messages(events, flag):
global sock
BUFSZ = 1024
sock.settimeout(0)
while True:
try:
await asyncio.sleep_ms(250)
message, address = sock.recvfrom(BUFSZ)
events.insert(0, message)
events.insert(0, address)
flag.set()
except OSError as e:
if e.args[0] not in [uerrno.EINPROGRESS, uerrno.ETIMEDOUT, uerrno.EAGAIN]:
raise
# ================================================================
count = 0
async def ping(events, flag):
global count
while True:
await asyncio.sleep(10)
count += 1
message = 'PING:{}'.format(count)
events.insert(0, message)
flag.set()
# ===============================================================
pot = ADC(Pin(34))
pot.atten(ADC.ATTN_11DB)
pot_prev = 0
pot_curr = 0
def add_adc_event(event):
global pot
global pot_prev
global pot_curr
pot_curr = pot.read()//100
if abs(pot_curr - pot_prev) > 1:
pot_prev = pot_curr
event.events.insert(0, 'POT:{}'.format(pot_curr))
event.flag.set()
def get_adc_handler(events, flag):
def handler(timer):
event = Event(events, flag, timer.value())
micropython.schedule(add_adc_event, event)
return handler
# =================================================================
def add_ping_event(event):
global count
event.events.insert(0, 'ZZZZ:{}'.format(count))
event.flag.set()
def get_ping_handler(events, flag):
def handler(timer):
event = Event(events, flag, timer.value())
micropython.schedule(add_ping_event, event)
return handler
# =================================================================
async def reactor():
global sock
pins = [14, 15, 27]
events = []
flag = asyncio.ThreadSafeFlag()
for p in pins:
pin = Pin(p, Pin.IN, Pin.PULL_UP)
pin.irq(trigger = Pin.IRQ_FALLING, handler = get_button_handler(events, flag))
await asyncio.sleep(0)
timer0 = Timer(0)
timer0.init(mode=Timer.PERIODIC, period=500, callback=get_adc_handler(events, flag))
timer1 = Timer(1)
timer1.init(mode=Timer.PERIODIC, period=5000, callback=get_ping_handler(events, flag))
asyncio.create_task(get_messages(events, flag))
asyncio.create_task(ping(events, flag))
address = None
while True:
if len(events) == 0:
await flag.wait()
while len(events):
event = events.pop()
print(event)
if type(event) == tuple:
address = event
elif address is not None:
sock.sendto(event, address)
asyncio.run(reactor())