uart_read response add an extra byte

AleGiaco
Posts: 10
Joined: Thu Feb 06, 2020 9:48 am

uart_read response add an extra byte

Postby AleGiaco » Thu Jun 03, 2021 9:29 am

Hello,
I'm using a custom board where there are a microprocessor that collects informations and the Esp32 reads that informations via modBus.
Now my problem is that sometimes (i have no clue when or why that happends) i see an extra byte in the response and is always the first byte and always at 0x00.
I checked with the oscilloscope and the response length of the micro is correct
It usually works correctly, but once it gives a wrong answer of that type it corrupts all the readings

This is how I initialize the uart:

Code: Select all

	// *****************
	// UART CONFIGURATION (modbus)
	// *****************
	uart_config_t uart_config;
	uart_config.baud_rate = BAUDRATE_DEFAULT;
	uart_config.data_bits = UART_DATA_8_BITS;
	uart_config.parity = UART_PARITY_DISABLE;
	uart_config.stop_bits = UART_STOP_BITS_1;
	uart_config.flow_ctrl = UART_HW_FLOWCTRL_DISABLE;
	uart_config.rx_flow_ctrl_thresh = 122;
	uart_param_config(UART_NUM_1, &uart_config);
	uart_set_pin(UART_NUM_1, TXD_PIN, RXD_PIN, TX_EN_PIN, UART_PIN_NO_CHANGE);
	uart_driver_install(UART_NUM_1, RX_BUF_SIZE * 2, 0, 0, NULL, 0);
	SET_PERI_REG_MASK(UART_MEM_CONF_REG(UART_NUM_1), 0X10);
	CLEAR_PERI_REG_MASK(UART_MEM_CONF_REG(UART_NUM_1), 0X08);
	// Set RS485 half duplex mode
	uart_set_mode(UART_NUM_1, UART_MODE_RS485_HALF_DUPLEX);

And these are the functions to read the data from the micro:

Code: Select all


	unsigned char TX_UARTBuffer[280]
	unsigned char bufferricezione1[512];
	
	int send_pkt_sngl_and_rcv_answer(unsigned char bytes_to_send, int responseLenght)
	{
		static TickType_t timer_timeout = 0;
		unsigned long timeout_variable = 500;
		int len, lenghtTX = 0;
		switch (MB_master_FSM)
		{
			case TXing:
			{
				if (GET_PERI_REG_MASK(UART_STATUS_REG(UART_NUM_1), (UART_ST_UTX_OUT_M | UART_ST_URX_OUT_M)) == 0)
				{
					memset(bufferricezione1, 0, responseLenght);
					lenghtTX = uart_write_bytes(UART_NUM_1, (const char*)TX_UARTBuffer, bytes_to_send);
					MB_master_FSM = TX_ENABLE_RESETTING;
				}
				else
				{
					vTaskDelay(pdMS_TO_TICKS(50));
				}

			}
			break;
			case TX_ENABLE_RESETTING:
			{
				if (isModbusPacketSent())
				{
					MB_master_FSM = START_TIMER;
				}
			}
			break;
			case START_TIMER:
			{
				timer_timeout = xTaskGetTickCount();     			// timeout timer
				MB_master_FSM = RX_WAITING;
			}
			break;
			case RX_WAITING:
			{
				len = uart_read_bytes(UART_NUM_1, bufferricezione1, BUF_SIZE, pdMS_TO_TICKS(1 + 40000 / QBO_memory.serial_data.baudrate));
				if (len >= responseLenght)
				{
					if (len > responseLenght)
					{
						for (int i = 0; i < len; i++)
						{
							printf(" TX_UARTBuffer %d: 0x%.2X | ", i, (uint8_t)TX_UARTBuffer[i]);
							printf(" i %d val %x", i, bufferricezione1[i]);
						}
					}
					MB_master_FSM = NEXT_MSG_SET;
				}
				else if (len == 5)
				{
					MB_master_FSM = TXing;
					return EXCEPTION;
				}
				else if ((xTaskGetTickCount() - timer_timeout) < timeout_variable)
				{
				
				}
				else
				{
					MB_master_FSM = TXing;
					exception = 1;
					return NO_RESPONSE;
				}
			}
			break;
			case NEXT_MSG_SET:
			{
				MB_master_FSM = TXing;
				return MB_OK;
			}
			break;
			default:
			break;
		}
		return WAITING;
	}
	
	signed long readSingleRegister(int zone, int index)
	{
		unsigned short crc;
		unsigned char j = 0;
		int  response = 0;
		int responseLenght = 7;

		TX_UARTBuffer[0] = zone;
		TX_UARTBuffer[1] = READ_HOLDING;
		TX_UARTBuffer[2] = ((index & 0xFFFF) >> 8);
		TX_UARTBuffer[3] = index & 0x00FF;
		TX_UARTBuffer[4] = 0x00;
		TX_UARTBuffer[5] = 0x01; 
		j = 6;
		crc = modbusCRC(TX_UARTBuffer, j);
		TX_UARTBuffer[j++] =	 crc & 0xff;
		TX_UARTBuffer[j++] = (crc >> 8) & 0xff;

		MB_master_FSM = TXing;
		do
		{
			vTaskDelay(5);
			response = send_pkt_sngl_and_rcv_answer(j, responseLenght);
		} while (response < MB_OK);
		if (exception == 0)
		{
			memset(TX_UARTBuffer, 0, 8);
			uint32_t val = WORD(bufferricezione1[3], bufferricezione1[4]);
			return val;
		}
		else
		{
			return response;
		}
	}
And this is the wrong answer, on the left the request and on the right the answer:

Code: Select all

	TX_UARTBuffer 0: 0xF0 |  i 0 val 0
	TX_UARTBuffer 1: 0x03 |  i 1 val f0
	TX_UARTBuffer 2: 0x00 |  i 2 val 3
	TX_UARTBuffer 3: 0x88 |  i 3 val 2
	TX_UARTBuffer 4: 0x00 |  i 4 val 0
	TX_UARTBuffer 5: 0x01 |  i 5 val 0
	TX_UARTBuffer 6: 0x11 |  i 6 val c5
	TX_UARTBuffer 7: 0x01 |  i 7 val 91
I look forward to your replies and I thank you in advance for your help.

WiFive
Posts: 3529
Joined: Tue Dec 01, 2015 7:35 am

Re: uart_read response add an extra byte

Postby WiFive » Fri Jun 04, 2021 6:18 pm

Maybe a glitch on the tx driver disable but your Rx parsing should be smart enough to filter out extra bytes or corruption

AleGiaco
Posts: 10
Joined: Thu Feb 06, 2020 9:48 am

Re: uart_read response add an extra byte

Postby AleGiaco » Wed Jun 09, 2021 2:18 pm

Thank you for the reply!
WiFive wrote:
Fri Jun 04, 2021 6:18 pm
your Rx parsing should be smart enough to filter out extra bytes or corruption
Yes i can filter the extra bytes but it doesn't seem like a good idea to filter all the answers from then on.
A possible solution could be to uninstall and reinstall the drivers?

Who is online

Users browsing this forum: Bing [Bot] and 67 guests