uasyncio StreamReader .readline() blocking

RP2040 based microcontroller boards running MicroPython.
Target audience: MicroPython users with an RP2040 boards.
This does not include conventional Linux-based Raspberry Pi boards.
Post Reply
chaley
Posts: 4
Joined: Fri Mar 05, 2021 8:35 pm

uasyncio StreamReader .readline() blocking

Post by chaley » Fri Mar 05, 2021 8:45 pm

I'm currently trying to get sreader.readline() working but as soon as I put an input it stops outputting `Hello uart` and blocks, I have to then restart the device.

I'm not exactly sure what's happening here or if this is an issue with the rp2040 (I have some ESP modules I can test on?)

Code: Select all

from machine import Pin,  UART
import uasyncio

uart = UART(0, 9600, parity=None, stop=1, bits=8, rx=Pin(13), tx=Pin(12))

async def sender():
    swriter = uasyncio.StreamWriter(uart, {})
    while True:
        await swriter.awrite('Hello uart\n')
        await uasyncio.sleep(2)

async def receiver():
    sreader = uasyncio.StreamReader(uart)
    while True:
        res = await sreader.readline()
        print('Recieved', res)

loop = uasyncio.get_event_loop()
loop.create_task(sender())
loop.create_task(receiver())
loop.run_forever()

kevinkk525
Posts: 969
Joined: Sat Feb 03, 2018 7:02 pm

Re: uasyncio StreamReader .readline() blocking

Post by kevinkk525 » Sat Mar 06, 2021 9:02 am

I can't reproduce this issue.
I used the following code to receiving messages while at the same time sending messages. However, I used the uart 1, you use uart 0. Maybe that's the problem because if I'm correct, uart 0 is the same uart used for the repl?

Code: Select all

uart = machine.UART(1, rx=machine.Pin(5), tx=machine.Pin(4), baudrate=460800)  # , timeout=10)
suart = asyncio.StreamReader(uart)

async def test2async(t):
    while True:
        gc.collect()
        recv = b''
        read = []
        st = time.ticks_us()
        while time.ticks_diff(time.ticks_us(), st) < t:
            rr = await suart.read(1000)
            recv += rr
            read.append(len(rr))
        if len(recv) > 0:
            print(recv, len(recv), read)


async def busy():
    while True:
        print(time.ticks_ms(), "busy")
        await asyncio.sleep(1)
        await suart.awrite(b'hi there')


print("Started")
asyncio.create_task(busy())
asyncio.run(test2async(10000))
Kevin Köck
Micropython Smarthome Firmware (with Home-Assistant integration): https://github.com/kevinkk525/pysmartnode

chaley
Posts: 4
Joined: Fri Mar 05, 2021 8:35 pm

Re: uasyncio StreamReader .readline() blocking

Post by chaley » Sat Mar 06, 2021 8:56 pm

kevinkk525 wrote:
Sat Mar 06, 2021 9:02 am
I can't reproduce this issue.
I used the following code to receiving messages while at the same time sending messages. However, I used the uart 1, you use uart 0. Maybe that's the problem because if I'm correct, uart 0 is the same uart used for the repl?
Hmm, I tried switching to UART1 and pins 4/5 like you have above and I get the same issue, it also blocks the REPL output (as well as UART) as soon as a I enter a char.

Interestingly I put your code on my Pico and a similar thing happened. It ran for a bit, then locked up after a few seconds.

REPL:

Code: Select all

Connecting to COM9...
2079 busy
3081 busy
Serial:

Code: Select all

hi therehi therehi there
My next plan of action will be try a different Pico

kevinkk525
Posts: 969
Joined: Sat Feb 03, 2018 7:02 pm

Re: uasyncio StreamReader .readline() blocking

Post by kevinkk525 » Sat Mar 06, 2021 9:51 pm

are you using a daily firmware?
Kevin Köck
Micropython Smarthome Firmware (with Home-Assistant integration): https://github.com/kevinkk525/pysmartnode

chaley
Posts: 4
Joined: Fri Mar 05, 2021 8:35 pm

Re: uasyncio StreamReader .readline() blocking

Post by chaley » Sun Mar 07, 2021 2:02 pm

kevinkk525 wrote:
Sat Mar 06, 2021 9:51 pm
are you using a daily firmware?
Nope, I'm using v1.14 from the MicroPython website. I just tried a brand new Pico, I didn't hook up UART I just flashed it and looked at the REPL output. Again, it just seems to lock up, I tried on my Windows machine using the Pico-Go vscode extension and on my laptop just using rshell -p /dev/ttyACM0 --buffer-size 512 repl

This is the exact code I'm running

Code: Select all

from machine import Pin,  UART
import time
import gc
import uasyncio as asyncio

uart = machine.UART(1, rx=machine.Pin(5), tx=machine.Pin(4), baudrate=9600)  # , timeout=10)
suart = asyncio.StreamReader(uart)

async def test2async(t):
    while True:
        gc.collect()
        recv = b''
        read = []
        st = time.ticks_us()
        while time.ticks_diff(time.ticks_us(), st) < t:
            rr = await suart.read(1000)
            recv += rr
            read.append(len(rr))
        if len(recv) > 0:
            print(recv, len(recv), read)


async def busy():
    while True:
        print(time.ticks_ms(), "busy")
        await asyncio.sleep(1)
        await suart.awrite(b'hi there')


print("Started")
asyncio.create_task(busy())
asyncio.run(test2async(10000))

User avatar
pythoncoder
Posts: 5956
Joined: Fri Jul 18, 2014 8:01 am
Location: UK
Contact:

Re: uasyncio StreamReader .readline() blocking

Post by pythoncoder » Sun Mar 07, 2021 2:20 pm

I think this is yet another instance of this issue.

On some PC's the Pico stops issuing text on the USB interface if it runs a script which only produces output at a low rate. The problem goes away if you increase the rate. I added a count so I could check it was running when the output had filled the window. Increasing the rate to 2Hz "fixed" the problem.

Code: Select all

from machine import Pin,  UART
import uasyncio

uart = UART(0, 9600, parity=None, stop=1, bits=8)

async def sender():
    count = 0
    swriter = uasyncio.StreamWriter(uart, {})
    while True:
        await swriter.awrite('Hello uart {}\n'.format(count))
        count += 1
        await uasyncio.sleep(0.5)  # This made the problem go away

async def receiver():
    sreader = uasyncio.StreamReader(uart)
    while True:
        res = await sreader.readline()
        print('Recieved', res)

loop = uasyncio.get_event_loop()
loop.create_task(sender())
loop.create_task(receiver())
loop.run_forever()
The problem is with the USB interface rather than the UART (which has other issues).
[EDIT]
The above script stalled after a few messages at a 2 second rate. At a 2Hz rate it was still running after 5000 messages.
Peter Hinch
Index to my micropython libraries.

chaley
Posts: 4
Joined: Fri Mar 05, 2021 8:35 pm

Re: uasyncio StreamReader .readline() blocking

Post by chaley » Sun Mar 07, 2021 5:52 pm

pythoncoder wrote:
Sun Mar 07, 2021 2:20 pm
The above script stalled after a few messages at a 2 second rate. At a 2Hz rate it was still running after 5000 messages.
Okay that works and doesn't stall for me, although PuTTY also seems to be just sending a CR on the serial port so that's why `readline()` was blocking, as soon as I manually send an LF over (Ctrl + J) it outputs.

Post Reply