Page 1 of 1

Halting on empty uart buffer

Posted: Tue Feb 16, 2021 10:00 pm
by Speedbrid620
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)

Re: Halting on empty uart buffer

Posted: Tue Feb 16, 2021 10:55 pm
by dhylands
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.

Re: Halting on empty uart buffer

Posted: Thu Feb 18, 2021 1:18 pm
by Speedbrid620
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.

Re: Halting on empty uart buffer

Posted: Thu Feb 18, 2021 4:24 pm
by dhylands
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).