Problem with receiving uart data using esp32

Hi im trying to solve a bug in a home automation device. The device works as follows : we touch a button on a touch panel or smart phone which is connected to some key via wifi and that key is connected to a device and some relays are activated this way. The problem is when i touch buttons on touch panel quickly sometimes the data is not received by esp32 I send and receive data on RS485 using esp32 with arduino platform and free rtos. I tried to use different cores for transmit and receive but this bug still occures. what is the reason ? What should i do to solve this bug ? Here is the transmit task I will post the receive task i the follow up posts. thanks in advance.


void data_Transmite(void *pvParameters)

{

data_tars_sema = xSemaphoreCreateBinary();

data_tars_finish_sema = xSemaphoreCreateBinary();

data_sema = xSemaphoreCreateBinary();

Protocol_ = &Protocol;

LnkLst_ = LnkLst;

int t1, t2;

bool flg = 0;

ReportAllKeys();

xSemaphoreGive(data_tars_sema);

while (1)

{

if (xSemaphoreTake(data_tars_sema,(TickType_t)0) == pdTRUE)

{

flg = 1;

Serial.println("task data transmit is running ");

Protocol_ = &Protocol;

LnkLst_ = LnkLst;

t2 = millis() + 10;

t1 = t2 + 1000;

}

if (xSemaphoreTake(data_tars_finish_sema, (TickType_t)0) == pdTRUE)

{

Serial.printf("\n transmite finishhhhh !!!\n");

flg = 0;

}

if (flg == 1)

{

if ((t1 - millis()) > 0)

{

uint8_t *txbuf;

txbuf = LnkLst_->SendNext(Protocol_);

if (txbuf != 0)

{

int t_wait = 0;

t_wait = millis() + 100;

while (1) // waiting for getting line free

{

if (Port.Linestate == HAL_UART_STATE_READY)

{

Serial.println("uart is ready");

break;

}

else if ((millis() - t_wait) > 5) // time out !

{

Serial.println("timeout !");

vTaskDelay(170);

break;

}

}

digitalWrite(DIR_Pin, HIGH);

vTaskDelay(12);

Port.Linestate = HAL_UART_STATE_BUSY_TX;

Serial.printf("time before writing is %d\n",millis());

Serial1.write(txbuf, 5);

Serial1.flush();

Serial.printf("time after writing and flush is %d\n",millis());

digitalWrite(DIR_Pin, LOW);

Port.Linestate = HAL_UART_STATE_READY;

 } } else { flg = 0; } } }}



}

}

else

{

flg = 0;

}

}

}

}

void data_Recive(void *pvParameters)

{

int counter = 0;

uint8_t buf[20];

int U_rec;

int t = 0;

int flg = 0;

delay(2);

while (1)

{

// check Line state for using uart

if (Port.Linestate == HAL_UART_STATE_READY )

{

Port.Linestate = HAL_UART_STATE_BUSY_RX;

U_rec = Serial1.read(buf, 20);

for (int i = 0; i < U_rec; i++)

{

Serial.printf(" %d", buf[i]);

Port.Buffer[i] = buf[i];

buf[i] = 0;

}

if (U_rec != 0)

{

Serial.printf("\nport len %d", U_rec);

Port.Len = U_rec;

}

}

Port.Linestate = HAL_UART_STATE_READY;

if (Port.Len != 0)

{

Process();

for (int i = 0; i < Port.Len; i++)

{

Port.Buffer[i] = 0;

}

Port.Len = 0;

}

} 

}



void Process(void)

{

if (DataRecieved(Port))

;

if (KeyBufferCNT != 0)

{

xSemaphoreGive(data_tars_sema);

}

Port->Uartstate = Nothing;

}

xTaskCreatePinnedToCore(data_Recive,"data_Recive",30000,NULL,0,&data_Recive_handler,1);

xTaskCreatePinnedToCore(data_Transmite,"data_Transmite",30000,NULL,0,NULL,0);










