Page 1 of 1

UART not working anymore in current version

Posted: Thu Jun 21, 2018 4:25 pm
by crizeo
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)

Re: UART not working anymore in current version

Posted: Tue Jun 26, 2018 12:46 pm
by Damien
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.

Re: UART not working anymore in current version

Posted: Thu Jun 28, 2018 3:15 am
by Damien
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.

Re: UART not working anymore in current version

Posted: Sun Jul 15, 2018 6:48 pm
by crizeo
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!

Re: UART not working anymore in current version

Posted: Wed Aug 07, 2019 8:42 pm
by crizeo
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?