CircuitPython - Read user input from USB serial non-blocking
In CircuitPython, we can get user input using input(). But it's a blocking
function, that means it will not return until user input something. It's useful tricks to read user input non-blocking, circuitpython-tricks.
Here are my modified exercises running on ESP32-S3-DevKitC-1 flashed CircuitPython 8.0.5. In my exercises, onboard RGB neopixel change color to show it's non-blocking. Library neopixel.mpy is needed in my exercises, read ESP32-S3-DevKitC-1/CircuitPython to drive NeoPixel.
non-blocking_mostly.py Read user input from USB Serial, non-blocking (mostly)
In my test, supervisor.runtime.serial_bytes_available will not be cleared once user input; become blocking.
non-blocking.py Read user input from USB serial, non-blocking
read_key.py Read keys from USB Serial
Here are my modified exercises running on ESP32-S3-DevKitC-1 flashed CircuitPython 8.0.5. In my exercises, onboard RGB neopixel change color to show it's non-blocking. Library neopixel.mpy is needed in my exercises, read ESP32-S3-DevKitC-1/CircuitPython to drive NeoPixel.
non-blocking_mostly.py Read user input from USB Serial, non-blocking (mostly)
In my test, supervisor.runtime.serial_bytes_available will not be cleared once user input; become blocking.
"""
Read user input from USB Serial, non-blocking (mostly)
https://github.com/todbot/circuitpython-tricks#read-user-input-from-usb-serial-non-blocking-mostly
"""
import time
import supervisor
import board
import neopixel
# Create the NeoPixel object
pixel = neopixel.NeoPixel(board.NEOPIXEL,
1,
pixel_order=neopixel.GRB)
pixel[0] = (0, 0, 0)
neo = [0, 0, 150]
def rotNeopixel():
pixel[0] = (neo[0], neo[1], neo[2])
neo.insert(0, neo.pop())
print("Type something when you're ready")
last_time = time.monotonic()
while True:
if supervisor.runtime.serial_bytes_available:
my_str = input()
print("You entered:", my_str)
if time.monotonic() - last_time > 1: # every second
last_time = time.monotonic()
rotNeopixel()
non-blocking.py Read user input from USB serial, non-blocking
"""
Read user input from USB serial, non-blocking
https://github.com/todbot/circuitpython-tricks#read-user-input-from-usb-serial-non-blocking
"""
import time
import board
import neopixel
# Create the NeoPixel object
pixel = neopixel.NeoPixel(board.NEOPIXEL,
1,
pixel_order=neopixel.GRB)
pixel[0] = (0, 0, 0)
neo = [0, 0, 150]
def rotNeopixel():
pixel[0] = (neo[0], neo[1], neo[2])
neo.insert(0, neo.pop())
class USBSerialReader:
""" Read a line from USB Serial (up to end_char), non-blocking, with optional echo """
def __init__(self):
self.s = ''
def read(self,end_char='\n', echo=True):
import sys, supervisor
n = supervisor.runtime.serial_bytes_available
if n > 0: # we got bytes!
s = sys.stdin.read(n) # actually read it in
if echo: sys.stdout.write(s) # echo back to human
self.s = self.s + s # keep building the string up
if s.endswith(end_char): # got our end_char!
rstr = self.s # save for return
self.s = '' # reset str to beginning
return rstr
return None # no end_char yet
usb_reader = USBSerialReader()
print("type something and press the end_char")
last_time = time.monotonic()
while True:
mystr = usb_reader.read() # read until newline, echo back chars
#mystr = usb_reader.read(end_char='\t', echo=False) # trigger on tab, no echo
if mystr:
print("got:",mystr)
if time.monotonic() - last_time > 1: # every second
last_time = time.monotonic()
rotNeopixel()
read_key.py Read keys from USB Serial
"""
Read keys from USB Serial
https://github.com/todbot/circuitpython-tricks#read-keys-from-usb-serial
"""
import time, sys, supervisor
import board
import neopixel
# Create the NeoPixel object
pixel = neopixel.NeoPixel(board.NEOPIXEL,
1,
pixel_order=neopixel.GRB)
pixel[0] = (0, 0, 0)
neo = [0, 0, 150]
def rotNeopixel():
pixel[0] = (neo[0], neo[1], neo[2])
neo.insert(0, neo.pop())
print("type charactcers")
last_time = time.monotonic()
while True:
n = supervisor.runtime.serial_bytes_available
if n > 0: # we read something!
s = sys.stdin.read(n) # actually read it in
# print both text & hex version of recv'd chars (see control chars!)
print("got:", " ".join("{:s} {:02x}".format(c,ord(c)) for c in s))
if time.monotonic() - last_time > 1: # every second
last_time = time.monotonic()
rotNeopixel()
Comments
Post a Comment