Well first of all you should remove all excess white lines and format the code properly using ctrlT and re-post, and post the complete sketch including setup() & loop()
Please make sure closing braces are on a line by them self (unless when defining a class, but that doesn't apply here) So we can actually read what it is you wrote.
What pins are you connecting the RS485 to ? (which UART)

Sorry for the bad format and indentation it's because i'm posting from my phone i will correct my post as long as i get home. I can't post the whole code because it includes 15 libraries and thousands lines of code and nobody is going to read all that. But i can post the main code if you like it is 700 lines only. Im using uart1 for rs485 pin 14 is tx and pin 13 is rx. Baud rate is 4800. I don't know which strategy i can use here that can solve my problem. Uart interrupts ? Event group sync? or sth else.
Best regards
Salar

And how have you initialized that ? 13 & 14 are not the default pins, and the use of those pins can cause issues as do the default pins.
What specific board are you using, and with what board selection in the IDE?

Let's first make sure that the pins you are using actually work. Try creating a small test sketch for doing that, leaving the RS485 out of the equation. Just simple Serial transmit & receive.

Phones are good for making calls and taking pictures.

2 Likes

It is an esp32 wroom and i am using a custom pcb for using it.

Actually i didn't write the main code I'm just debugging it and he initialized the uart like this uart->begin(4800,134217756,rx_pin,tx_pin)

The rx and tx works most of the time but as i said when i touch the keys on the panel quickly sometimes one request is not received by the esp.

I will try to test the serial code without the rs485 as you said




Here are some photos of the device and touch panel so you could have a better understanding of the device

Are you sure it is actually being sent ?

Yes

And have you put a terminator on the RS485 ?

Yes

Hi i have a problem using uart with esp32 and arduino.while receving data I have some data loss so I want to use uart interrupt using the functions of hardwareserial library but there is no example or documentation about how to do this.

for example There is a function named setrxfifofull on this library which is related to interrupt. How should i use it along other functions ?

I'm using esp32 wroom with arduino platform with platformio and my code is based on FreeRTOS.

And I read lots of forum pages about this please don't recommend the serial available function because that is not useful for my case.

Thanks in advance.

This means that interrupts are not served in time. Reduce the controller load for more CPU time for essential tasks. Don't pin tasks or assign arbitrary priorities. Most probably it's your code that prevents the kernel from working properly.

The incoming data is not read fast enough.
In an RTOS environment interrupts belong to the RTOS.
What would You do better then the RTOS?

I'm sorry you misunderstood me. I'm not using interrupts right now. But i want to know how to use them.

What should i do to read them faster ? I tried to use indivisual cores for transmit and receive but no luck !

I know that. That's why your existing code is preventing proper operation of interrupts and the entire core. Please show your code.

and you did it wrong. As I already suggested: don't pin tasks to cores.

void data_Transmite(void *pvParameters)
{
  data_tars_sema = xSemaphoreCreateBinary();
  data_tars_finish_sema = xSemaphoreCreateBinary();
  data_sema = xSemaphoreCreateBinary();
  Protocol_ = &Protocol;
  LnkLst_ = LnkLst;
  int t1, t2;
  bool flg = 0;
  ReportAllKeys();
  xSemaphoreGive(data_tars_sema);
  while (1)
  {
    if (xSemaphoreTake(data_tars_sema, (TickType_t)0) == pdTRUE)
    {
      flg = 1;
      // Serial.println("task data transmit is runing ");
      Protocol_ = &Protocol;
      LnkLst_ = LnkLst;
      t2 = millis() + 10;
      t1 = t2 + 1000;
    }
    if (xSemaphoreTake(data_tars_finish_sema, (TickType_t)0) == pdTRUE)
    {
      // Serial.printf("\n transmite finishhhhh !!!\n");
      flg = 0;
    }
    if (flg == 1)
    {
      if ((t1 - millis()) > 0)
      {
        uint8_t *txbuf;
        txbuf = LnkLst_->SendNext(Protocol_);
        if (txbuf != 0)
        {
          int t_wait = 0;
          t_wait = millis() + 100;
          while (1) // waiting for getting line free
          {
            if (Port.Linestate == HAL_UART_STATE_READY)
            {
              break;
            }
            else if ((millis() - t_wait) > 5) // time out !
            {
              vTaskDelay(170);
              break;
            }
          }
          digitalWrite(DIR_Pin, HIGH);
          vTaskDelay(12);
          Port.Linestate = HAL_UART_STATE_BUSY_TX;
          Serial1.write(txbuf, 5);
          Serial1.flush();
          digitalWrite(DIR_Pin, LOW);
          // vTaskDelay(6);
          Port.Linestate = HAL_UART_STATE_READY;
        }
      }
      else
      {
        flg = 0;
      }
    }
  }
}
void data_Recive(void *pvParameters)
{
  int counter = 0;
  uint8_t buf[20];
  int U_rec;
  int t = 0;
  int flg = 0;
  delay(2);
  while (1)
  {
    // check Line state for using uart
    if (Port.Linestate == HAL_UART_STATE_READY)
    {
      Port.Linestate = HAL_UART_STATE_BUSY_RX;
      U_rec = Serial1.read(buf, 20);
      for (int i = 0; i < U_rec; i++)
      {
        // Serial.printf(" %d", buf[i]);
        Port.Buffer[i] = buf[i];
        buf[i] = 0;
      }
      if (U_rec != 0)
        // Serial.printf("\nport len  %d", U_rec);
        Port.Len = U_rec;
    }
    Port.Linestate = HAL_UART_STATE_READY;
    if (Port.Len != 0)
    {
      Protocol.Process();
      for (int i = 0; i < Port.Len; i++)
      {
        Port.Buffer[i] = 0;
      }
      Port.Len = 0;
    }
  }
}

Again: don't pin tasks to cores and report.