stephane / libmodbus

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

Timeout not respected #393

Closed FabioGenesy closed 7 years ago

FabioGenesy commented 7 years ago

Hi, I use the stable version of libmodbus (3.0.6) but I noticed a problem. If a set a timeout passing a timeval to the modbus_set_response_timeout, like 10ms, it's not respected but the program is blocked always for a second. Are you aware of this problem? I use the library for modbus TCP connection on Ubuntu 16.04

Thank you very muck!

stephane commented 7 years ago

No issues are known and we have a few tests for that. https://github.com/stephane/libmodbus/blob/master/tests/unit-test-client.c#L555 Are you able to test with latest version and/or provide your code?

FabioGenesy commented 7 years ago

Hi, I replicate the problem in an example, developed with Qt, that I attached to this email. Unfortunately I am forced to use version 3.0.6 and can not replace it. The test is executed on Ubuntu 16.04

Thank you in advace

Il 24-Jul-17 13:06, Stéphane Raimbault ha scritto:

No issues are known and we have a few tests for that. Are you able to test with latest version and/or provide your code?

— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub https://github.com/stephane/libmodbus/issues/393#issuecomment-317390150, or mute the thread https://github.com/notifications/unsubscribe-auth/Ac_5mNUfXPzXkmGOX-yjPOCqntaJkIFJks5sRHrKgaJpZM4OhA3b.

stephane commented 7 years ago

You can't attach files to github issue. Please provide a very minimal extract of your code we can compile if you want help.

stefanofiorentino commented 7 years ago

@FabioGenesy maybe you are passing wrong number format, did you check the function signature and timeout type?

FabioGenesy commented 7 years ago

Hi Stefano, this is the code for initialize the timeout:

 struct timeval response_timeout;
 response_timeout.tv_sec = 0;
 response_timeout.tv_usec = timeOut*1000;
 modbus_set_response_timeout(m_modbus, &response_timeout);

where timeOut is an integer that represents the timeout in milliseconds, for example 10. I tried also to set the tv_sec element but there is always the same problem.

Il 24-Jul-17 23:47, Stefano Fiorentino ha scritto:

@FabioGenesy maybe you are passing wrong number format, did you check the function signature and timeout type?

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/stephane/libmodbus/issues/393#issuecomment-317564665, or mute the thread https://github.com/notifications/unsubscribe-auth/Ac_5mOF6M_uorpmRirb-2C5VQbd04XVRks5sRRDYgaJpZM4OhA3b.

-- Ing. Fabio Benevento Genesy SrL Via Malasoma, 24 56121 Pisa tel 050 981970 - int. 203 fax 050 988138


Importante: Questo messaggio e gli eventuali allegati sono confidenziali e riservati. Se vi è stato recapitato per errore e non siete fra i destinatari elencati, siete pregati di darne immediatamente avviso al mittente. Le informazioni contenute non devono essere mostrate ad altri, né utilizzate, memorizzate o copiate in qualsiasi forma.

FabioGenesy commented 7 years ago

I upload it with WeTransfer. This is the link: https://we.tl/L1ocY8H3vA

Anyhow, this is the code for my modbus adapter:

modbus_adapter.h

ifndef MODBUSADAPTER_H

define MODBUSADAPTER_H

include

include

include <modbus/modbus.h>

/ Modbus function codes /

define MODBUS_FC_READ_COILS 0x01

define MODBUS_FC_READ_DISCRETE_INPUTS 0x02

define MODBUS_FC_READ_HOLDING_REGISTERS 0x03

define MODBUS_FC_READ_INPUT_REGISTERS 0x04

define MODBUS_FC_WRITE_SINGLE_COIL 0x05

define MODBUS_FC_WRITE_SINGLE_REGISTER 0x06

define MODBUS_FC_READ_EXCEPTION_STATUS 0x07

define MODBUS_FC_WRITE_MULTIPLE_COILS 0x0F

define MODBUS_FC_WRITE_MULTIPLE_REGISTERS 0x10

define MODBUS_FC_REPORT_SLAVE_ID 0x11

define MODBUS_FC_MASK_WRITE_REGISTER 0x16

define MODBUS_FC_WRITE_AND_READ_REGISTERS 0x17

class ModbusAdapter : public QObject { Q_OBJECT public: explicit ModbusAdapter(QObject *parent = 0);

  void modbusConnectRTU(QString port, int baud, QChar parity, int 

dataBits, int stopBits, int timeOut=1); void modbusConnectTCP(QString ip, int port, int timeOut=1); void modbusDisConnect();

  bool isConnected();

  void setSlave(int slave);
  void setFunctionCode(int functionCode);
  void setStartAddr(int addr);
  void setNumOfRegs(int num);
  void addItems();

  int packets();
  int errors();

  int modbusReadData(int slave, int functionCode, int startAddress, 

int noOfItems, uint8_t dest); int modbusWriteData(int slave, int functionCode, int startAddress, int noOfItems, uint8_t src);

private: QString stripIP(QString ip); modbus_t * m_modbus; bool m_connected; int m_ModBusMode; int m_slave; int m_functionCode; int m_startAddr; int m_numOfRegs; int m_packets; int m_errors; int m_timeOut;

public slots: void resetCounters();

};

