stephane / libmodbus

A Modbus library for Linux, Mac OS, FreeBSD and Windows
http://libmodbus.org
GNU Lesser General Public License v2.1
3.44k stars 1.74k forks source link

Possible issue due to different library versions : modbus_receive_confirmation() is not useful #726

Open Mr-MoNET opened 9 months ago

Mr-MoNET commented 9 months ago

The version of libmodbus in the Windows system: V3.1.1 The version of libmodbus in the Ubuntu system: V3.0.6

I recently encountered some issues while developing using the libmodbus library. The development scenario is that I need to use the libmodbus library as a communication protocol and use the QT framework to monitor power devices in real-time. The program runs on Jetson Nano.

I found that the instruction reading program I wrote can be implemented on the Windows and can successfully read the parameters of the power supply; However, when porting this program to run on Ubuntu, it cannot effectively read the parameters of the power supply, Error code prompt when I run the program:"failed to receive confirmation: Invalid argument".

I use modbus_send_raw_request() to send read instructions and modbus_receive_confirmation() to receive returned information. However, it is the same program that cannot be transferred from Windows to Ubuntu. Is this caused by different versions of the library?

In addition, I also found that the reason why the program can run on Windows but cannot run on Ubuntu may be related to the version, as the formal parameters of modbus_set_response_timeout() may also be different due to different versions? Tips: modbus_set_response_timeout() have three arguments in Windows(libmodbus V3.1.1),but it only have two arguments in Ubuntu(libmodbus V3.0.6)

Here is my program for writing and reading commands:

modbus_t* Light::writeBytes()
{
    uint8_t m_sendData[6] = {0x01,0x03,0x00,0x00,0x00,0x08};
    m_sendData[0] = 0x01;
    modbus_t *m_modbus = NULL;
    m_modbus = modbus_new_rtu("COM5", 9600, 'N', 8, 1);

    if (0 == modbus_rtu_get_serial_mode(m_modbus)){
        modbus_rtu_set_serial_mode(m_modbus, MODBUS_RTU_RS232);
        std::cout << "serial is RS232" << std::endl;
    } else {
        modbus_rtu_set_serial_mode(m_modbus, MODBUS_RTU_RS485);
        std::cout<<"serial is RS485"<<std::endl;
    }
    struct timeval response_timeout;
    response_timeout.tv_sec = 1;
    response_timeout.tv_usec = 2000*1000;
    modbus_set_response_timeout(m_modbus,response_timeout.tv_sec,response_timeout.tv_usec);

    modbus_set_slave(m_modbus, 1);

    if(modbus_connect(m_modbus) == -1) {
        std::cout<<"connection failed: "<<modbus_strerror(errno)<<std::endl;
    }

    printf("-------------send-----------------\n");

    int s = modbus_send_raw_request(m_modbus, m_sendData, 6);
    if(s==-1)
    {
        std::cout<<"failed to send raw request: "<<modbus_strerror(errno)<<std::endl;
    }
    else
    {
        std::cout<<"successfully sent raw request with "<< s <<" bytes"<<std::endl;
    }

    return m_modbus;
}

void Light::readBytes(modbus_t *m_modbus)
{
    uint8_t rsp[MODBUS_RTU_MAX_ADU_LENGTH];
    int rc = modbus_receive_confirmation(m_modbus, rsp);

    printf("-------------receive-----------------\n");

    if(rc==-1)
    {
        std::cout<<"failed to receive confirmation: "<<modbus_strerror(errno)<<std::endl;
    }else
    {
        std::cout<<"successfully receive confirmation with "<< rc <<" bytes"<<std::endl;
        PowerInfoReslove(rsp);
        PrintPowerInfo();
    }
    modbus_close(m_modbus);
    modbus_free(m_modbus);
}