debevv / nanoMODBUS

A compact MODBUS RTU/TCP C library for embedded/microcontrollers
MIT License
233 stars 47 forks source link

Timeout Issue #51

Open sowmyam123 opened 1 month ago

sowmyam123 commented 1 month ago

I integrated NanoModbus library with the quectel EC200u controller for RTU communication as a master. However, I'm encountering timeout errors despite successful communication. In the SDK, there isn't a timer function available to handle read and write operations. Could you please assist me in resolving this issue?

debevv commented 1 month ago

Sure, can you post your read and write functions?
In general, from the README:

A value < 0 for byte_timeout_ms means no timeout. Their return value should be the number of bytes actually read/written, or < 0 in case of error. A return value between 0 and count - 1 will be treated as if a timeout occurred on the transport side. All other values will > be treated as transport errors.

So if you can't honor the requested timings, you can just return the exact number of byte requested and you should never encounter any timeout error

sowmyam123 commented 1 month ago

Thanks for quick Answer

Please review the read and write code below along with the logs.

This code executes a read operation without incorporating any time delay handling between read and write operations. Upon request, we print the return value, which consistently shows -3.This indicate a read/write timeout error? How can we resolve this timeout issue? The read operation should function properly without resorting to alternatives.

Could you please assist me in resolving this issue?

Logs:

ql_rs485_demo:ql_rs485_read 206 entered ql_rs485_read read_bytes: 25 ql_rs485_demo:ql_rs485_read 206 entered ql_rs485_read read_bytes: 0 ql_rs485_demo:ql_rs485_read 206 entered ql_rs485_read read_bytes: 25 ql_rs485_demo:ql_rs485_read 206 entered ql_rs485_read read_bytes: 0 ql_rs485_demo:ql_rs485_read 206 entered ql_rs485_read read_bytes: 25 ql_rs485_demo:ql_rs485_read 206 entered ql_rs485_read read_bytes: 0

ql_rs485_demo:ql_rs485_demo_thread 371 Error1 in reading1: -3

Code:-

include

include

include

include "ql_api_osi.h"

include "ql_log.h"

include "ql_uart.h"

include "ql_gpio.h"

include "ql_pin_cfg.h"

include "nanomodbus.h"

ql_task_t rs485_task = NULL; nmbs_t nmbs;

int ql_rs485_write(ql_uart_port_number_e port, unsigned char *data, unsigned int data_len) { int write_len = 0; ql_uart_tx_status_e tx_status; ql_uart_errcode_e ret;

ql_gpio_set_level(QL_RS485_GPIO_NUM, LVL_HIGH);
 QL_RS485_DEMO_LOG("entered ql_rs485_write : %d ", data_len);
write_len = ql_uart_write(QL_UART_PORT_1, data, data_len);
QL_RS485_DEMO_LOG("entered ql_rs485_write write_len : %d ", write_len);
while(1)
{
     QL_RS485_DEMO_LOG("entered write while loop : ");
    ret = ql_uart_get_tx_fifo_status(QL_UART_PORT_1, &tx_status);
    if(ret)
    {
        break;
    }
    if(tx_status == QL_UART_TX_COMPLETE)
    {
        break;
    }
}
for(int i = 0; i < write_len; i++)
{
    QL_RS485_DEMO_LOG("sent byte %d: 0x%02X", i, data[i]);
}
ql_gpio_set_level(QL_RS485_GPIO_NUM, LVL_LOW);

return write_len;

}

int ql_rs485_read(ql_uart_port_number_e port, unsigned char *data, unsigned int data_len) { ql_gpio_set_level(QL_RS485_GPIO_NUM, LVL_LOW); QL_RS485_DEMO_LOG("entered ql_rs485_read : %d ", data_len); time_t start_time = time(NULL); int read_bytes = ql_uart_read(QL_UART_PORT_1, data, data_len);

// Log the received data in hexadecimal format
for(int i = 0; i < read_bytes; i++)
{
    QL_RS485_DEMO_LOG("Received  %d: 0x%02X", i, data[i]);
}
 QL_RS485_DEMO_LOG("entered ql_rs485_read read_bytes : %d ", read_bytes);
 time_t current_time = time(NULL);
 if(current_time -  start_time >= 1)
 {
    QL_RS485_DEMO_LOG("Timeout occured :  ");
 }

return read_bytes;

}

