I'm trying to get the UART to work but its buffer is so small, I can't even send 40 bytes at 460k baudrate, because only 35-37 actually get read.. And that is with reading without any delays in the loop except for merging the received bytes, which does indeed take longer than a single character (takes ~40us) but not longer than filling a 32 Byte buffer.. I'm a bit puzzled about this.. In my application I actually wait 10us if no data is available and read directly into a preallocated bytearray until the expected amount of bytes is received but still I can't receive all bytes!
When using 2 esp32 I could easily send 400 Bytes with a buffer of 256 Bytes.
So either I'm missing something crucial, or there is a bug somewhere?
I should add that I'm using the uart with the changes by @RobertHH to add a timeout and I use it with a timeout of 10.
Edit below, but summary is:
So somewhere in the UART implementation there must be some serious bugs and the uart is rather useless at the moment. It needs a very long delay on the sender/the uart line (>1ms) after a packet was sent/received to even return it to uart.read() and at that point it already received too much and its buffer probably drops characters. The delay might be due to uart.read() using a timeout implementation but even without that, uart is completely unreliable when receiving anything more than 30 Bytes.
Test script on the rp2:
Code: Select all
>>> uart = machine.UART(1, rx=machine.Pin(5), tx=machine.Pin(4), baudrate=460800, timeout=10)
>>> def test(t,t2):
... while True:
... recv=b''
... st=time.ticks_us()
... while time.ticks_diff(time.ticks_us(),st)<t:
... if uart.any():
... recv+=uart.read()
... else:
... time.sleep_us(t2)
... if len(recv)>0:
... print(recv,len(recv))
...
...
...
>>> test(10000,10)
Code: Select all
b'0123456789012345678901234567890123456' 37
b'012345678901234567890123456789012345' 36
b'01234567890123456789012345678901234' 35
b'0123456789012345678901234567890123456' 37
This test reveals something more interesting:
Code: Select all
>>> def test2(t,t2):
... while True:
... gc.collect()
... recv=b''
... read=[]
... st=time.ticks_us()
... while time.ticks_diff(time.ticks_us(),st)<t:
... if uart.any():
... rr=uart.read()
... recv+=rr
... read.append(len(rr))
... else:
... time.sleep_us(t2)
... if len(recv)>0:
... print(recv,len(recv),read)
...
...
...
>>> test2(10000,1)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 3, in test2
NameError: name 'gc' isn't defined
>>> import gc
>>> test2(10000,1)
b'012345678901234567890123456789012345678' 39 [39]
b'012345678901234567890123456789012345' 36 [36]
b'0123456789012345678901234567890123456789' 40 [40]
b'01234567890123456789012345678901' 32 [32]
b'01234567890123456789012345678901' 32 [32]
b'01234567890123456789012345678901' 32 [32]
b'012345678901234567890123456789012345' 36 [36]
b'01234567890123456789012345678901234512345678901234567890123456789' 65 [65]
b'01234567890123456789012345678901234512345678901234567890123456789' 65 [65]
b'0123456789012345678901234567890156789012345678901234567890123456784567890123456789012345678901234562345678901234567890123456789012349012345678901234567890123456789017890123456789012345678901234567894567890123456789012345678901234562345678901234567890123456789012349012345678901234567890123456789012349012345678901234567890123456789017890123456789012345678901234567894567890123456789012345678901234562345678901234567890123456789012349012345678901234567890123456789016789012345678901234567890123456784567890123456789012345678901234561234567890123456789012345678901234012345678901234567890123456789012789012345678901234567890123456789456789012345678901234567890123456234567890123456789012345678901234901234567890123456789012345678901789012345678901234567890123456789456789012345678901234567890123456234567890123456789012345678901234012345678901234567890123456789012789012345678901234567890123456789' 895 [895]
It gets even more interesting, I can introduce a delay on the sender between the first 20 Bytes and the 2nd 20 Bytes to send 40 Bytes in total and even with a delay of 500us between them, the rp2 still misses characters and reads from the uart in a single operation!
On the sender:
Code: Select all
a=b'0123456789'
uart.write(a*2);time.sleep_us(500);uart.write(a*2)
Code: Select all
b'01234567890123456789012345678901' 32 [32]
b'012345678901234567890123456789012345' 36 [36]
b'01234567890123456789012345678901' 32 [32]
b'0123456789012345678901234567890123456789' 40 [40]
b'012345678901234567890123456789012345' 36 [36]
b'012345678901234567890123456789012345' 36 [36]
b'012345678901234567890123456789012345' 36 [36]
b'01234567890123456789012345678901' 32 [32]
b'01234567890123456789012345678901' 32 [32]
b'012345678901234567890123456789012345789' 39 [39]
b'012345678901234567890123456789012345689' 39 [39]
b'012345678901234567890123456789012345689' 39 [39]
b'0123456789012345678901234567890123456789' 40 [40]
b'0123456789012345678901234567890123456789' 40 [40]
b'01234567890123456789012345678901' 32 [32]
b'0123456789012345678901234567890123456789' 40 [40]
Now comparison to using the uart without a timeout:
Sending with a delay works fine (most of the time) for 40 Bytes (so maybe a problem with the timeout implementation?), even though the often get read within one operation which does not make sense with a 500us delay. When sending 2x30Bytes it sometimes works and I get 60 Bytes in a single read, sometimes only 32 Bytes:
Code: Select all
b'01234567890123456789012345678901' 32 [32]
b'012345678901234567890123456789012345678901234567890123456789' 60 [60]
b'012345678901234567890123456789012345678901234567890123456789' 60 [60]
b'01234567890123456789012345678901' 32 [32]
b'012345678901234567890123456789012345678901234567890123456789' 60 [60]
Code: Select all
b'012345678901234567890123456789012345678901234567890123456789' 60 [30, 30]
b'012345678901234567890123456789012345678901234567890123456789' 60 [30, 30]
b'012345678901234567890123456789012345678901234567890123456789' 60 [30, 30]
b'012345678901234567890123456789012345678901234567890123456789' 60 [30, 30]
But don't try to send more than the buffer in a single operation without sufficient delay between sends and it will mess up the data again..
So somewhere in the UART implementation there must be some serious bugs and the uart is rather useless at the moment. It needs a very long delay on the sender/the uart line (>1ms) after a packet was sent/received to even return it to uart.read() and at that point it already received too much and its buffer probably drops characters. The delay might be due to uart.read() using a timeout implementation but even without that, uart is completely unreliable when receiving anything more than 30 Bytes.
I have yet to compare this behaviour with my esp32s but this seems rather very wrong to me.. Didn't test it this thorougly on my esp32s because I had no problem sending 400 Bytes between them, which was fine for my case.