Results 1 to 15 of 15

Thread: Modbus implementation

  1. #1
    Join Date
    Oct 2009
    Location
    South Africa
    Posts
    94
    Thanks
    4
    Thanked 1 Time in 1 Post
    Qt products
    Qt4
    Platforms
    Windows

    Default Modbus implementation

    Hello everyone. New to this forum, loving using Qt.

    My question:
    I am trying to implement Modbus protocol using Qt on TCP. Looking at various articles, a lot of them are obviously for serial connection, and a lot more include precompiled libraries, and others are for linux (I'm using Windows), with the result that I'm not making progress.

    However, from what I have seen, a socket connection gets made, with a few options set, using structures to store the ip address, port, file descriptor, etc which then uses the memset function to clear it. Then there is a command setsockopt to set options of the socket like TCP_NODELAY, IP_TOS. Do I really need all this?

    In Qt, it "appears" as easy as

    Qt Code:
    1. tcpSocket = new QTcpSocket(this);
    2. tcpSocket->connectToHost("193.1.1.14",502);
    To copy to clipboard, switch view to plain text mode 

    Now I say appear, because I'm sure it isn't, however, I do manage to connect by viewing the socket state, and it returns connection established.

    The next stage again appears that I need to write to the socket, and then read something back. Now this is where I am stuck, and would appreciate help. I don't mind the hard work, just some guidance please.

  2. #2
    Join Date
    Oct 2009
    Location
    South Africa
    Posts
    94
    Thanks
    4
    Thanked 1 Time in 1 Post
    Qt products
    Qt4
    Platforms
    Windows

    Default Re: Modbus implementation

    Please, is there no one who has any suggestions/help for me? I really am desperate for some help, and I see my post slowly moving down the page, I don't want it to disappear!
    Thanks.
    Shaun

  3. #3
    Join Date
    Jan 2009
    Location
    Russia
    Posts
    309
    Thanks
    2
    Thanked 43 Times in 42 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Re: Modbus implementation

    So what's the actual problem then? I do not understand!
    Read assistant QAbstractSocket and see examples of in /examples/network

  4. #4
    Join Date
    Oct 2009
    Location
    South Africa
    Posts
    94
    Thanks
    4
    Thanked 1 Time in 1 Post
    Qt products
    Qt4
    Platforms
    Windows

    Default Re: Modbus implementation

    Hi
    Thanks for replying.
    My actual probelm is that I do not know what exactly to write to the socket, and how to set up the data structure. All the info I come across is written for Linux, and so it uses different libraries. I have been working through them for about 2 weeks now, no luck. The one bit of source I got using Qt, the serial connection had been done, but for TCP, it had said "to be done", i.e. not yet implemented. It was using the modbus library (but this is Linux again).
    Also, it jumps everywhere between fuinctions, and it is too difficult for me to keep track of what is happening, even using breakpoints in Qt Creator.
    I would love to do it using neat classes, but like I say, battling to understand it.

  5. #5
    Join Date
    Jan 2009
    Location
    Russia
    Posts
    309
    Thanks
    2
    Thanked 43 Times in 42 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Re: Modbus implementation

    1. Modbus TCP protocol itself is very easy to implement yourself (from scratch), it is not necessary to use any third-party libraries. Protocol is very easy.
    2. The structure of the data before writing it must first be prepared, for example, QByteArray, and then this array is written in the socket, etc.
    3. See the documentation for the protocol:
    Modbus_Messaging_Implementation_Guide_V1_0b.pdf
    Modbus_Application_Protocol_V1_1b.pdf

    http://www.modbus.org/
    http://en.wikipedia.org/wiki/Modbus

    etc. everything there is clear written! Read the documentation!

  6. #6
    Join Date
    Oct 2009
    Location
    South Africa
    Posts
    94
    Thanks
    4
    Thanked 1 Time in 1 Post
    Qt products
    Qt4
    Platforms
    Windows

    Default Re: Modbus implementation

    Easy for some, I'm battling

    This is what I have so far, perhaps you can comment?

    I first make a connection to a button being pressed...

    Qt Code:
    1. connect(getFortuneButton, SIGNAL(clicked()),this, SLOT(requestNewFortune()));
    To copy to clipboard, switch view to plain text mode 

    Then in my slot...

    Qt Code:
    1. getFortuneButton->setEnabled(false);
    2. blockSize = 0;
    3. tcpSocket->abort();
    4. tcpSocket->connectToHost("193.1.1.14",502);
    5.  
    6. QByteArray block;
    7. QDataStream out(&block, QIODevice::WriteOnly);
    8. out.setVersion(QDataStream::Qt_4_0);
    9. out << (quint16)0;
    10. block.resize(7);
    11. //***********************************************************
    12. //*****see http://www.simplymodbus.ca/TCP.htm ************
    13. //***********************************************************
    14. block[0] = 0x0001; //unique transaction identifier
    15. block[1] = 0x0000; //protocol identifier - always 00 00
    16. block[2] = 0x0006; //message length i.e. 6 bytes to follow
    17. block[3] = 0x01; //unit identifier
    18. block[4] = 0x03; //the function code
    19. block[5] = 0x0000; //40108-40001 = 107 = 6B
    20. block[6] = 0x0064; //no. of registers requested 64(16) = 100(10)
    21. out.device()->seek(0);
    22. out << (quint16)(block.size() - sizeof(quint16));
    23.  
    24. qDebug() << tcpSocket->write(block);
    To copy to clipboard, switch view to plain text mode 

    qDebug shows 7 bytes having been written to the socket. This should be 12 bytes?

    Now I have a slot to catch the readyRead of the socket, but it never gets activated!

  7. #7
    Join Date
    Jan 2009
    Location
    Russia
    Posts
    309
    Thanks
    2
    Thanked 43 Times in 42 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Re: Modbus implementation

    In this situation, simply do not use QDataStream in general!

    example:
    Qt Code:
    1. getFortuneButton-> setEnabled (false);
    2. blockSize = 0;
    3. tcpSocket-> abort ();
    4. tcpSocket-> connectToHost ( "193.1.1.14", 502);
    5.  
    6. QByteArray block;
    7. / / TID = 2 BYTE!!!
    8. block [0] = 0x00; / / unique transaction identifier HI BYTE
    9. block [1] = 0x01; / / unique transaction identifier LO BYTE
    10. / / PID = 2 BYTE!!!
    11. block [2] = 0x00; / / protocol identifier HI
    12. block [3] = 0x00; / / protocol identifier LO
    13. / / Length = 2 BYTE!!!
    14. block [4] = 0x00; / / message length i.e. 6 bytes to follow HI
    15. block [5] = 0x06; / / message length i.e. 6 bytes to follow LO
    16. / / UID = 1 BYTE!!!
    17. block [6] = 0x01; / / unit identifier
    18. / / FC = 1 BYTE!!!
    19. block [7] = 0x03; / / the function code
    20. / / START REGS ADDR = 2 BYTE (example 4x5 - 4x10)
    21. block [8] = 0x00; / / HI byte
    22. block [9] = 0x04; / / LO byte (0x0004 - is start addr 4x5)
    23. / / COUNT REGS = 2 BYTE!!! (example 6 regs)
    24. block [10] = 0x00; / / HI Byte
    25. block [11] = 0x06; / / LO Byte
    26.  
    27. qDebug () <<tcpSocket-> write (block);
    To copy to clipboard, switch view to plain text mode 
    Total length of the ADU = MBHap + PDU = 7 + 5 = 12 BYTES!!!

    PS: Read the documentation on the Modbus!

  8. #8
    Join Date
    Oct 2009
    Location
    South Africa
    Posts
    94
    Thanks
    4
    Thanked 1 Time in 1 Post
    Qt products
    Qt4
    Platforms
    Windows

    Default Re: Modbus implementation

    Thank you, the slot now gets activated.
    I have actually read the documentation. Before 2 weeks ago, I had never heard of Modbus in my life! So basically I've been trying to get my head around it. Also, I actually program in Delphi, so at the same time I am trying to learn C++/Qt as this is one of my modules I am doing.
    Thank you for this, I have spent for ages trying to get the library working for me, but glad that it seems possible in such a simpler setup.

    I will keep working on the program.

  9. #9
    Join Date
    Oct 2009
    Location
    South Africa
    Posts
    94
    Thanks
    4
    Thanked 1 Time in 1 Post
    Qt products
    Qt4
    Platforms
    Windows

    Default Re: Modbus implementation

    Thank you. In a readyRead slot, I have placed the following...

    Qt Code:
    1. QByteArray block;
    2. block = tcpSocket->readAll();
    To copy to clipboard, switch view to plain text mode 

    and then running in debug mode, I notice similarities between what is read to what I pick up in a program called "Simply Modbus TCP" (demo version), so this is my first positive result.

  10. #10
    Join Date
    Jan 2009
    Location
    Russia
    Posts
    309
    Thanks
    2
    Thanked 43 Times in 42 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Re: Modbus implementation

    No, I do not need to use readAll ()!!! (IMHO)

    Algorithm reading about the following:
    1. Must first read the first 7 bytes of incoming data packet (MBHAP)
    2. To analyze these 7 bytes and allocate field Length
    3. Read the remaining bytes from the socket size = Length - 1 (PDU)

  11. #11
    Join Date
    Oct 2009
    Location
    South Africa
    Posts
    94
    Thanks
    4
    Thanked 1 Time in 1 Post
    Qt products
    Qt4
    Platforms
    Windows

    Default Re: Modbus implementation

    I assume by MBHAP you mean the header?

    From Modbus_Application_Protocol_V1_1b.pdf I get:
    MBAP = 7 bytes, for TCP that leaves 253 bytes for PDU, giving total of 260 bytes for ADU.

    The mb_rsp_pdu is defined as: (response from slave)
    mb_rsp_pdu = {function_code, response_data}, where
    function_code = [1 byte] MODBUS function code
    response_data = [n bytes] This field is function code dependent and usually
    contains information such as variable references,
    variable counts, data offsets, sub-function codes, etc.
    And then further in the document: (for function code 3)

    Response
    Function code 1 Byte 0x03
    Byte count 1 Byte 2 x N*
    Register value N* x 2 Bytes
    *N = Quantity of Registers
    Now byte count I am assuming is 2xN (qty of registers) since each register is 2 bytes long (16bits), but then that means only the first 2 bytes are used for letting me know how much data is following, i.e. byte #2, but previously it says 7 bytes? And that is why I just do a full readAll() call, even though not best way.

    When I use (demo) "Simply Modbus TCP", it shows the registers I want are in numbers 40017 & 40018, with an offset of 40001, so this then means I want registers 16 & 17?

    So I set up my data structure as :
    Qt Code:
    1. block [0] = 0x00; // unique transaction identifier HI BYTE
    2. block [1] = 0x01; // unique transaction identifier LO BYTE
    3. block [2] = 0x00; // protocol identifier HI
    4. block [3] = 0x00; // protocol identifier LO
    5. block [4] = 0x00; // message length i.e. 6 bytes to follow HI
    6. block [5] = 0x06; // message length i.e. 6 bytes to follow LO
    7. block [6] = 0x01; // unit identifier
    8. block [7] = 0x03; // the function code
    9. block [8] = 0x00; // HI byte
    10. block [9] = 0x10; // Start from register mem addr 16
    11. block [10] = 0x00; // Hi byte
    12. block [11] = 0x02; // Read in 2 registers
    To copy to clipboard, switch view to plain text mode 

    And the response I get is
    Qt Code:
    1. block [0] = 0x00;
    2. block [1] = 0x01;
    3. block [2] = 0x00;
    4. block [3] = 0x00;
    5. block [4] = 0x00;
    6. block [5] = 0x07;
    7. block [6] = 0x01;
    8. block [7] = 0x03;
    9. block [8] = 0x04;
    10. block [9] = 0x3D;
    11. block [10] = 0x7E;
    12. block [11] = 0xBF;
    13. block [12] = 0x26;
    To copy to clipboard, switch view to plain text mode 

    So it is reading the correct registers, yet 13 bytes are returned, 4 making up the data, block[8] I take it tells me how many bytes are following, [7] is just a return of the function code, remainder back to 0 as in request, except for [5] that (I assume?) again tells me how many bytes are still to follow, i.e. 7, plust the 6 already given ([0]-[6]) = 13.

    So I am still a bit confused as to its makeup. block [9] to [12] is the data I want, basically a float point number as single-precision, which is fine to convert.

    Possibly one more question, if you aren't already tired of my ignorance, when I do a

    Qt Code:
    1. qDebug() << QString::number(block[9],16);
    2. qDebug() << QString::number(block[10],16);
    3. qDebug() << QString::number(block[11],16);
    4. qDebug() << QString::number(block[12],16);
    To copy to clipboard, switch view to plain text mode 

    it prints out

    "3d"
    "7e"
    "ffffffffffffffbf"
    "26"
    Why does the 3rd value come out so strange, yet in the debugging (watchpoints) it displays as "bf"?

    Again, thanks for your insight. I appreciate your time and help.
    Shaun

  12. #12
    Join Date
    Oct 2009
    Location
    South Africa
    Posts
    94
    Thanks
    4
    Thanked 1 Time in 1 Post
    Qt products
    Qt4
    Platforms
    Windows

    Default Re: Modbus implementation

    I have subsequently found this in another document:

    The header is 7 bytes long:
    Transaction Identifier - It is used for transaction pairing, the MODBUS server copies in the
    response the transaction identifier of the request.
    Protocol Identifier – It is used for intra-system multiplexing. The MODBUS protocol is identified
    by the value 0.
    Length - The length field is a byte count of the following fields, including the Unit Identifier and data fields.
    Unit Identifier – This field is used for intra-system routing purpose. It is typically used to
    communicate to a MODBUS or a MODBUS+ serial line slave through a gateway between an
    where
    Transaction Identifier : Recopied by the server from the received request
    Protocol Identifier : Recopied by the server from the received request
    Length : Initialized by the server (Response - no. of following bytes)
    Unit Identifier : Recopied by the server from the received request

    so it is indeed 7 bytes.

    So my response makes sense, until it then gets to block[7]-[12]. I can't seem to find reference to this, or more specifically, to block [7] & [8] of my response.

  13. #13
    Join Date
    Jan 2009
    Location
    Russia
    Posts
    309
    Thanks
    2
    Thanked 43 Times in 42 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Re: Modbus implementation

    Yuor response:
    block [0] = 0x00; //TID HI
    block [1] = 0x01; //TID LO
    block [2] = 0x00; //PID HI
    block [3] = 0x00; //PID LO
    block [4] = 0x00; // LENGTH HI
    block [5] = 0x07; // LENGTH LO
    block [6] = 0x01; //UID

    block [7] = 0x03; // FC
    block [8] = 0x04; // Bytes Count
    block [9] = 0x3D; //HI DATA REGS in addr 0x10
    block [10] = 0x7E; //LO DATA REGS in addr 0x10
    block [11] = 0xBF; //HI DATA REGS in addr 0x11
    block [12] = 0x26; //LO DATA REGS in addr 0x11

    All right!

    MBHAP = [0] - [6]
    PDU = [7] - [12]

    block [4] and block [5] = length = 0x0007 bytes, ie [6] - [12] = 7 byte!
    Parameter length - controls the length of the entire package, including [6] - [12]!

    block [8] - includes the length of the data from the registers! because You asked for data from two registers to 16 bits - a natural response will be data = 2 x 16 bits = 4 bytes, ie [8] = 4 bytes!

    Next come the data itself is already registers:
    0x10 = [9] - [10] = 0x3D7E
    0x11 = [11] - [12] = 0xBF26

    I do not understand that you do not understand? I'll have to explain everything. Sam understood further.

    PS:
    Qt has nothing to do with. We first with Modbus protocol

  14. #14
    Join Date
    Oct 2009
    Location
    South Africa
    Posts
    94
    Thanks
    4
    Thanked 1 Time in 1 Post
    Qt products
    Qt4
    Platforms
    Windows

    Default Re: Modbus implementation

    Thank you, I have figured out how the response is made up your assistance.
    Any idea on my question i.e.

    qDebug() << QString::number(block[9],16);
    qDebug() << QString::number(block[10],16);
    qDebug() << QString::number(block[11],16);
    qDebug() << QString::number(block[12],16);

    it prints out

    "3d"
    "7e"
    "ffffffffffffffbf"
    "26"

    Shaun

  15. #15
    Join Date
    Dec 2011
    Posts
    1
    Qt products
    Qt4
    Platforms
    Unix/X11

    Default Re: Modbus implementation

    Have got any solution to the 0xffffffbf problem?
    I am facing the same problem while reading a float data from modbus .
    If u have a solution pls tell me.

Similar Threads

  1. Modbus, QextSerialPort and QTimer
    By ^NyAw^ in forum General Programming
    Replies: 6
    Last Post: 27th October 2009, 17:14
  2. Read Sensor Temperature and Modbus Protocol
    By photovoltaico in forum General Programming
    Replies: 1
    Last Post: 7th August 2009, 09:32
  3. Correct Member Sheet Extension Implementation
    By PeeAeMKAy in forum Qt Programming
    Replies: 8
    Last Post: 17th July 2009, 16:47
  4. questions re: inline implementation, const
    By Urthas in forum Newbie
    Replies: 1
    Last Post: 2nd May 2009, 23:41
  5. Readonly Model implementation requirements for QComboBox
    By DeepDiver in forum Qt Programming
    Replies: 6
    Last Post: 8th November 2007, 18:10

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
Digia, Qt and their respective logos are trademarks of Digia Plc in Finland and/or other countries worldwide.