Halting on empty uart buffer

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
Speedbrid620
Posts: 5
Joined: Thu Dec 31, 2020 3:17 pm

Halting on empty uart buffer

Post by Speedbrid620 » Tue Feb 16, 2021 10:00 pm

I have been considering switching from PyBoard to Raspberry Pi Pico and I thought I should do some tests. But I almost instantly ran into a problem that I cant solve.

I am reading from two serial ports and combine the two data streams into a third, so I want to read the two uarts on the Pico. The problem is that as long as the uarts is receiving data continuously everything works fine. But when one of the sources stops feeding data the Pico is waiting to get data. It will simply not continue exacting the next line of code.

Executing the (almost) same code on my PyBoard it works flawlessly. Any suggestions?

Code: Select all

from machine import UART
import time

u0 = UART(0, baudrate=38400)					#Pi Pico
#u0 = UART(2, 38400)						#PyBoard 1.1
#u0.init(38400, bits=8, parity=None, stop=1, rxbuf=512)		#PyBoard 1.1

u1 = UART(1, baudrate=38400)					#Pi Pico
#u1 = UART(4, 38400)						#PyBoard 1.1
#u1.init(38400, bits=8, parity=None, stop=1, rxbuf=512)		#PyBoard 1.1


while True:

    if u0.any() > 0:
        x = u0.readline()
        print(x)

    if u1.any() > 0:
        y = u1.readline()
        print(y)

User avatar
dhylands
Posts: 3599
Joined: Mon Jan 06, 2014 6:08 pm
Location: Peachland, BC, Canada
Contact:

Re: Halting on empty uart buffer

Post by dhylands » Tue Feb 16, 2021 10:55 pm

I think that the issue is that the timeout feature isn't currently implemented for the rp2040 UARTs.

There is a PR which adds this functionality: https://github.com/micropython/micropython/pull/6870

In the meantime, you can use the UART.any() method to query if any characters are available.

This means that you need to read the UART one character at a time (i.e. use UART.read(1) and not readline()), but I've found that's the best way anyways.

Speedbrid620
Posts: 5
Joined: Thu Dec 31, 2020 3:17 pm

Re: Halting on empty uart buffer

Post by Speedbrid620 » Thu Feb 18, 2021 1:18 pm

Thanks Dave, it worked fine.

Code: Select all

from machine import UART
import time

u0 = UART(0, baudrate=115200, bits=8, parity=None, stop=1)
u1 = UART(1, baudrate=115200, bits=8, parity=None, stop=1)

while True:

    x = ""
    while u0.any():
        z = u0.read(1).decode()
        x = x + z

    y = ""
    while u1.any():
        z = u1.read(1).decode()
        y = y + z

    if len(x) > 1:
        print("u0: " + x)

    if len(y) > 1:
        print("u1: " + x)
However, the output seems a bit short. The string (MAVLINK-protocol) is a bit longer.

Code: Select all

u0: #S:1.4,,,16,,,48D
#A:4ACAA1,1F00,SAS003.154,AA0A,5.1138,

u1: #S:1.4,,,16,,,48D
#A:4ACAA1,1F00,SAS003.154,AA0A,5.1138,
The PyBoard can the UART buffer be expanded. I cant find that option for the RPi Pico.

User avatar
dhylands
Posts: 3599
Joined: Mon Jan 06, 2014 6:08 pm
Location: Peachland, BC, Canada
Contact:

Re: Halting on empty uart buffer

Post by dhylands » Thu Feb 18, 2021 4:24 pm

Yeah - looking at the source I don't see any rxbuf option for pico.

Do you see the same results if you only read from a single UART? I would expect at a baud rate of 38400 (which has a character time of around 260 usec) that micropython should be able to keep up with reading a single UART.

You can also reduce the memory allocations by using readinto to read into a previously allocated buffer. This means you need to keep an index of where you are, but it eliminates all of the allocations caused by doing x = x + z (Calling read also causes an allocation each time its called).

Post Reply