UART not working anymore in current version

All ESP8266 boards running MicroPython.
Official boards are the Adafruit Huzzah and Feather boards.
Target audience: MicroPython users with an ESP8266 board.
Post Reply
crizeo
Posts: 42
Joined: Sun Aug 06, 2017 12:55 pm
Location: Germany

UART not working anymore in current version

Post by crizeo » Thu Jun 21, 2018 4:25 pm

Does anyone know what they changed in the UART class so it doesn't work correctly anymore?

In version 1.9.3 I could simply read and write data but in the current version, I am losing the last byte on RX all the time... So when I expect 20 bytes as an example, I can read 19 without any problems but an timeout occurs when I try to read the 20th...

Edit: They added the possibility to change UART0. A great feature that I would need, but unfortunately UART does not work at all with this, so I will stay with older versions, although I can't disable the REPL there.


Update: At least found a way to use UART0 not for the REPLas described in other posts. I now also know how to return to the REPL so that you can use UART0 for any device at any baudrate and when an exception is thrown, you will see it on the REPL. You'll have to define a variable uart0 = UART(0, 115200) (any baudrate you like). In main() you'll have to reinit uart0 for your device using uart0.init(10400) (e.g. when you need baudrate 10400). The function calling main looks like this:

Code: Select all

if __name__ == '__main__':
    # dupterm(None)  # disable output/input on WebREPL
    # dupterm(None, 1)  # disable REPL (v1.9.4)

    ex = None
    try:
        main()
    except Exception as e:
        ex = e  # save exception that happend in my program using UART0

    uart0.init(115200, bits=8, parity=None, stop=1)  # so that it fits REPL again

    if ex is not None:
        raise ex  # show the exception on REPL

    # dupterm(uart0)  # enable WebREPL
    # dupterm(uart0, 1)  # enable REPL (v1.9.4)

Damien
Site Admin
Posts: 623
Joined: Mon Dec 09, 2013 5:02 pm

Re: UART not working anymore in current version

Post by Damien » Tue Jun 26, 2018 12:46 pm

In version 1.9.3 I could simply read and write data but in the current version, I am losing the last byte on RX all the time...
Are you able to provide some test code which shows this issue? If it's a bug then it should be fixed ASAP.

Damien
Site Admin
Posts: 623
Joined: Mon Dec 09, 2013 5:02 pm

Re: UART not working anymore in current version

Post by Damien » Thu Jun 28, 2018 3:15 am

Ok, I see the problem here: the new UART code has a 16-byte ring buffer when disconnected from the REPL. So it can buffer at most 15 bytes. You can increase this value manually in the C code, line 39 of ports/esp8266/uart.c (static byte uart_ringbuf_array[16]). But it would be better to allow to configure this value dynamically.

crizeo
Posts: 42
Joined: Sun Aug 06, 2017 12:55 pm
Location: Germany

Re: UART not working anymore in current version

Post by crizeo » Sun Jul 15, 2018 6:48 pm

Thanks for the hint!

I changed the size of uart_ringbuf_array to 256, as this seems to be the value in the previous version (where the buffer is called input_buf). Additionally I disabled interrupts (as I did in the previous version) by commenting the lines 180 to 188, apart from:

Code: Select all

ringbuf_put(&uart_ringbuf, RcvChar)
All I want to do is continously reading and writing to UART0 (no webrepl, no stdin, just UART to another device). Unfortunately, this does not work.

Do you have other ideas what I could try? Thanks!

crizeo
Posts: 42
Joined: Sun Aug 06, 2017 12:55 pm
Location: Germany

Re: UART not working anymore in current version

Post by crizeo » Wed Aug 07, 2019 8:42 pm

Today I wanted to upgrade to version 1.11, but unfortunately the problem still exists. I am currently using MicroPython v1.9.4-29-g1b7487e, where I modified uart.c minimally, so that the "CTRL+C"-byte does not cause an interrupt.

My objective: ESP8266 talking to another device using UART (REPL and WebREPL are not required).

Minimal example code:

Code: Select all

import machine
import utime
import uasyncio

uart = machine.UART(0, 115200)
uart.init(10400, timeout=800, bits=8, parity=None, stop=1)


# Read and return <n> bytes from UART. Exception on timeout.
async def uread(n):
    r = b''
    while n > 0:  # read byte by byte since read() is blocking
        tmr = utime.ticks_ms()
        while not uart.any():  # any() returns 0 or 1 (not the amount)
            if utime.ticks_diff(utime.ticks_ms(), tmr) > 800:
                raise Exception("UART timeout")
            await uasyncio.sleep_ms(0)
        r += uart.read(1)
        n -= 1
    return r


async def uwrite(msg):
    await uasyncio.sleep_ms(25)  # prevent too fast writing
    uart.write(msg)


async def main():
    # setup K-line:
    tx = machine.Pin(1, machine.Pin.OUT)
    tx(0)
    utime.sleep_ms(70)
    tx(1)
    await uasyncio.sleep_ms(130)

    # send UART message:
    uart.read()  # clear RX buffer
    await uwrite(bytes((0x72, 0x05, 0x00, 0xF0, 0x99)))
    echo = await uread(5)  # clear echo (since k-line is single-wire half-duplex)

    # retrieve device response:
    rType = await uread(1)  # =====> EXCEPTION: UART timeout <======
    # [... some more response bytes ...]


loop = uasyncio.get_event_loop()
loop.run_until_complete(main())
The issue: This code works fine in v1.9.4, whereelse in v1.11 an UART timeout occurs when trying to read the device response. Do you have an idea, what changed from v1.9.3/1.9.4 to later versions in the UART module (or uasyncio?) that could cause this issue?

schwinnez
Posts: 5
Joined: Sun Apr 22, 2018 12:19 pm

Re: UART not working anymore in current version

Post by schwinnez » Tue Oct 22, 2019 10:30 am

Any updates on this?
For me, using MicroPython 1.11 reading from UART 0 is also not working (ESP8266). Writing works fine.
I am (also) reading from serial in a coroutine (if this might be a cause of the issue?).

schwinnez
Posts: 5
Joined: Sun Apr 22, 2018 12:19 pm

Re: UART not working anymore in current version

Post by schwinnez » Tue Oct 22, 2019 8:52 pm

Okay, just realized, that since 1.10, one needs to detach the REPL explicitly.

Code: Select all

uos.dupterm(None, 1)
https://github.com/micropython/micropyt ... fbc4cd0c03

Actually, I am wondering, why this change has been made. Previously "print" message were seen in a serial monitor. I used this a lot for debugging purposes (of course it might not be the cleanest thing to do;-)). Is it just to be more "clean" here or are there any reasons that i don't see yet?

Post Reply