P-ModbusTCP 0013: Port locked


Jonessy

Recommended Posts

Hello,

I get this P-ModbusTCP 0013: Port locked error and can not get it away what ever setting I try. Some times it takes more than 30 mins before next error and sometimes get error every second, just one page showing data and no changes except changing some values to plc. There are timeouts also not not as often as locked ports.

Funny though , when I open device/port monitor, errors stop almost completely.

I have some 70 register channels and 30 digitals going from ModbusTCP to RTU plc.

Any ideas??

Br Jone

Comm_errors.txt

Link to comment
Share on other sites

Your device is VERY, VERY slow. It looks like it takes anywhere between 70 to 80ms for it to reply to a query. During this time, the port is locked while DAQFactory waits for a response. Once it gets a response, DF will move on to the next register, releasing the port for a millisecond at most and then locking it up again waiting for a response from your device.

So first, why is your device so slow? Are you using a ModbusTCP to RTU protocol converter? If so, get rid of it, and just get a standard Serial to Ethernet device and have DAQFactory talk ModbusRTU over Ethernet.

If the device itself just has a slow Modbus implementation, then you should look to see if you can somehow combine your registers into a block, either inside the PLC by changing the mapping, or by reading some junk registers. What I mean by junk registers is if you needed register 1 and register 3, read register 2 as well, even though you don't use it. This is because DF can read registers 1 through 3 in a single query, where reading 1 and 3 would take 2. It is often, and probably especially in your case, beneficial even if you end up reading two to three times as many tags as you need.

Next, you need to slow down your Timing on your channels. Take the # of queries required to read all your channels, and multiply by 80ms and this is how long it will take to cycle through them all. The Timing interval needs to be bigger than that number or DF won't be able to keep up.

If you are doing output, then you have an additional problem because you need space in your queries to perform the output. In this case you may have to stagger out your reads by putting them on different Offsets. But, before we get into that, lets look at the first few things I mentioned.

Link to comment
Share on other sites

  • 3 weeks later...

Hi,

I'm getting the exact same problem.

I've tried slowing down the timing to 2 secs but this only seems to slow the rate of port locked messages. I'm pretty sure the hardware is fast enough since I've tested it using Modbus scanner at 0.25 secs and works ok.

I have 3 blocks of MB TCP registers to read, each block consisting of 1 reg, 5 regs and 3 regs. These use MB command Read Input U16 (4). I also have 2 blocks of regs to write with 5 and 3 regs respectively. These use MB command Set Register S16 (16). The write blocks are written to approx 1 per sec by sequences running continuously.

Any ideas of where to start?

Regards

Andrew

Link to comment
Share on other sites

I would just put all your I/O in a sequence. You can still use channels. Just put all channels into different channel groups. Then in the sequence that does the control, do the reads as well using the:

channel.readgroup("channelGroup")

function, replacing channelGroup with the name of the group. Only put input channels in a channel group that you read this way. By putting all your I/O for the modbus in one sequence, you make it all sequential and eliminate any port locked issues.

Link to comment
Share on other sites

Something weird is happening.

I started making changes as suggested and first set all the timing to 0, except 1 input register which I left at 1sec. Now I'm still getting port locked message, once a second. I haven't implemented the sequence read of other channels yet so the only device access is this single channel.

Is it possible there is a problem in the MB device driver. I'm using latest 5.87 with builtin MB TCP device. I've included the ctl doc if it's worth you checking it out.

Andrew

0038-008.ctl

Link to comment
Share on other sites

There is a password on the file. Email if you don't want to post it.

Its also possible that the port was locked before you made the changes and the system is just in a locked state. You can manually unlock by restarting of course, or doing:

device.myDevice.unlockPort()

at the command/alert window.

No, there is nothing wrong with the MB device driver that I know of. It hasn't changed in quite a while.

Link to comment
Share on other sites

  • 3 months later...

I would just put all your I/O in a sequence. You can still use channels. Just put all channels into different channel groups. Then in the sequence that does the control, do the reads as well using the:

channel.readgroup("channelGroup")

function, replacing channelGroup with the name of the group. Only put input channels in a channel group that you read this way. By putting all your I/O for the modbus in one sequence, you make it all sequential and eliminate any port locked issues.

