Jump to content

Recommended Posts

I've been scratching my head with this one and am hoping someone has dealt with it before.

My physical setup is a PC, CAT5 cables, a couple of switches, an Eaton HMI, and an Eaton PLC. I'm talking Modbus TCP to the PLC using the library on NI's website.

I'm using Wireshark to troubleshoot other problems and found the PLC retransmitting the response to the PC very frequently (not every time). The PC is reads and writes 32 words to the PLC every 100 msec, but only performs a write when the data changes. The PLC transmits a response within 6 msec of a read message (function 3 in Modbus). The PC never responds with an acknowledgement of the message from the PLC. The PLC retransmits 50 msec later and the PC acknowledges that message. The write messages occur about every 1 second (my heartbeat to the PLC).

I've tried switching to the second port on the PC, which goes to a second card in the PLC. That network has four drives, two air manifolds, a remote I/O block and an RFID system on it that are all talking to the PLC. The PLC sequences through all the remote devices, including the PC, so the response to the PC can take 75 - 150+ msec. The PC always acknowledges the first message with that network.

Anyone have some thoughts as to what's going on?

Tim

Forgot to mention that I'm using LabVIEW 8.6.1 and have swapped all of the network components.

Link to post
Share on other sites

I'm talking Modbus TCP to the PLC using the library on NI's website.

Is it this library you are using? If so, did you correct the bug pointed out in the comments:

a flaw in MB CRC-16.vi in NI Modbus.llb

A failure mode turn up in testing at 1200 baud. It turned out to be a flaw in MB CRC-16.vi in NI Modbus.llb. The failure mode is that the MB Serial Recieve.vi that waits for a Modbus reply to a command may falsely detemines that the message is complete before the last byte is recieved. This is becuase because MB CRC-16.vi coerces the U16 CRC to a U8, and the U8 becomes zero for a message with all but the last byte transmitted. The correction is to change the data type of the Exception Code indicator from U8 to U16.

- Jim Figucia, Code G Automation. labview_work@msn.com - Sep 15, 2009

I haven't used it but when I downloaded the library a few months ago the bug was still there. Don't know if it could cause your problem.

Link to post
Share on other sites

Before I forget, I appreciate any and all thoughts.

Sounds like a network stack issue. What OS are you running? Is this your problem?

Sorry, forgot to put that in. Windows7 is the OS. It is possible that I'm seeing an OS level issue, which appears to be how the person solved the issue (replace with WinXP system). I don't have a reset of the ethernet card and am starting the PC side after the PLC has booted up. I'll check for the start of connection, though.

Is it this library you are using? If so, did you correct the bug pointed out in the comments:

Ah, yes, that's it.

a flaw in MB CRC-16.vi in NI Modbus.llb

A failure mode turn up in testing at 1200 baud. It turned out to be a flaw in MB CRC-16.vi in NI Modbus.llb. The failure mode is that the MB Serial Recieve.vi that waits for a Modbus reply to a command may falsely detemines that the message is complete before the last byte is recieved. This is becuase because MB CRC-16.vi coerces the U16 CRC to a U8, and the U8 becomes zero for a message with all but the last byte transmitted. The correction is to change the data type of the Exception Code indicator from U8 to U16.

- Jim Figucia, Code G Automation. labview_work@msn.com - Sep 15, 2009

I haven't used it but when I downloaded the library a few months ago the bug was still there. Don't know if it could cause your problem.

Unfortunately it's not the cause. TCP is a connection based protocol, meaning all messages have to be acknowledged by the receiver; this occurs down in the TCP primitives. The issue I'm having doesn't show up except that the TCP Read takes ~56 msec to complete. The TCP Read should complete in ~6 msec if the TCP acknowledge by the PC occurred as it should instead of occurring when the PLC retransmits the message after not receiving an acknowledgement.

Link to post
Share on other sites

I recently chased a TCP issue under LV 8.6 and came away beliveing that 10Hz is about the best I can expect out of Windows.

Since its OK on another NIC I would expect the other network traffic is getting in the way and tying up the TCP stack and not acking the packet.

I found a lot of info posted by gamers trying to reduce Lag so searching on Lag and speed will get you some good hits.

This link

http://technet.microsoft.com/en-us/library/bb726981.aspx

gives you the internals of the TCP stack under windows and if there anything that can be tweaked its in there. If you find something out please share so we can benefit.

Ben

Link to post
Share on other sites

Have you checked out driver-level settings? Through the Device Manager in Windows you can usually tweak all sorts of settings for the NIC. I don't have a good jump-off point, but at least seeing what's available might give you some ideas.

Link to post
Share on other sites

Most of the gaming advice has been about removing unneeded services and setting the performance options (system properties->advanced tab->performance options button) to "adjust for best performance". These did not help the acknowledge issue.

I found one YouTube video at:

