Open hitecSmartHome opened 2 weeks ago
So the esp pulls the pin low after so much time that the response data is already coming. It can be because the slaves response time is really low.
Yep that remark you made before made me realize this could be what's causing this...
The slave response packet is already assembled by the time it receives a request and it sends as soon as it can so... I have to make the rts pin quicker. Maybe if I do not call Serial1.setPins(-1, -1, -1, MBUS_RTS);
and I controll the pin it will be better. But I don't know when the data actually sent, I just put the data into the serial buffer. :/
That is why I suggested to pull the /RE down and enable 'collision detection', so you essentially always listen.
I wonder what @SuGlider thinks about this
Just to summarize my hypothesis, so he doesn't have to read 50+ messages ;)
Remember, this is just an idea I got, no idea if it is the real cause. When the error occurs under some kind of load, then the "hardware" handling of the RTS pin is essentially done in software. If it is actually done in "hardware", then the load of the ESP should have nothing to do with this.
On some request ( with long response data ) the last byte is truncated and I got two crc errors
// CRC ERROR
E (11153) Modbus: CRC error in response packet: 0x03
CRC error raw packet: : 03 03 20 00 05 00 00 00 04 00 00 00 04 00 00 00 04 00 00 00 03 00 00 00 02 00 00 00 03 00 00 00 02 00 00 fe
E (11159) Modbus: Invalid packet. Can't process it.
MODBUS INVALID PACKET: 03 03 20 00 05 00 00 00 04 00 00 00 04 00 00 00 04 00 00 00 03 00 00 00 02 00 00 00 03 00 00 00 02 00 00 fe
E (11176) HardwareHandler: Packet error code: 1
// ERROR PARSING
E (11182) Expander: M8 new rele info read error. Last modbus error: 1
// CRC ERROR in the next packet
E (11195) Modbus: CRC error in response packet: 0x89
CRC error raw packet: : 89
E (11197) Modbus: Invalid packet. Can't process it.
MODBUS INVALID PACKET: 89
E (11205) HardwareHandler: Packet error code: 1
E (11210) HardwareHandler: (Packet error handler) Expander not found 0x89
Fist I got a packet 03 03 20 00 05 00 00 00 04 00 00 00 04 00 00 00 04 00 00 00 03 00 00 00 02 00 00 00 03 00 00 00 02 00 00 fe
with missing last byte. This resulted in a CRC error.
Than I got an other packet which is the last packet last byte 89
this also resulted in a CRC error.
I don't know what truncates the packets. ESP won't send another packet until the last one is processed so it can't switch the rs485 chip to transmit mode.
But these packets are the best
E (301443) Modbus: CRC error in response packet: 0x00
CRC error raw packet: : 00
E (301444) Modbus: Invalid packet. Can't process it.
MODBUS INVALID PACKET: 00
E (301449) HardwareHandler: Packet error code: 1
Does handleReceiveError()
get any BREAK error?
I know that when UART IDF Driver gets BREAK, it breaks the way how the driver works and it could create 2 separated calls for onReceive()
.
Other than that, I can't imagine a good reason for this package splitting issue.
E (7572) uart: tout_thresh = 12 > maximum value = 1
yeap... just check it in the IDF code. ESP32 has a limit which is 15/symbol_length ==> 15/10 = 1.
Other ESP32 (S2/S3/C3 etc) have not such limitation.
For SERIAL_8N1
maximum RX Timeout is always 1 symbol.
But these packets are the best
E (301443) Modbus: CRC error in response packet: 0x00 CRC error raw packet: : 00 E (301444) Modbus: Invalid packet. Can't process it. MODBUS INVALID PACKET: 00 E (301449) HardwareHandler: Packet error code: 1
This error sounds like receiving an UART BREAK.
You can test break receiving using the uart loopback as in the https://github.com/espressif/arduino-esp32/blob/master/libraries/ESP32/examples/Serial/OnReceiveError_BREAK_Demo/OnReceiveError_BREAK_Demo.ino example.
UART BREAK causes different behaviour when using onReceive()
and onReceiveError()
@hitecSmartHome - Could you try running your project with BREAK disabled:
#include "driver/uart.h"
#include "hal/uart_hal.h"
void Modbus::init() {
Serial1.setRxBufferSize(MAX_RX_BUFFER_SIZE);
Serial1.setTxBufferSize(MAX_MBUS_DATA_LENGTH);
Serial1.begin(MBUS_BAUD, SERIAL_8N1, MBUS_RX, MBUS_TX);
Serial1.setPins(-1, -1, -1, MBUS_RTS);
Serial1.setMode(UART_MODE_RS485_HALF_DUPLEX);
Serial1.setRxTimeout(MBUS_RX_TIMEOUT);
uart_disable_intr_mask((uart_port_t) 1, UART_INTR_BRK_DET); // disable Serial1 BREAK INT
Serial1.onReceive(
std::bind(&Modbus::handlePacket, this),
PACKET_TRIGGER_ONLY_ON_TIMEOUT
);
Serial1.onReceiveError(
std::bind(&Modbus::handleReceiveError, this, std::placeholders::_1)
);
}
running the BREAK receive example I can see that receiving BREAK will add 0x00 to the received payload...
It is possible to write uart using break for testing (using IDF functions): int uart_write_bytes_with_break(uart_port_tuart_num, const void *src, size_t size, int brk_len)
// Write data to UART, end with a break signal with 100 uart bits baud rate length
uart_write_bytes_with_break(uart_num, "test break\n",strlen("test break\n"), 100);
Oh god i hope it is as simple as that.
Tomorrow I can test it. I dont know if i got break because i specifically do not print or log errors related to break because i got a lot of that in prev versions and it was annoying. Ofc there is a break because it has to be.
Will check it for sure thank you very much.
It may not be "so simple as that".
Looking into that, I just guess that the issue may be related to a BREAK detection and UART adding 0x00 to the FIFO.
BREAK also forces onReceive()
to be called.
It will require a lot of data analysis and checking the logs.
@hitecSmartHome -
Also sometimes there is a 0x00 at the first byte of the data which we do not see with an oscilloscope. That 0x00 sometimes there even with this 1ms delay after an onRecive callback.
00 0e 03 01 00 00 1c 45 should be 0e 03 01 00 00 1c 45 ( address, func code, reg num, data first, data second, crc, crc ) registers are 16 bit and sending two 8 bit data. But that 0x00 is mistery still.
This is consistent with a BREAK received in the beginning of the packet transmission. As side effect, it adds a 0x00 into FIFO when a BREAK is detected. This is the HW that adds it.
Unfortunatelly, disabling BREAK INT doesn't fix this extra 0x00.
Fixing it would require some sort of combination of detecting the BREAK and ignoring any "extra 0x00"... Using the BREAK receive example: 1- when BREAK is received at the end of the packet: (a) BREAK Error is detected and onReceiveError callback can see all the data + extra 0x00 at the end (b) onReceive callback gets an extra 0x00 is added at the end 2- when BREAK is received at the beginning of the packet: (a) BREAK Error is detected and onReceiveError callback no data (b) onReceive callback gets an extra 0x00 is added at the beginning of the packet.
The output below considers a FIFO Full as 120 bytes.
================================
Test Case #1 BREAK at END
================================
Testing onReceive for receiving 26 bytes at 115200 baud, using RX FIFO Full = 120.
onReceive is called on both FIFO Full and RX Timeout events.
BREAK event will be sent at the END of the 26 bytes
[ 678][V][HardwareSerial.cpp:276] _uartEventTask(): UART1 RX break.
-- onReceiveError [ERR#1:UART_BREAK_ERROR]
-- onReceiveError:: There are 27 bytes available.
onReceive Callback:: There are 27 bytes available: {0x41='A' 0x42='B' 0x43='C' 0x44='D' 0x45='E' 0x46='F' 0x47='G' 0x48='H' 0x49='I' 0x4a='J' 0x4b='K' 0x4c='L' 0x4d='M' 0x4e='N' 0x4f='O' 0x50='P' 0x51='Q' 0x52='R' 0x53='S' 0x54='T' 0x55='U' 0x56='V' 0x57='W' 0x58='X' 0x59='Y' 0x5a='Z' 0x0=''}
Sent String: ABCDEFGHIJKLMNOPQRSTUVWXYZ
It has sent 26 bytes from Serial1 TX to Serial1 RX
onReceive() has read a total of 27 bytes
================================
Test Case #1 BREAK at BEGINNING
================================
Testing onReceive for receiving 26 bytes at 115200 baud, using RX FIFO Full = 120.
onReceive is called on both FIFO Full and RX Timeout events.
BREAK event will be sent at the BEGINNING of the 26 bytes
[ 756][V][HardwareSerial.cpp:276] _uartEventTask(): UART1 RX break.
-- onReceiveError [ERR#1:UART_BREAK_ERROR]
-- onReceiveError:: There are 0 bytes available.
Sent String: ABCDEFGHIJKLMNOPQRSTUVWXYZ
onReceive Callback:: There are 27 bytes available: {0x0='' 0x41='A' 0x42='B' 0x43='C' 0x44='D' 0x45='E' 0x46='F' 0x47='G' 0x48='H' 0x49='I' 0x4a='J' 0x4b='K' 0x4c='L' 0x4d='M' 0x4e='N' 0x4f='O' 0x50='P' 0x51='Q' 0x52='R' 0x53='S' 0x54='T' 0x55='U' 0x56='V' 0x57='W' 0x58='X' 0x59='Y' 0x5a='Z'}
It has sent 26 bytes from Serial1 TX to Serial1 RX
onReceive() has read a total of 27 bytes
========================
Finished!
That is.... funny. So I need to listen to a break error and expect a 0x00 somewhere in the packet...
Break is not an error in this case. It should be there after every message since there is a packet timeout.
But why don't i get this extra byte every single time? And why is the uart acting and placing random bytes into the buffer in my behalf? Even on cases where it is an error, ( like streams ) it should not alter the buffer...
So In my testing
void Modbus::handleReceiveError(hardwareSerial_error_t error) {
if (error == UART_NO_ERROR) { return; }
ESP_LOGE(MBUS_DEBUG_TAG, "Packet error code: %d", error);
ESP_LOGE(MBUS_DEBUG_TAG, "Packet error description: %s", uartErrorStrings[error]);
if( error == UART_BREAK_ERROR ){ return; }
translateUartError(error);
callErrorCb(lastPacketError);
}
I get a BREAK_ERROR after every message.
E (376014) Modbus: Packet error code: 1
E (376018) Modbus: Packet error description: UART_BREAK_ERROR
E (376025) Modbus: Packet error code: 1
E (376029) Modbus: Packet error description: UART_BREAK_ERROR
E (376036) Modbus: Packet error code: 1
E (376040) Modbus: Packet error description: UART_BREAK_ERROR
E (376046) Modbus: Packet error code: 1
E (376051) Modbus: Packet error description: UART_BREAK_ERROR
E (376057) Modbus: Packet error code: 1
E (376061) Modbus: Packet error description: UART_BREAK_ERROR
E (376068) Modbus: Packet error code: 1
E (376072) Modbus: Packet error description: UART_BREAK_ERROR
This is consistent and comes after every packet and there are no 0x00
byte in my actual packets.
It does not split in half or anything.
Previously I had this error handler like this
void Modbus::handleReceiveError(hardwareSerial_error_t error) {
if (error == UART_NO_ERROR || error == UART_BREAK_ERROR) { return; }
ESP_LOGE(MBUS_DEBUG_TAG, "Packet error code: %d", error);
ESP_LOGE(MBUS_DEBUG_TAG, "Packet error description: %s", uartErrorStrings[error]);
translateUartError(error);
callErrorCb(lastPacketError);
}
So I ignored the BREAK_ERROR
since there is a break after every message as it should be.
What is the purpose of the onReceive
callback if the framework forces me to do my own packet framing because it is unreliable and useless? UART_BREAK
should not be an error in the case of UART_MODE_RS485_HALF_DUPLEX
because it will fire no matter what and it should not alter my receive buffer. Now I have to implement a workaround into my packet handler to check for single 0 bytes and check the first and last byte of my packet and continue to ignore BREAK
From this
void Modbus::handlePacket() {
int available = Serial1.available();
uint8_t rawPacket[available] = {0};
int readBytes = Serial1.readBytes(rawPacket, available);
if (!isPacketValid(rawPacket, readBytes)) {
ESP_LOGE(MBUS_DEBUG_TAG, "Invalid packet. Can't process it.");
utils.printRawPacket("MODBUS INVALID PACKET", rawPacket, readBytes);
callErrorCb(rawPacket[0]);
return;
}
parseScanPacket(rawPacket, readBytes);
if (packetCallback && !isScanning) {
packetCallback(rawPacket, readBytes);
}
}
I can workaround the 0x00 issue like this
void Modbus::handlePacket() {
int available = Serial1.available();
if (available <= 0) { return; }
uint8_t rawPacket[available] = {0};
int readBytes = Serial1.readBytes(rawPacket, available);
// Check and remove 0x00 at the start
int startIdx = 0;
if (rawPacket[0] == 0x00) {
ESP_LOGW(MBUS_DEBUG_TAG, "Detected 0x00 at start - removing.");
startIdx = 1; // Skip the first byte
}
// Check and remove 0x00 at the end
int endIdx = readBytes;
if (rawPacket[readBytes - 1] == 0x00) {
ESP_LOGW(MBUS_DEBUG_TAG, "Detected 0x00 at end - removing.");
endIdx = readBytes - 1; // Ignore the last byte
}
// Calculate the new length after trimming
int trimmedLength = endIdx - startIdx;
if (trimmedLength <= 0) {
ESP_LOGW(MBUS_DEBUG_TAG, "Packet length is zero after trimming - ignoring packet.");
return;
}
// Create a trimmed packet array if necessary
uint8_t trimmedPacket[trimmedLength];
memcpy(trimmedPacket, rawPacket + startIdx, trimmedLength);
if (!isPacketValid(trimmedPacket, trimmedLength)) {
ESP_LOGE(MBUS_DEBUG_TAG, "Invalid packet. Can't process it.");
utils.printRawPacket("MODBUS INVALID PACKET", trimmedPacket, trimmedLength);
callErrorCb(trimmedPacket[0]);
return;
}
parseScanPacket(trimmedPacket, trimmedLength);
if (packetCallback && !isScanning) {
packetCallback(trimmedPacket, trimmedLength);
}
}
This way I can detect single 0x00 or at the start or end but I still got truncated packets like this
E (11162) Modbus: CRC error in response packet: 0x03
CRC error raw packet: : 0x03 0x03 0x20 0x00 0x05 0x00 0x00 0x00 0x04 0x00 0x00 0x00 0x04 0x00 0x00 0x00 0x04 0x00 0x00 0x00 0x03 0x00 0x00 0x00 0x02 0x00 0x00 0x00 0x03 0x00 0x00 0x00 0x02 0x00 0x00 0xfe
E (11175) Modbus: Invalid packet. Can't process it.
MODBUS INVALID PACKET: 0x03 0x03 0x20 0x00 0x05 0x00 0x00 0x00 0x04 0x00 0x00 0x00 0x04 0x00 0x00 0x00 0x04 0x00 0x00 0x00 0x03 0x00 0x00 0x00 0x02 0x00 0x00 0x00 0x03 0x00 0x00 0x00 0x02 0x00 0x00 0xfe
E (11198) HardwareHandler: Packet error code: 1
E (11216) Modbus: CRC error in response packet: 0x89
CRC error raw packet: : 0x89
E (11219) Modbus: Invalid packet. Can't process it.
MODBUS INVALID PACKET: 0x89
E (11227) HardwareHandler: Packet error code: 1
The driver cuts the last byte of the frame and makes an other frame with it with an other callback...
This frame does not even overflow the buffer. This is 37 bytes and cuts the last byte.
0x03 0x03 0x20 0x00 0x05 0x00 0x00 0x00 0x04 0x00 0x00 0x00 0x04 0x00 0x00 0x00 0x04 0x00 0x00 0x00 0x03 0x00 0x00 0x00 0x02 0x00 0x00 0x00 0x03 0x00 0x00 0x00 0x02 0x00 0x00 0xfe 0x89
I must switch to interrupts handling and process the incoming bytes myself...
As you say, onReceive()
may not fit the application needs.
It works based on how IDF and the HW works, as described in https://github.com/espressif/arduino-esp32/issues/10578#issuecomment-2460210311
It may be usefull withSerial1.setRxFIFOFull(1);
in order to use an async callback for each single incomming byte.
Regarding the BREAK signal, this is how ESP32 HW works. If the BREAK is too long, it will add 0x00
to the UART RX FIFO.
Don't bother if BREAK is called error. This is just a denomination.
Thank you for your response and your help.
As you say, onReceive() may not fit the application needs.
What application would need a truncated/clipped frame provider callback?
Regarding the BREAK signal, this is how ESP32 HW works. If the BREAK is too long, it will add 0x00 to the UART RX FIFO.
Why?
Anyway, regarding the initial topic of this issue, there is no relationship between HTTP / Flash Accessing Tasks and the truncated UART packets.
What application would need a truncated/clipped frame provider callback?
onReceive()
is just a way to emulate an UART ISR (async callback). It can be configured to be used in different ways using Timeout or FIFO Full events.
Other possible application: an UART console.
Regarding the BREAK signal, this is how ESP32 HW works. If the BREAK is too long, it will add 0x00 to the UART RX FIFO. Why?
This is a question for the Espressif Digital Design team... I have no answer.
@hitecSmartHome - thinking about the BREAK = received 0x00:
What if used Parity is ODD instead of EVEN? 0x00 ==> Start Bit + DATA + Parity Bit + STOPBIT. BREAK is when ParityBit doesn't match the necessary STOPBIT which shall be HIGH when the Line is hold LOW.
But if Parity is ODD, Parity Bit should be 1 instead of 0. Therefore you may get a BREAK associated to a PARITY error instead of BREAK error... This may work in the sense of not adding 0x00 to FIFO.
Just guessing...
@hitecSmartHome - thinking about the BREAK = received 0x00:
What if used Parity is ODD instead of EVEN? 0x00 ==> Start Bit + DATA + Parity Bit + STOPBIT. BREAK is when ParityBit doesn't match the necessary STOPBIT which shall be HIGH when the Line is hold LOW.
But if Parity is ODD, Parity Bit should be 1 instead of 0. Therefore you may get a BREAK associated to a PARITY error instead of BREAK error... This may work in the sense of not adding 0x00 to FIFO.
Just guessing...
It doesn't help... I've just tested it using the OnReceiveError_BREAK_Demo.ino
example code, but it still adds 0x00 to FIFO.
I have tried EVEN/ODD, 7 bits ... no solution.
Another possible way would be using some SoftwareSerial Library to deal with UART. It is CPU intensive, but it may give the application a better control over bytes and timing.
Just a suggestion.
As you say,
onReceive()
may not fit the application needs. It works based on how IDF and the HW works, as described in #10578 (comment)It may be usefull with
Serial1.setRxFIFOFull(1);
in order to use an async callback for each single incomming byte. Regarding the BREAK signal, this is how ESP32 HW works. If the BREAK is too long, it will add0x00
to the UART RX FIFO.Don't bother if BREAK is called error. This is just a denomination.
Well... as final testing: Serial1.setRxFIFOFull(1);
will execute the callback on every single byte, but if the callback takes too long, it could be called when FIFO has more bytes waiting for processing. It means that a single byte will force a callback, but it doens't mean that there is just one byte waiting in FIFO, therefore, Serial1.available()
may return higher than 1.
Anyway, regarding the initial topic of this issue, there is no relationship between HTTP / Flash Accessing Tasks and the truncated UART packets.
Yes, that is true.
Technically the single 0x00 byte "packet" callback happens because of the uart driver puts it when BREAK happens. But the last byte clipping is an other issue it seems. I can workaround the 0x00 byte as I shown but I don't know about the last byte clip. Needs more testing
just to see if I understand correctly:
UART_BREAK
happens if the flow of data stops for x timeUART_BREAK
happens, the driver puts a 0x00 byte into the buffer, indicating a breakonReceive
callback with only the 0x00 break byte since the timeout is fired.Well, interestingly the application wrote a file automatically meanwhile and I got this on the serial
I (10830070) DataBase: Writing json: /saves/users.json
W (10830075) Modbus: Detected single byte frame: 0x00. Ignoring it...
W (10830092) Modbus: Detected single byte frame: 0x00. Ignoring it...
W (10830103) Modbus: Detected single byte frame: 0x00. Ignoring it...
W (10830111) Modbus: Detected single byte frame: 0x00. Ignoring it...
W (10830125) Modbus: Detected single byte frame: 0x00. Ignoring it...
W (10830130) Modbus: Detected single byte frame: 0x00. Ignoring it...
W (10830132) Modbus: Detected single byte frame: 0x00. Ignoring it...
W (10830138) Modbus: Detected single byte frame: 0x00. Ignoring it...
W (10830146) Modbus: Detected single byte frame: 0x00. Ignoring it...
W (10830152) Modbus: Detected single byte frame: 0x00. Ignoring it...
W (10830171) Modbus: Detected single byte frame: 0x00. Ignoring it...
W (10830173) Modbus: Detected single byte frame: 0x00. Ignoring it...
W (10830179) Modbus: Detected single byte frame: 0x00. Ignoring it...
W (10830199) Modbus: Detected single byte frame: 0x00. Ignoring it...
W (10830201) Modbus: Detected single byte frame: 0x00. Ignoring it...
W (10830209) Modbus: Detected single byte frame: 0x00. Ignoring it...
W (10830217) Modbus: Detected single byte frame: 0x00. Ignoring it...
W (10830222) Modbus: Detected single byte frame: 0x00. Ignoring it...
W (10830228) Modbus: Detected single byte frame: 0x00. Ignoring it...
W (10830236) Modbus: Detected single byte frame: 0x00. Ignoring it...
W (10830242) Modbus: Detected single byte frame: 0x00. Ignoring it...
W (10830247) Modbus: Detected single byte frame: 0x00. Ignoring it...
W (10830253) Modbus: Detected single byte frame: 0x00. Ignoring it...
W (10830260) Modbus: Detected single byte frame: 0x00. Ignoring it...
W (10830267) Modbus: Detected single byte frame: 0x00. Ignoring it...
W (10830280) Modbus: Detected single byte frame: 0x00. Ignoring it...
W (10830294) Modbus: Detected single byte frame: 0x00. Ignoring it...
W (10830299) Modbus: Detected single byte frame: 0x00. Ignoring it...
W (10830301) Modbus: Detected single byte frame: 0x00. Ignoring it...
W (10830307) Modbus: Detected single byte frame: 0x00. Ignoring it...
W (10830315) Modbus: Detected single byte frame: 0x00. Ignoring it...
W (10830329) Modbus: Detected single byte frame: 0x00. Ignoring it...
W (10830341) Modbus: Detected single byte frame: 0x00. Ignoring it...
W (10830347) Modbus: Detected single byte frame: 0x00. Ignoring it...
W (10830349) Modbus: Detected single byte frame: 0x00. Ignoring it...
W (10830353) Modbus: Detected single byte frame: 0x00. Ignoring it...
W (10830360) Modbus: Detected single byte frame: 0x00. Ignoring it...
W (10830369) Modbus: Detected single byte frame: 0x00. Ignoring it...
W (10830374) Modbus: Detected single byte frame: 0x00. Ignoring it...
W (10830387) Modbus: Detected single byte frame: 0x00. Ignoring it...
W (10830389) Modbus: Detected single byte frame: 0x00. Ignoring it...
W (10830395) Modbus: Detected single byte frame: 0x00. Ignoring it...
W (10830402) Modbus: Detected single byte frame: 0x00. Ignoring it...
W (10830409) Modbus: Detected single byte frame: 0x00. Ignoring it...
W (10830417) Modbus: Detected single byte frame: 0x00. Ignoring it...
W (10830424) Modbus: Detected single byte frame: 0x00. Ignoring it...
W (10830436) Modbus: Detected single byte frame: 0x00. Ignoring it...
W (10830441) Modbus: Detected single byte frame: 0x00. Ignoring it...
W (10830445) Modbus: Detected single byte frame: 0x00. Ignoring it...
W (10830452) Modbus: Detected single byte frame: 0x00. Ignoring it...
W (10830467) Modbus: Detected single byte frame: 0x00. Ignoring it...
W (10830473) Modbus: Detected single byte frame: 0x00. Ignoring it...
W (10830477) Modbus: Detected single byte frame: 0x00. Ignoring it...
W (10830481) Modbus: Detected single byte frame: 0x00. Ignoring it...
W (10830487) Modbus: Detected single byte frame: 0x00. Ignoring it...
W (10830494) Modbus: Detected single byte frame: 0x00. Ignoring it...
W (10830504) Modbus: Detected single byte frame: 0x00. Ignoring it...
W (10830508) Modbus: Detected single byte frame: 0x00. Ignoring it...
W (10830516) Modbus: Detected single byte frame: 0x00. Ignoring it...
W (10830525) Modbus: Detected single byte frame: 0x00. Ignoring it...
W (10830575) Modbus: Detected single byte frame: 0x00. Ignoring it...
W (10830586) Modbus: Detected single byte frame: 0x00. Ignoring it...
W (10830602) Modbus: Detected single byte frame: 0x00. Ignoring it...
W (10830605) Modbus: Detected single byte frame: 0x00. Ignoring it...
W (10830611) Modbus: Detected single byte frame: 0x00. Ignoring it...
W (10830614) Modbus: Detected single byte frame: 0x00. Ignoring it...
W (10830621) Modbus: Detected single byte frame: 0x00. Ignoring it...
W (10830628) Modbus: Detected single byte frame: 0x00. Ignoring it...
W (10830635) Modbus: Detected single byte frame: 0x00. Ignoring it...
W (10830653) Modbus: Detected single byte frame: 0x00. Ignoring it...
W (10830656) Modbus: Detected single byte frame: 0x00. Ignoring it...
W (10830661) Modbus: Detected single byte frame: 0x00. Ignoring it...
W (10830665) Modbus: Detected single byte frame: 0x00. Ignoring it...
W (10830674) Modbus: Detected single byte frame: 0x00. Ignoring it...
W (10830693) Modbus: Detected single byte frame: 0x00. Ignoring it...
W (10830695) Modbus: Detected single byte frame: 0x00. Ignoring it...
W (10830706) Modbus: Detected single byte frame: 0x00. Ignoring it...
W (10830712) Modbus: Detected single byte frame: 0x00. Ignoring it...
W (10830716) Modbus: Detected single byte frame: 0x00. Ignoring it...
W (10830733) Modbus: Detected single byte frame: 0x00. Ignoring it...
W (10830741) Modbus: Detected single byte frame: 0x00. Ignoring it...
W (10830743) Modbus: Detected single byte frame: 0x00. Ignoring it...
W (10830749) Modbus: Detected single byte frame: 0x00. Ignoring it...
I (10830774) UserHandler: Saved 1 users to file: /saves/users.json
As you can see, it started writing I (10830070) DataBase: Writing json: /saves/users.json
-> bunch of UART BREAK BYTES coming in -> stopped writing to flash I (10830774) UserHandler: Saved 1 users to file: /saves/users.json
-> no further errors
god help us
This frame does not even overflow the buffer. This is 37 bytes and cuts the last byte.
0x03 0x03 0x20 0x00 0x05 0x00 0x00 0x00 0x04 0x00 0x00 0x00 0x04 0x00 0x00 0x00 0x04 0x00 0x00 0x00 0x03 0x00 0x00 0x00 0x02 0x00 0x00 0x00 0x03 0x00 0x00 0x00 0x02 0x00 0x00 0xfe 0x89
I have tested sending this sequence using the OnReceiveError_BREAK_Demo.ino
example code.
I see no cut when FIFO Full is 120 bytes.
It adds the 0x00 because of the BREAK (at the end or beginning of the package), but that's all.
Could it be a problem with the Line? Bad impedance or parasitic capacitance?
just to see if I understand correctly:
UART_BREAK
happens if the flow of data stops for x time- If
UART_BREAK
happens, the driver puts a 0x00 byte into the buffer, indicating a break- This break signaling byte will show up at the first byte of the next packet if the data flow started right after a break but the timeout does not fired
- If the data flow does not start right away, I get an
onReceive
callback with only the 0x00 break byte since the timeout is fired.
Yes, correct!
This has been an excellent issue report. I'll add that as a reference discussion later on.
Could it be a problem with the Line? Bad impedance or parasitic capacitance?
Yes, it can be line problem or the slave itself. Iam testing it meanwhile and so far it occoures on the same slave over and over again. Requires further testing.
But it seems flash write also triggers uart break. Hehe
Will test this as well
Board
esp32 wrover
Device Description
psram, eth, flash etc..
Hardware Configuration
psram, eth, flash etc..
Version
latest master (checkout manually)
IDE Name
PlatformIO
Operating System
Windows 10
Flash frequency
80
PSRAM enabled
yes
Upload speed
115200
Description
I often get truncated packets on uart when accessing either the flash with LittleFS wrapper or when making an http call from client to esp32. The way I test this is that I get an interrupt from
Serial1.onReceive()
with0x00
data in it when I save something to flash or when making an http request. http server uses the IDF server implementation as well as the arduino Serial wrapper.I expect the
onReceive
function to call my cb only when the set timeout is triggered. It isUART_SYMBOL_TIMEOUT 1
in this case. The problem is triggered every time when I write to flash. I can access menuconfig so I made sure that the UART functions and variables are inIRAM
and interrupts too.Sketch
Debug Message
Other Steps to Reproduce
Give repeated modbus packets to your esp, wait for them and access the flash meanwhile.
I have checked existing issues, online documentation and the Troubleshooting Guide