alejoseb / Modbus-STM32-HAL-FreeRTOS

Modbus TCP and RTU, Master and Slave for STM32 using Cube HAL and FreeRTOS
GNU Lesser General Public License v2.1
576 stars 191 forks source link

Master read queries sometimes sends two read request with no delays between (UART) #31

Closed pa0694 closed 3 years ago

pa0694 commented 3 years ago

Hi, First, thanks for the lib. It's a wonderful work. I'm using it with a TouchGFX app on STM32H7, as a master device with UART. I'm polling my device from a modbus task StartTaskPollModbus, by sending 6 requests for reading 100 words with MB_FC_READ_REGISTERSat each request. It works fine for the first 5 requests, my slave is responding and datas are well processed by the lib. My problem is that at the 6th request, my master is sending the read request directly (no delay) after the 5th request on my UART TX, while the slave is still responding from the previous request on my UART RX. For the 5 firsts read requests from my master, I can see on my scope that the most of the time, the master waits the slave answer to be complete before sending an other read request. But sometimes it sends two read request with no delay even before the 6th request. Though, at the 6 request it never waits for the slave answer of the previous request to be completed. See my code below. Any idea what could cause that ? Thanks!

void StartTaskPollModbus(void *argument)
{
  for(;;)
  {
        for (int i = 0; i < 6; i++)
        {
          modbusRead(100 * i, 100);
        }
    osDelay(300);
  }
}

void modbusRead(uint16_t regAdd, uint16_t regNo)
{
    modbus_t telegram;
    telegram.u8id = 1; // slave address
    telegram.u8fct = MB_FC_READ_REGISTERS; // function code
    telegram.u16RegAdd = regAdd;
    telegram.u16CoilsNo = regNo; // number of elements (coils or registers) to read
    telegram.u16reg = &modbusBuffer[regAdd]; // pointer to a memory array
    ModbusQuery(&ModbusH, telegram);
    ulTaskNotifyTake(pdTRUE, portMAX_DELAY);
}

// ModbusConfig.h
#define T35  2//5              // Timer T35 period (in ticks) for end frame detection.
#define MAX_BUFFER  128    // Maximum size for the communication buffer in bytes.
#define TIMEOUT_MODBUS 1000 // Timeout for master query (in ticks)
#define MAX_M_HANDLERS 2    //Maximum number of modbus handlers that can work concurrently
#define MAX_TELEGRAMS 50     //Max number of Telegrams in master queue
alejoseb commented 3 years ago

Hi, You need to handle the communication channel according to the value returned by the notification in this line:

ulTaskNotifyTake(pdTRUE, portMAX_DELAY);

In your case, you are sending request without taking care of what is actually happening. Also, I recommend to add a small delay between request in the for loop, otherwise your slave my not handle the traffic, which could be part of the issue.

pa0694 commented 3 years ago

Hi alejoseb, thanks for your answer! I will try the code below if I've well understood your answer. This seems logicial, I will try asap when I'm near my device!

void modbusRead(uint16_t regAdd, uint16_t regNo)
{
    uint32_t ulNotificationValue;

    ulNotificationValue = ulTaskNotifyTake(pdTRUE, portMAX_DELAY);

    if(ulNotificationValue)
    {
        modbus_t telegram;
        telegram.u8id = 1; // slave address
        telegram.u8fct = MB_FC_READ_REGISTERS; // function code
        telegram.u16RegAdd = regAdd;
        telegram.u16CoilsNo = regNo; // number of elements (coils or registers) to read
        telegram.u16reg = &modbusBuffer[regAdd]; // pointer to a memory array
        ModbusQuery(&ModbusH, telegram);

        osDelay(30);
    }
}
alejoseb commented 3 years ago

The expected return value is 0 any other value is an error or timeout.