UART not working with today's version of micropython

RP2040 based microcontroller boards running MicroPython.
Target audience: MicroPython users with an RP2040 boards.
This does not include conventional Linux-based Raspberry Pi boards.
Tinus
Posts: 40
Joined: Sun Feb 14, 2021 4:53 pm

UART not working with today's version of micropython

Post by Tinus » Wed Apr 14, 2021 12:40 pm

I tried todays version of micropython for the pico but my code doesn't work anymore.

I am communicating between the pi and an ESP32 and where before I was able to send lines of text from the ESP to the pico I no only receive the last few characters.

before I would receive

Code: Select all

heartrate=64\r\n
but now I only get:

Code: Select all

ate=64\r\n
when I do readline()

I understand that something has changed in the UART code, can somebody tell me what I have to change to be able to get full lines of text over serial in this new version?

Thanks

Tinus
Posts: 40
Joined: Sun Feb 14, 2021 4:53 pm

Re: UART not working with today's version of micropython

Post by Tinus » Wed Apr 14, 2021 1:45 pm

This is the code I have been using:

Code: Select all

class MyHr:
    hr = 0
    uart = None
    
    def __init__(self, TXPinNr=12, RXPinNr=13):
        self.uart = UART(0, 9600 , parity=None, stop=1, bits=8, tx=Pin(TXPinNr), rx=Pin(RXPinNr))
    
    def read(self):
        if (self.uart.any()):
            raw = self.uart.readline()
            strRaw = raw.decode().replace('\r\n','')
            if (strRaw.find('heartrate=')==0):
                try:
                    self.hr = int(strRaw.replace('heartrate=',''))
                except ValueError:
                    pass
        return self.hr

User avatar
Roberthh
Posts: 2639
Joined: Sat May 09, 2015 4:13 pm
Location: Rhineland, Europe

Re: UART not working with today's version of micropython

Post by Roberthh » Wed Apr 14, 2021 2:48 pm

Does that happen for every message or just the first one?

Tinus
Posts: 40
Joined: Sun Feb 14, 2021 4:53 pm

Re: UART not working with today's version of micropython

Post by Tinus » Wed Apr 14, 2021 2:52 pm

All of them

User avatar
Roberthh
Posts: 2639
Joined: Sat May 09, 2015 4:13 pm
Location: Rhineland, Europe

Re: UART not working with today's version of micropython

Post by Roberthh » Wed Apr 14, 2021 3:06 pm

OK. I could replicate that. You have to add a small timeout to the init, like:

self.uart = UART(0, 9600 , parity=None, stop=1, bits=8, tx=Pin(TXPinNr), rx=Pin(RXPinNr), timeout=10)

The difference: before the change, UART was blocking. Now it is non-blocking like in all other ports.
Edit: See also the documentation at https://docs.micropython.org/en/latest/ ... chine.UART
Read a line, ending in a newline character. It may return sooner if a timeout is reached. The timeout is configurable in the constructor.

Tinus
Posts: 40
Joined: Sun Feb 14, 2021 4:53 pm

Re: UART not working with today's version of micropython

Post by Tinus » Wed Apr 14, 2021 4:20 pm

Oh super,

Thank you very much.

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

Re: UART not working with today's version of micropython

Post by kevinkk525 » Thu Apr 15, 2021 5:20 am

Maybe I'm missing something but my understanding is, that if anything should be missing, it's the end of the message, not the start? Wh, would "heart" disappear?
Apart from that I never used readline() but would expect it to only return something when it had a full line (otherwise returning none?). How do other ports handle that?
Kevin Köck
Micropython Smarthome Firmware (with Home-Assistant integration): https://github.com/kevinkk525/pysmartnode

User avatar
Roberthh
Posts: 2639
Joined: Sat May 09, 2015 4:13 pm
Location: Rhineland, Europe

Re: UART not working with today's version of micropython

Post by Roberthh » Thu Apr 15, 2021 6:47 am

All ports handle it the same way, and there is a note in the documentation (!) that uart.readline() may return a partial line, if timeout is not set. Why the error happens here is not clear, because uart.readline() is called only after uart.any() flags presence of data. So even if it is not an undocumented behavior, it is something worth to be analyzed.

Tinus
Posts: 40
Joined: Sun Feb 14, 2021 4:53 pm

Re: UART not working with today's version of micropython

Post by Tinus » Thu Apr 15, 2021 11:19 am

The timeout works for the readline().

I am also seeing some strange behaviour on the write().
I am sending commands to a Nextion display like this:

Code: Select all

 def send(self, command):
        write_buffer = bytearray(len(command) + 3)
        write_buffer[0: len(command)] = bytes(command, 'ASCII')
        write_buffer[-3:] = b'\xff\xff\xff'
        self.uart.write(write_buffer)
Before this worked flawlessly but now starnge things happen on the display. This is extra weird because the display usually just ignores any command it doesn't understand.

I am repeatedly sending commands like this:

page1.gSpeed.val=9

on a loop with a sleep(0.1)

Every other second (more or less) the display apears to receive messages like:

page1.gSpeed.val=99

the same occurs for other fields. I have tried changing the timeouts but that doesn't change anything.
I can't get my head around how the numbers get duplicated At first I thought it was just the last digit that is repeated but that makes no sense since that is not the last character sent, there is always the appended b'\xff\xff\xff' to end the command.
Then I also noticed larger numbers getting doubled up occasionally.

page1.gDistance.val=812

occasionally results in the display showing 812812

User avatar
Roberthh
Posts: 2639
Joined: Sat May 09, 2015 4:13 pm
Location: Rhineland, Europe

Re: UART not working with today's version of micropython

Post by Roberthh » Thu Apr 15, 2021 11:45 am

That seems to be a different topic. Timeout does/should not affect write.
In a simple test of sending that data to the screen I could not replicate that. It should however be considered, that uart.write() is too not blocking any more. As long as the message is shorter than the buffer size, it returns immediately. The default buffer size is 256, the minimal size is 32 (set with txbuf=nnn). So calling uart.write() again before the message actually has been transmitted will shorten the time gap between two transmissions. That may lead to an overrun in the receiver.
You could try to set txbuf to 32, which is the hardware FIFO size. Then uart.write() should behave as before.

Post Reply