It recommends going into the registry and adding "TcpAckFrequency" and "TCPNoDelay" to the parameters for the NIC. I'm seeing a positive change, but I was fooled a couple of times today, so I'm not ready to say it's fixed yet. The registry path is:

HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\services\Tcpip\Parameters\Interfaces\{ .... some GUID identifying your NIC card port .... }

Check the IP address to figure out which interface you should be looking at. Under the path add the values:

TcpAckFrequency DWORD data=0x1

TCPNoDelay DWORD data=0x1

TCPNoDelay = 1 turns off nagling

TcpAckFrequency is far more interesting per: http://support.microsoft.com/kb/328890

It seems Windows sends out a TCP acknowledge for every other segment received (per RFC 1122). Setting the ack frequency from 2 (default of every other segment) to 1 will acknowledge every segment. :frusty:

Tim

  • Like 1
Link to post
Share on other sites

If you use the link that I provided earlier, you will find that there is a way to turn off Nagling for a specific connection ref inside LabVIEW rather than disabling Nagle's Algorithm for all connections on an interface (registry setting).

The change could be done completely from within LabVIEW. Note the name of the LLB in the link: TCP_NODELAY.LLB

Link to post
Share on other sites

Sorry, though I'd posted.

Adding the TcpAckFrequency with data = 0x01 to the registry for the physical interface resolved it. The default value is 2, meaning it will acknowledge every other TCP message or after a 200 msec timeout (the PLC retransmitted after 50 msec). Setting the data to 1 forces it to acknowledge every message that arrives.

I've passed the info along to NI. Interestingly, I had to use email support as I used the word "Modbus"; it seems there is a recon (I think that was the name) group responsible for such and they only support through email at the moment. I could have continued with phone support if I had stuck to the TCP aspect.

Tim

  • Like 1
Link to post
Share on other sites

Sorry, though I'd posted.

Adding the TcpAckFrequency with data = 0x01 to the registry for the physical interface resolved it. The default value is 2, meaning it will acknowledge every other TCP message or after a 200 msec timeout (the PLC retransmitted after 50 msec). Setting the data to 1 forces it to acknowledge every message that arrives.

I've passed the info along to NI. Interestingly, I had to use email support as I used the word "Modbus"; it seems there is a recon (I think that was the name) group responsible for such and they only support through email at the moment. I could have continued with phone support if I had stuck to the TCP aspect.

Tim

Not really much NI can do about it. This is not a standard socket property at all and Windows socket implementations don't even support to set it through the API. So even if NI ever decides to add a property interface to network refnums, it's not possible to change this setting from the program in any way. And the 200ms acknowledgment is a standard TCP/IP socket feature, that Microsoft implemented in Windows 2000 to conform to the standard. So the really faulty party here is the PLC that resends already after 50 ms if you want to call it a fault. Realistically it's just a workaround to guarantee that any packet is acknowledged after not more than 50ms :-)

Enabling this registry setting in Windows is the only way to change this setting, and you don't want LabVIEW to change this behind your back in the registry ever! Especially since it enables this feature for any connection on that interface, which can be a real burden on network traffic if normal internet traffic also happens to go through this interface.

  • Like 1
Link to post
Share on other sites

Not really much NI can do about it. This is not a standard socket property at all and Windows socket implementations don't even support to set it through the API. So even if NI ever decides to add a property interface to network refnums, it's not possible to change this setting from the program in any way. And the 200ms acknowledgment is a standard TCP/IP socket feature, that Microsoft implemented in Windows 2000 to conform to the standard. So the really faulty party here is the PLC that resends already after 50 ms if you want to call it a fault. Realistically it's just a workaround to guarantee that any packet is acknowledged after not more than 50ms :-)

Enabling this registry setting in Windows is the only way to change this setting, and you don't want LabVIEW to change this behind your back in the registry ever! Especially since it enables this feature for any connection on that interface, which can be a real burden on network traffic if normal internet traffic also happens to go through this interface.

