[SOLVED] UART response too late

gibzwein
Posts: 11
Joined: Fri Jul 03, 2020 3:19 am

[SOLVED] UART response too late

Postby gibzwein » Fri Jul 03, 2020 3:35 am

Hi,
I have problem with UART response. I am sending a frame of bytes to RX and send them back to TX. Delay between end of RX transmission end start of TX is 150 ms. I need to shorten it to 40 ms.
What am I doing wrong?

Code: Select all

#define ECHO_TEST_TXD (GPIO_NUM_4)
#define ECHO_TEST_RXD (GPIO_NUM_5)
#define ECHO_TEST_RTS (UART_PIN_NO_CHANGE)
#define ECHO_TEST_CTS (UART_PIN_NO_CHANGE)

#define BUF_SIZE (128)

static void echo_task()
{
  uint8_t data[8];

  while (1)
  {
    int len = uart_read_bytes(UART_NUM_2, data, 8, 1);
    uart_write_bytes(UART_NUM_2, (const char *)data, len);
  }
}

enum mgos_app_init_result mgos_app_init(void)
{
  uart_config_t uart_config = {
      .baud_rate = 450,
      .data_bits = UART_DATA_8_BITS,
      .parity = UART_PARITY_DISABLE,
      .stop_bits = UART_STOP_BITS_1,
      .flow_ctrl = UART_HW_FLOWCTRL_DISABLE};
  uart_param_config(UART_NUM_2, &uart_config);
  uart_set_pin(UART_NUM_2, ECHO_TEST_TXD, ECHO_TEST_RXD, ECHO_TEST_RTS, ECHO_TEST_CTS);
  uart_driver_install(UART_NUM_2, BUF_SIZE * 2, 0, 0, NULL, 0);
  xTaskCreate(echo_task, "uart_echo_task", 1024, NULL, 10, NULL);
  return MGOS_APP_INIT_SUCCESS;
}
Attachments
screen.png
screen.png (30.42 KiB) Viewed 9237 times
Last edited by gibzwein on Sat Jul 04, 2020 7:40 pm, edited 1 time in total.

PeterR
Posts: 621
Joined: Mon Jun 04, 2018 2:47 pm

Re: UART response too late

Postby PeterR » Fri Jul 03, 2020 10:32 pm

EDIT: 'Ignore this! It would be better if you initialised 'data' such that we might then compare your logic analyser trace with code.'
Anyway...
(1) You use 450Hz baud rate & a buffer of 8 bytes. Thats 140 mS + start/stop/parity.
If you must use 450Hz baud then you might reduce latency (end receiver latency) by reading one byte at a time and relay (but only by tx size -1 + some driver latency).
(2) I don't get your trace.
You don't show signal labels.
If I were to assume that the top signals are the RX and bottom TX then why is TX data different to RX?
We can explain the 150mS gap between RX and TX as (1) above.

The bottom line will be that the last TX byte will only leave the gate at 140mS+ (after being received) unless; you increase the baud rate &/or develop mystical abilities to predict the last byes within the esp ;)

EDIT: 2400 should do it, 9600 would rock & 19200 would beat your 40mS requirement into the dust.

PS
See now that data is supplied by the RX, so even more confussed why TX is different
& I also believe that IDF CAN should be fixed.

gibzwein
Posts: 11
Joined: Fri Jul 03, 2020 3:19 am

Re: UART response too late

Postby gibzwein » Sat Jul 04, 2020 5:08 am

Thank you very much PeterR for your answer.
The upper signal is RX the lower TX as You assumed.
I can't change the baudrate, data is read from the connected device and sent alternately.
Could you please explain how to reduce latency?
Attachments
screen2.png
screen2.png (86.59 KiB) Viewed 9157 times

ESP_Sprite
Posts: 9709
Joined: Thu Nov 26, 2015 4:08 am

Re: UART response too late

Postby ESP_Sprite » Sat Jul 04, 2020 8:00 am

The UART by default waits until a certain number of bytes have come in or a timeout happens before it tells the software to process the data it received. (The reason is because it would result in a lot of overhead if the UART would poke the processor for every byte.). You can change this by setting e.g. the rxfifo_full_thresh member in a uart_intr_config_t struct and passing that to uart_intr_config.