int32_t read_serial(uint8_t buf, uint16_t count, int32_t byte_timeout_ms, void arg) {

QL_RS485_DEMO_LOG("Received byte_timeout_ms1 %d:", byte_timeout_ms);

return ql_rs485_read(QL_UART_PORT_1, buf, count);

}

int32_t write_serial(const uint8_t buf, uint16_t count, int32_t byte_timeout_ms, void arg) {

 QL_RS485_DEMO_LOG("Received byte_timeout_ms2 %d:", byte_timeout_ms);

return ql_rs485_write(QL_UART_PORT_1, (unsigned char*)buf, count);

}

static void ql_rs485_demo_thread(void *param) { int ret = 0; QlOSStatus err = 0;

ql_uart_config_s uart_cfg = {0};

uint32_t event_mask = 0;

ret = ql_pin_set_func(QUEC_PIN_DNAME_GPIO_18, 0);
if(QL_GPIO_SUCCESS != ret)
{
    goto exit;
}
ql_gpio_deinit(QL_RS485_GPIO_NUM);
ql_gpio_init(QL_RS485_GPIO_NUM, GPIO_OUTPUT, QUEC_PIN_NONE, LVL_LOW);

//step3:set event mask
event_mask = QL_UART_EVENT_RX_ARRIVED | QL_UART_EVENT_RX_OVERFLOW;
ret = ql_uart_set_event_mask(QL_UART_PORT_1, event_mask);
if(QL_UART_SUCCESS != ret)
{
    goto exit;
}

//step4:rs485 init, baud rate and other parameters need to be configured
uart_cfg.baudrate = QL_UART_BAUD_115200;
uart_cfg.flow_ctrl = QL_FC_NONE;
uart_cfg.data_bit = QL_UART_DATABIT_8;
uart_cfg.stop_bit = QL_UART_STOP_1;
uart_cfg.parity_bit = QL_UART_PARITY_NONE;

 nmbs_platform_conf platform_conf;
    platform_conf.transport = NMBS_TRANSPORT_RTU;
  platform_conf.read = read_serial;
   platform_conf.write = write_serial;

    nmbs_error error1 = nmbs_client_create(&nmbs, &platform_conf);
     QL_RS485_DEMO_LOG("error1 = %d",error1);
    if (error1 != NMBS_ERROR_NONE)
    {
        QL_RS485_DEMO_LOG("Error ");
    }

     nmbs_set_read_timeout(&nmbs, 1000);
     nmbs_set_byte_timeout(&nmbs, 100);
     nmbs_set_destination_rtu_address(&nmbs, RTU_SERVER_ADDRESS);

ret = ql_rs485_init(QL_UART_PORT_1, &uart_cfg, ql_rs485_notify_cb);
if(ret)
{
    goto exit;
}

while(1)
{

     uint16_t r_regs[10];
    error1 = nmbs_read_holding_registers(&nmbs, 4, 10, r_regs);
    if (error1 != NMBS_ERROR_NONE && error1 == NMBS_ERROR_TIMEOUT)
    {
        QL_RS485_DEMO_LOG("Error1 in reading1 : %d",error1);
    }
  else if(error1 == NMBS_ERROR_NONE)
    {
           QL_RS485_DEMO_LOG("No error reading1 : %d",error1);
    }    

ql_rtos_task_sleep_ms(1000); // Example: Delay for 1 second (1000 milliseconds)

}

exit: QL_RS485_DEMO_LOG("ret: 0x%x", ret); err = ql_rtos_task_delete(NULL); if(err != QL_OSI_SUCCESS) { QL_RS485_DEMO_LOG("task deleted failed"); } }