I completely agree. NI tech support is adding it to their database for when someone has the same issue. I expect Eaton and Delta (not sure who wrote the firmware for the ethernet module; Eaton repackages Delta PLCs) are not the only ones who are not aware of or compliant with the RFC standard. The other pieces of my system (Eaton/Vaccon drives, Festo manifolds, and Balluff RFID reader) have no issues.

Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

  • Similar Content

    • By David Akinpelu
      I am implementing a TCP connection between MyRio(client) and Python(server). The goal is to send data from the server to the client, perform some calculations, and send the result to the server. I need to keep changing the data being sent to the client. I noticed the first data works fine and the result returned to the server, but the client could not read subsequent data. I debugged and was able to detect that the error is coming from the first read function is the "Reading values subvi"  but I don't know how to correct it. How do I go about it?
      I have attached the files below.
      Reading Unknown Bytes from TCP.vi Second_client.vi SimpleServer.py
    • By Porter
      View File Plasmionique Modbus Master
      This package contains the Plasmionique Modbus Master library for LabVIEW.
      It supports RTU, ASCII and TCP modes with the following function codes:
      0x01 - Read Coils
      0x02 - Read Discrete Inputs
      0x03 - Read Holding Registers
      0x04 - Read Input Registers
      0x05 - Write Single Coil
      0x06 - Write Single Register
      0x07 - Read Exception Status
      0x0F - Write Multiple Coils
      0x10 - Write Multiple Registers
      0x16 - Mask Write Register
      0x17 - Read/Write Multiple Registers
      0x2B/0x0E - Read Device Identification
      Other features include:
      - Sharing a COM port across multiple Modbus sessions using VISA locks (10 second timeout).
      - Sharing a Modbus session across multiple communication loops.
      - TCP transaction ID handling to ensure that requests and responses are matched up correctly in case responses are received out of order.
      - Modbus Comm Tester, available through the "Tools->Plasmionique" menu, for testing communication with a slave device without writing any code. 
      - Detailed help document available through the "Help->Plasmionique" menu.
      Examples are included in "<LabVIEW>\examples\Plasmionique\MB Master\":
      MB_Master Comm Tester.vi: Demonstrates usage of API to open/close connection and communicate with a Modbus slave device. MB_Master Multiple Sessions.vi: Demonstrates usage of API to open concurrent Modbus sessions. MB_Master Simple Serial.vi: Demonstrates polling of a single input register over serial line. Download a copy of the user guide here: MB_Master - User Guide.pdf
      Note that Version 1.3.4 of this library has been certified compatible with LabVIEW and has been released on the LabVIEW Tools Network: http://sine.ni.com/nips/cds/view/p/lang/en/nid/214230
      The most recent version of this library will always be released on LAVA first before going through NI's certification process.
      ***This project is now available on GitHub: https://github.com/rfporter/Modbus-Master
      Submitter Porter Submitted 04/01/2016 Category LabVIEW Tools Network Certified LabVIEW Version 2012 License Type BSD (Most common)  
    • By Porter
      This package contains the Plasmionique Modbus Master library for LabVIEW.
      It supports RTU, ASCII and TCP modes with the following function codes:
      0x01 - Read Coils
      0x02 - Read Discrete Inputs
      0x03 - Read Holding Registers
      0x04 - Read Input Registers
      0x05 - Write Single Coil
      0x06 - Write Single Register
      0x07 - Read Exception Status
      0x0F - Write Multiple Coils
      0x10 - Write Multiple Registers
      0x16 - Mask Write Register
      0x17 - Read/Write Multiple Registers
      0x2B/0x0E - Read Device Identification
      Other features include:
      - Sharing a COM port across multiple Modbus sessions using VISA locks (10 second timeout).
      - Sharing a Modbus session across multiple communication loops.
      - TCP transaction ID handling to ensure that requests and responses are matched up correctly in case responses are received out of order.
      - Modbus Comm Tester, available through the "Tools->Plasmionique" menu, for testing communication with a slave device without writing any code. 
      - Detailed help document available through the "Help->Plasmionique" menu.
      Examples are included in "<LabVIEW>\examples\Plasmionique\MB Master\":
      MB_Master Comm Tester.vi: Demonstrates usage of API to open/close connection and communicate with a Modbus slave device. MB_Master Multiple Sessions.vi: Demonstrates usage of API to open concurrent Modbus sessions. MB_Master Simple Serial.vi: Demonstrates polling of a single input register over serial line. Download a copy of the user guide here: MB_Master - User Guide.pdf
      Note that Version 1.3.4 of this library has been certified compatible with LabVIEW and has been released on the LabVIEW Tools Network: http://sine.ni.com/nips/cds/view/p/lang/en/nid/214230
      The most recent version of this library will always be released on LAVA first before going through NI's certification process.
      ***This project is now available on GitHub: https://github.com/rfporter/Modbus-Master
    • By Diegodemf
      Hello, I'm trying to send data from my RPI b+ to labview and store the information in a spreadsheet, right now the data I'm using is just a sawtooth generated in the python code but eventually it will be sensor data adquired via spi, the data comes at =~ 6-7khz but the time it takes to send the data to labview is much greater, I fear the circular buffer I intended to use to store the data before sending it via tcp will get filled pretty fast. I'm not very experienced in either python nor Labview, I was wondering if i could get some advice in the optimization of the code.

      I attached the VI of the client and a VI that graphs the data on the spreadsheet, also the python code.
      Thanks in advance, sorry for the mess.
      Waveform Grapher.vi
      Client.vi
      serverSerial.py
    • By Porter
      NI Labs Modbus API is now on GitHub!
      Password protection of VIs has been removed.
      https://github.com/NISystemsEngineering/LabVIEW-Modbus-API
×
×
  • Create New...

Important Information

By using this site, you agree to our Terms of Use.