endif // MODBUSADAPTER_H


modbus_adapter.cpp

include

include "modbusadapter.h"

include

include

include

static enum {RTU = 0, TCP = 1, None = 2} ModbusMode;

ModbusAdapter *m_instance;

ModbusAdapter::ModbusAdapter(QObject *parent) : QObject(parent), m_modbus(NULL) { m_instance = this; m_connected = false; m_ModBusMode = None; m_timeOut = 0; m_packets = 0;

 m_errors = 0;

}

void ModbusAdapter::modbusConnectRTU(QString port, int baud, QChar parity, int dataBits, int stopBits, int timeOut) { //Modbus RTU connect modbusDisConnect();

 qDebug() << "Modbus Connect RTU";

 m_modbus = 

modbus_new_rtu(port.toLatin1().constData(),baud,parity.toLatin1(),dataBits,stopBits); qDebug() << "Connecting to Serial Port " << port <<"...";

 //Debug messages from libmodbus
 #ifdef LIB_MODBUS_DEBUG_OUTPUT
     modbus_set_debug(m_modbus, 1);
 #endif

 m_timeOut = timeOut;

 if(m_modbus && modbus_connect(m_modbus) == -1) {
     qCritical() << "Connection failed. Could not connect to serial 

port"; m_connected = false; } else { struct timeval response_timeout; response_timeout.tv_sec = 0; response_timeout.tv_usec = timeOut*1000; modbus_set_response_timeout(m_modbus, &response_timeout); m_connected = true; qInfo() << "Connection OK"; }

 m_ModBusMode = RTU;

}

void ModbusAdapter::modbusConnectTCP(QString ip, int port, int timeOut) { //Modbus TCP connect QString strippedIP = ""; QString line; modbusDisConnect();

 qInfo() << "Modbus Connect TCP";

m_timeOut = timeOut;

 if (m_modbus == NULL){
     strippedIP = stripIP(ip);
     if (strippedIP == ""){
         qCritical()  << "Connection failed. Blank IP Address";
         return;
     }
     else {
         m_modbus = 

modbus_new_tcp(strippedIP.toLatin1().constData(), port); struct timeval response_timeout; response_timeout.tv_sec = 0; //timeOut/1000; response_timeout.tv_usec = timeOut*1000; modbus_set_response_timeout(m_modbus, &response_timeout); } }

 //Debug messages from libmodbus
 #ifdef LIB_MODBUS_DEBUG_OUTPUT
     modbus_set_debug(m_modbus, 1);
 #endif

 struct timeval response_timeout;
 modbus_get_response_timeout(m_modbus, &response_timeout);
 qInfo() << "Timeout = " << response_timeout.tv_usec/1000 << " sec";

 qInfo() << "Connecting to IP : " << ip << port;

 fflush(stdout);         //TODO: per capire se era un problema di printf

 if(m_modbus && modbus_connect(m_modbus) == -1) {
     qCritical() << "Connection to IP: %1:%2 failed." << ip << port;
     m_connected = false;
 }
 else {
     m_connected = true;
     qInfo() << "Connection Ok" ;
 }

 m_ModBusMode = TCP;

}

void ModbusAdapter::modbusDisConnect() { //Modbus disconnect

 qInfo() << "Modbus disconnected" ;

// if(m_modbus) { // modbus_close(m_modbus); // modbus_free(m_modbus); // m_modbus = NULL; // }

 m_connected = false;

 m_ModBusMode = None;

}

bool ModbusAdapter::isConnected() { //Modbus is connected

 return m_connected;

}

int ModbusAdapter::modbusReadData(int slave, int functionCode, int startAddress, int noOfItems, uint8_t *dest) { qDebug() << "Modbus Read Data: slaveID=" << slave << ", functionCode=" << functionCode << ", startAddress=" << startAddress << ", nOfItems=" << noOfItems << ".";

 int ret = -1; //return value from read functions
 if(m_modbus == NULL) return ret;

 uint16_t * dest16 = (uint16_t *) dest;
 bool is16Bit = false;

 modbus_set_slave(m_modbus, slave);
 //request data from modbus
 switch(functionCode)
 {
         case MODBUS_FC_READ_COILS:
                 ret = modbus_read_bits(m_modbus, startAddress, 

noOfItems, dest); break;

         case MODBUS_FC_READ_DISCRETE_INPUTS:
                 ret = modbus_read_input_bits(m_modbus, 

startAddress, noOfItems, dest); break;

         case MODBUS_FC_READ_HOLDING_REGISTERS:
                 ret = modbus_read_registers(m_modbus, startAddress, 

noOfItems, dest16); is16Bit = true; break;

         case MODBUS_FC_READ_INPUT_REGISTERS:
                 ret = modbus_read_input_registers(m_modbus, 

startAddress, noOfItems, dest16); is16Bit = true; break;

         default:
                 break;
 }

 if(ret == -1)
 {
     qCritical() << "Modbus Read Data error code: " << errno;
     m_errors += 1;
     modbus_flush(m_modbus); //flush data
 }
 else{
     qInfo() << "Modbus Read Data OK";
 }

 return ret;

}

int ModbusAdapter::modbusWriteData(int slave, int functionCode, int startAddress, int noOfItems, uint8_t* src) {

 qDebug() << "Modbus Write Data: slaveID=" << slave << ", 

functionCode=" << functionCode << ", startAddress=" << startAddress << ", nOfItems=" << noOfItems << ".";

 int ret = -1; //return value from functions

 if(m_modbus == NULL) return ret;

 modbus_set_slave(m_modbus, slave);
 //request data from modbus
 switch(functionCode)
 {
         case MODBUS_FC_WRITE_SINGLE_COIL:
                 ret = modbus_write_bit(m_modbus, startAddress, 

(uint32_t )src); noOfItems = 1; break;

         case MODBUS_FC_WRITE_SINGLE_REGISTER:
                 ret = modbus_write_register( m_modbus, 

startAddress, (uint32_t )src); noOfItems = 1; break;

         case MODBUS_FC_WRITE_MULTIPLE_COILS:
         {
                 ret = modbus_write_bits(m_modbus, startAddress, 

noOfItems, src); break; } case MODBUS_FC_WRITE_MULTIPLE_REGISTERS: { uint16_t src16 = (uint16_t ) src; ret = modbus_write_registers(m_modbus, startAddress, noOfItems, src16); break; }

         default:
                 break;
 }

 if(ret == -1)
 {
     qCritical() << "Modbus Write Data error code: " << errno;
     m_errors += 1;
     modbus_flush(m_modbus); //flush data
 }
 else{
     qInfo() << "Modbus Write Data OK";
 }

 return ret;

}

void ModbusAdapter::setSlave(int slave) { m_slave = slave; }

void ModbusAdapter::setFunctionCode(int functionCode) { m_functionCode = functionCode; }

void ModbusAdapter::setStartAddr(int addr) { m_startAddr = addr; }

void ModbusAdapter::setNumOfRegs(int num) { m_numOfRegs = num; }

void ModbusAdapter::resetCounters() { m_packets = 0; m_errors = 0; }

int ModbusAdapter::packets() { return m_packets; }

int ModbusAdapter::errors() { return m_errors; }

QString ModbusAdapter::stripIP(QString ip) { //Strip zero's from IP QStringList ipBytes; QString res = ""; int i;

 ipBytes = ip.split(".");
 if (ipBytes.size() == 4){
     res = QString("").setNum(ipBytes[0].toInt());
     i = 1;
     while (i <  ipBytes.size()){
         res = res + "." + QString("").setNum(ipBytes[i].toInt());
         i++;
     }
     return res;
 }
 else
     return "";

}

Thank you very much!

Il 24-Jul-17 22:35, Stéphane Raimbault ha scritto:

You can't attach files to github issue. Please provide a very minimal extract of your code we can compile if you want help.

— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub https://github.com/stephane/libmodbus/issues/393#issuecomment-317546212, or mute the thread https://github.com/notifications/unsubscribe-auth/Ac_5mNwt8f9BJBDsCVw2kiZYpXt4tyKyks5sRP_zgaJpZM4OhA3b.

-- Ing. Fabio Benevento Genesy SrL Via Malasoma, 24 56121 Pisa tel 050 981970 - int. 203 fax 050 988138


Importante: Questo messaggio e gli eventuali allegati sono confidenziali e riservati. Se vi è stato recapitato per errore e non siete fra i destinatari elencati, siete pregati di darne immediatamente avviso al mittente. Le informazioni contenute non devono essere mostrate ad altri, né utilizzate, memorizzate o copiate in qualsiasi forma.

FabioGenesy commented 7 years ago

Have you been able to replicate the issue?

Il 24-Jul-17 22:35, Stéphane Raimbault ha scritto:

You can't attach files to github issue. Please provide a very minimal extract of your code we can compile if you want help.

— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub https://github.com/stephane/libmodbus/issues/393#issuecomment-317546212, or mute the thread https://github.com/notifications/unsubscribe-auth/Ac_5mNwt8f9BJBDsCVw2kiZYpXt4tyKyks5sRP_zgaJpZM4OhA3b.

-- Ing. Fabio Benevento Genesy SrL Via Malasoma, 24 56121 Pisa tel 050 981970 - int. 203 fax 050 988138


Importante: Questo messaggio e gli eventuali allegati sono confidenziali e riservati. Se vi è stato recapitato per errore e non siete fra i destinatari elencati, siete pregati di darne immediatamente avviso al mittente. Le informazioni contenute non devono essere mostrate ad altri, né utilizzate, memorizzate o copiate in qualsiasi forma.

jcwren commented 7 years ago

@FabioGenesy, your WeTransfer page has been deleted.

You can attach files to issues. See https://help.github.com/articles/file-attachments-on-issues-and-pull-requests/