Will the channel.readgroup("channelGroup") read the registeries as a block or timed as defined in the group (based on the timimg offset)?

Can you write to registeries in a similar way (say a separate "write" group) for things like resetting a registery value the first day of the month?

Also, can I set the timing in a channel group to "0" then use a sequence to run/poll the group based on sequence timing? (looking for confirmation here). I want to know it works before I try it, I have live values reporting up to DAQconnect I want to minimize any disruption.

-Greg

Link to comment
Share on other sites

channel.readGroup() will immediately trigger the read of all the channels in the group. It is only for input channels, and typically only used when those channels have a timing of 0. It allows you to control the polling of groups of channels from script rather than using Channel Timing, which has a lot of advantages.

As for output, no there isn't a short way to control a block of outputs, though I believe if you do readGroup() on a bunch of output channels it will actually set them to 0 (this may not be supported in the future, so I'd avoid doing it) but you could always cycle through the channels programmatically. Just use channel.listAll("groupName") to get a list of your output channels (put all your output channels in their own group). Then loop through the result and use execute() to run a formed up string that sets the value to 0.

Link to comment
Share on other sites

  • 2 weeks later...

Would on of the advantages be that if the "port locup" or "timeout" occurs (which I am getting a lot, even with an offset of .8 sec), will a scrip continue running and try to read the channel group instead of stop? I am getting a new piece of equipment that is not so much of a piece of junk (acturally has buffering for ModbusTCP), but I need to make what I have right now work as best I can.

When DF gets fed up, communications with the ModbusTCP "gateway" (if you can call it that) just stops reading the channel goup, I can see it when watching the comm monitor... just stops. The only way I can get it to stat up again is to restart DF. I am guessing that using a script will continue banging away at the crappy gateway until it responds.

Is this a good guess?

Thanks

Link to comment
Share on other sites

All I did was a simple sequence with this:

while(1)

channel.readgroup("mychannelgroup")

delay(7)

endwhile

It's pretty simple, is there anything else I should include in this sequence to read the channel goup? The registers are not configured in a block right now (need to do that soon) so I polling 7 or so different registers. Would it be easier to take, say a block of 40 values than try and pick up 7 separate registery values?

Thanks

Link to comment
Share on other sites

ReadGroup should never fail, even if there is a timeout. To determine if it is successful, you usually have to look at the timestamp of one of the channels and see if its newer than the time you called readGroup():


private starttime = systime()
channel.readGroup("mychannelGroup")
if (mychannel.time[0] < starttime)
// failure!
endif

[/CODE]

The idea behind using readgroup for you is to put all your comms into a single sequence. So, after doing readgroup(), you'd then change any outputs you want to do.

As for the register blocking, yes, if you have 7 registers of the same type (i.e. holding register U16), that are within a block of 40 or so registers, its probably faster to read all 40 registers and pull out the 7 you want then to read 7 different times. It depends, however, on the hardware and its response time. You can tell what that is by looking at the comm monitor with tx/rx times enabled and look at the difference between tx and rx.

Link to comment
Share on other sites

Just to confirm, creating a block of channels to read means I need to create a channel for each registry in the block (not just the ones I want to use). There is no shortcut for getting registery channels, say 1002 through 1180, is there?

I am using Read Holding Float R Words (3), its what worked for floating point values. When I read the group, DF will optimze the request in one communication, if I have the fiming and offset set to "0" zero.

I am assuming that any offset value would be included in the chanel.readGroup("mychannelgroup") when the ModbusTCP device is sent a request.

Link to comment
Share on other sites

Creating a block of channels means exactly what you said, you create a bunch of channels with consecutive channel #'s (remembering to skip by 2 if its float as in your case or 32 bit integer). Name the channels you don't want something like junk1, junk2, etc. DF will optimize the read into one. The offset value has no affect when using ReadGroup(). Its only used in conjunction with TIming.

The alternative is to simply use script:

device.myDevice.ReadHoldingFloatRWords(1, 1002, 178)

but note that the above line won't work because ModbusRTU doesn't allow you to read that many registers in a single block. The max is 62 floats, so you'll have to change the 178 to 62 and adjust accordingly.

See section 16.9.5 in the user's guide to see an example of using script to actually poll and stick the result in channels.

Link to comment
Share on other sites

Archived

This topic is now archived and is closed to further replies.