PeterR
Posts: 621
Joined: Mon Jun 04, 2018 2:47 pm

Re: UART response too late

Postby PeterR » Sat Jul 04, 2020 10:41 am

You ask for 8 bytes in uart_read_bytes(). Therefore the function only returns when you have 8 bytes or timeout.
Instead sit in a loop requesting one byte and tx as soon as you receive.
This will reduce your latency to 1 byte + driver overheads.
You are only 450 baud which is about 20mS per byte & so the overhead will be fine.

Looking at your trace then even though you ask for 8 bytes you seem to return before 8 bytes have been received.
EDIT: No, you don't, its just a new frame comming in.
EDIT: There might be a timeout at work still. As Sprite says, setting low timeout & low FIFIO threshold will help but I think you also need to request 1 byte at a time to achieve best latency. In that scenario (& with 1 byte FIFO threshold) you don't need to reduce timeout, you will return as soon as you have one byte which is as good as it gets!
Driver overheads will be <<100 uS so we can ignore that latency against the 20 mS per byte.

EDIT: Your best case latency is therefore around 22mS + driver delays.
& I also believe that IDF CAN should be fixed.

gibzwein
Posts: 11
Joined: Fri Jul 03, 2020 3:19 am

Re: UART response too late

Postby gibzwein » Sat Jul 04, 2020 6:27 pm

PeterR, thank You for reply.
Asking for 1 byte:

Code: Select all

uint8_t data[1];

  while (1)
  {
    int len = uart_read_bytes(UART_NUM_2, data, 1, 1);
    uart_write_bytes(UART_NUM_2, (const char *)data, len);
  }
Result:
screen8.png
screen8.png (83.59 KiB) Viewed 9103 times
Added FIFO Tresh

Code: Select all

uart_intr_config_t uart_intr = {
    .rxfifo_full_thresh = 1};
  // //  .rx_timeout_thresh = 22};
  uart_intr_config(UART_NUM_2, &uart_intr);
  uart_enable_rx_intr(UART_NUM_2);
Result:
screen9.png
screen9.png (66.34 KiB) Viewed 9103 times
Timeout added:

Code: Select all

uart_intr_config_t uart_intr = {
      .rxfifo_full_thresh = 1,
      .rx_timeout_thresh = 22};
  uart_intr_config(UART_NUM_2, &uart_intr);
  uart_enable_rx_intr(UART_NUM_2);
Result:
screen10.png
screen10.png (67.33 KiB) Viewed 9103 times
Am I doing something wrong?

gibzwein
Posts: 11
Joined: Fri Jul 03, 2020 3:19 am

Re: UART response too late

Postby gibzwein » Sat Jul 04, 2020 6:37 pm

Oh, ESP_Sprite thank You as well.

gibzwein
Posts: 11
Joined: Fri Jul 03, 2020 3:19 am

Re: UART response too late

Postby gibzwein » Sat Jul 04, 2020 7:25 pm

Probably I found the solution.
Now testing.

gibzwein
Posts: 11
Joined: Fri Jul 03, 2020 3:19 am

Re: UART response too late

Postby gibzwein » Sat Jul 04, 2020 7:38 pm

I found the solution here:
viewtopic.php?t=3751
I had to make struck like above
Result:
screen11.png
screen11.png (39.15 KiB) Viewed 9085 times
Thank You very much.
Regards

PeterR
Posts: 621
Joined: Mon Jun 04, 2018 2:47 pm

Re: [SOLVED] UART response too late

Postby PeterR » Sat Jul 04, 2020 8:43 pm

Without looking at your code - still looks like you can do better.
You're trace seems to show that you only output the first byte after all 8 bytes have been achieved. You could output the first byte after the first byte has been received! Maybe this is the FIFO issue related by Sprite.
If you are happy then np. Don't optimise what you don't need to, just checking you see the approach.
& I also believe that IDF CAN should be fixed.

Who is online

Users browsing this forum: MicroController and 170 guests