Store PLCnext CommunityPLCnext on LinkedInPLCnext on Instagram  PLCnext on YouTube Github PLCnext CommunityStore PLCnext Community

  1. argentumbolo
  2. PLCnext Engineer
  3. Friday, 30 July 2021
Hi,
I found unexpected behaviour while tested MB_TCP_FC3 example with PyModbus test server.
It looks like register range request is requested twice for one activisation but second result is not used.

slave-server-ex.py(python3) is example server which generates waves in time.
In order to work with unchanged MB_TCP_FC3 example it always returns 0x07d0 in first position. If requested registers count more or equal to 5 it returns 0x07d0 then 64bit float packed in 4x16bit values then random numbers to fill response.
First time I found the same behaviour in unchanged MB_TCP_FC3 example (only with right IP and port set up) but it works the same way with slightly modified one.

PLC address 192.168.1.10.
pymodbus server is running on Linux(Ubuntu 20.04.2 LTS) with IP:192.168.1.166 on port 5020.
The result of the one button click in HMI is:

bolo@Win10-Home:~/projects/modbus$ python3 slave-server-ex.py
DEBUG:pymodbus.server.sync:Started thread to serve client at ('192.168.1.10', 53932)
DEBUG:pymodbus.server.sync:Client Connected [192.168.1.10:53932]
DEBUG:pymodbus.server.sync:Handling data:
DEBUG:pymodbus.framer.socket_framer:Processing:
DEBUG:pymodbus.server.sync:Client Disconnected [192.168.1.10:53932]
DEBUG:pymodbus.server.sync:Started thread to serve client at ('192.168.1.10', 56043)
DEBUG:pymodbus.server.sync:Client Connected [192.168.1.10:56043]
DEBUG:pymodbus.server.sync:Handling data: 0x0 0x2f 0x0 0x0 0x0 0x6 0x0 0x3 0x0 0x0 0x0 0x1
DEBUG:pymodbus.framer.socket_framer:Processing: 0x0 0x2f 0x0 0x0 0x0 0x6 0x0 0x3 0x0 0x0 0x0 0x1
DEBUG:pymodbus.factory:Factory Request[ReadHoldingRegistersRequest: 3]
DEBUG:pymodbus.datastore.context:validate: fc-[3] address-1: count-1
DEBUG:pymodbus.datastore.context:getValues fc-[3] address-1: count-1
DEBUG:root: -- .getValues(address:1(ignored), count:1) -> Whatever
DEBUG:pymodbus.server.sync:send: [ReadHoldingRegistersResponse (1)]- b'002f0000000500030207d0'
DEBUG:pymodbus.server.sync:Handling data: 0x0 0x30 0x0 0x0 0x0 0x6 0x0 0x3 0x0 0x0 0x0 0x5
DEBUG:pymodbus.framer.socket_framer:Processing: 0x0 0x30 0x0 0x0 0x0 0x6 0x0 0x3 0x0 0x0 0x0 0x5
DEBUG:pymodbus.factory:Factory Request[ReadHoldingRegistersRequest: 3]
DEBUG:pymodbus.datastore.context:validate: fc-[3] address-1: count-5
DEBUG:pymodbus.datastore.context:getValues fc-[3] address-1: count-5
DEBUG:root: -- .getValues(address:1(ignored), count:5) -> Number 62.33024177245201 as ['0x3A2C', '0x5CC6', '0x2A45', '0x404F']
DEBUG:pymodbus.server.sync:send: [ReadHoldingRegistersResponse (5)]- b'00300000000d00030a07d03a2c5cc62a45404f'
DEBUG:pymodbus.server.sync:Handling data: 0x0 0x31 0x0 0x0 0x0 0x6 0x0 0x3 0x0 0x0 0x0 0x5
DEBUG:pymodbus.framer.socket_framer:Processing: 0x0 0x31 0x0 0x0 0x0 0x6 0x0 0x3 0x0 0x0 0x0 0x5
DEBUG:pymodbus.factory:Factory Request[ReadHoldingRegistersRequest: 3]
DEBUG:pymodbus.datastore.context:validate: fc-[3] address-1: count-5
DEBUG:pymodbus.datastore.context:getValues fc-[3] address-1: count-5
DEBUG:root: -- .getValues(address:1(ignored), count:5) -> Number 60.87016928107259 as ['0x1866', '0xB4FE', '0x6F61', '0x404E']
DEBUG:pymodbus.server.sync:send: [ReadHoldingRegistersResponse (5)]- b'00310000000d00030a07d01866b4fe6f61404e'


So, there are two requests from the PLC and two responses from the server...

DEBUG:pymodbus.datastore.context:getValues fc-[3] address-1: count-5
DEBUG:root: -- .getValues(address:1(ignored), count:5) -> Number 62.33024177245201 as ['0x3A2C', '0x5CC6', '0x2A45', '0x404F']
...
DEBUG:pymodbus.datastore.context:getValues fc-[3] address-1: count-5
DEBUG:root: -- .getValues(address:1(ignored), count:5) -> Number 60.87016928107259 as ['0x1866', '0xB4FE', '0x6F61', '0x404E']

...but according to the inspector and HMI PLC takes in account only first one with 62.33024177245201 value.

I tried the same server other ways (like different software requesters) and it always reseived only one request.

So, am I doing something wrong here?

* slave-server-ex.py(python3) - https://pastebin.com/BWA9cE1i
* ExampleMachine_1 (modified version) - https://pastebin.com/qWcnkTsT
Attachments (3)
Martin PLCnext Team Accepted Answer Pending Moderation
0
Votes
Undo
Here is the answer from the library developer:

The MB_TCP_FC3 sends request as long as xActivate is TRUE .
If you just want to send one request please set the xActivate = FALSE after the output xNDR turns to TRUE.
I hope this helps.


.
Phoenix Contact Electronics Headquarters - PLCnext Runtime Product Management and Support
  1. more than a month ago
  2. PLCnext Engineer
  3. # 1
argentumbolo Accepted Answer Pending Moderation
0
Votes
Undo
Hi Martin,

I changed code in order to set xActivate:=false immidiately after xNDR became TRUE (full source):

MB1_STATE#WAITING_FOR_ACTIVE_SECOND:
(* Deactivate FB after first data received *)
IF udtExample.udtMB_TCP_FC3.xNDR = TRUE THEN
udtExample.udtMB_TCP_FC3.xActivate := FALSE;
END_IF;
IF
udtExample.udtMB_TCP_FC3.xActive = TRUE AND
udtExample.udtMB_TCP_FC3.xError = FALSE
THEN
iState := MB1_STATE#CHECK_SECOND_VALUES_READ;
END_IF;

MB1_STATE#CHECK_SECOND_VALUES_READ:
(* Deactivate FB after first data received *)
IF udtExample.udtMB_TCP_FC3.xNDR = TRUE THEN
udtExample.udtMB_TCP_FC3.xActivate := FALSE;
END_IF;
(* Modbus server has to deliver these values! *)
IF
udtExample.udtMB_TCP_FC3.xError = FALSE AND
udtExample.udtMB_TCP_FC3.uiByteCount = UINT#10
THEN
iState := MB1_STATE#DEACTIVATE_F3_SECOND;
END_IF;


But anyway request was performed twice with about 10ms gap:

2021-08-08 21:34:00,400 DEBUG:slave-server-ex.py: -- .getValues(address:1(ignored), count:5) -> Number 79.27187328418321 as ['0x0E46', '0x5F34', '0xD166', '0x4053']
2021-08-08 21:34:00,401 DEBUG:sync.py: send: [ReadHoldingRegistersResponse (5)]- b'00030000000d00030a07d00e465f34d1664053'
...
2021-08-08 21:34:00,411 DEBUG:slave-server-ex.py: -- .getValues(address:1(ignored), count:5) -> Number 79.08051674400849 as ['0x9300', '0x2FB3', '0xC527', '0x4053']
2021-08-08 21:34:00,411 DEBUG:sync.py: send: [ReadHoldingRegistersResponse (5)]- b'00040000000d00030a07d093002fb3c5274053'


Then I added 100ms delay into server emulator code (full source):

# Get values by count ignoring address
def getValues(self, address, count=1):
...
value = ThermometrEmulator.clamp(value, 0.0, 100.0)
# 100ms
time.sleep(0.1)
if count >= 5:
...
return [0x07d0] + [*values16from64f] + [randint(0x0000, 0xffff) for _ in range(count - 5)]
else:
...
return [0x07d0] + [randint(0x0000, 0xffff) for _ in range(count - 1)]


And still I got two requests:

2021-08-08 21:48:06,187 DEBUG:slave-server-ex.py: -- .getValues(address:1(ignored), count:5) -> Number 55.244863790232046 as ['0x82B8', '0xB259', '0x9F57', '0x404B']
2021-08-08 21:48:06,188 DEBUG:sync.py: send: [ReadHoldingRegistersResponse (5)]- b'00030000000d00030a07d082b8b2599f57404b'
...
2021-08-08 21:48:06,299 DEBUG:slave-server-ex.py: -- .getValues(address:1(ignored), count:5) -> Number 54.17356562598424 as ['0xA7F2', '0x65FF', '0x1637', '0x404B']
2021-08-08 21:48:06,300 DEBUG:sync.py: send: [ReadHoldingRegistersResponse (5)]- b'00040000000d00030a07d0a7f265ff1637404b'


It looks like I'm still doing something wrong.

* slave-server-ex2.py(python3) - https://pastebin.com/afLMYnsj
* ExampleMachine_1 (modified version) - https://pastebin.com/0n4cNenU
  1. more than a month ago
  2. PLCnext Engineer
  3. # 2
argentumbolo Accepted Answer Pending Moderation
0
Votes
Undo
Self update:

I moved on Modbus_TCP_9.
Python part exactly the same as in previous message.
ST part from the MB_9 example with modification:
    2020: (* Check values, if uiByteCount = 5 values are read correctly *)
(* Modbus server has to deliver these values! *)
IF udtExample.udtMB_TCP_FC3.xNDR = TRUE THEN
udtExample.udtMB_TCP_FC3.xActivate := FALSE;
END_IF;
IF
udtExample.udtMB_TCP_FC3.xError = FALSE AND
udtExample.udtMB_TCP_FC3.uiByteCount = UINT#10
THEN
xBufferReady := TRUE;
iState := 2100;
END_IF;

According to the debug line udtExample.udtMB_TCP_FC3.xActivate := FALSE activates.

Result is the same:
2021-08-11 19:01:46,150 DEBUG:slave-server-ex.py:  -- .getValues(address:1(ignored), count:5) -> Number 79.37271231017154 as ['0xC037', '0x84BB', '0xD7DA', '0x4053']
2021-08-11 19:01:46,150 DEBUG:sync.py: send: [ReadHoldingRegistersResponse (5)]- b'00090000000d00030a07d0c03784bbd7da4053'
...
2021-08-11 19:01:46,549 DEBUG:slave-server-ex.py: -- .getValues(address:1(ignored), count:5) -> Number 79.8292742456625 as ['0x2246', '0xD449', '0xF512', '0x4053']
2021-08-11 19:01:46,550 DEBUG:sync.py: send: [ReadHoldingRegistersResponse (5)]- b'000a0000000d00030a07d02246d449f5124053'
  1. more than a month ago
  2. PLCnext Engineer
  3. # 3
Martin PLCnext Team Accepted Answer Pending Moderation
0
Votes
Undo
Thanks for the update.
I have passed this information to the developers of that library, who are investigating this problem.
Phoenix Contact Electronics Headquarters - PLCnext Runtime Product Management and Support
  1. more than a month ago
  2. PLCnext Engineer
  3. # 4
Martin PLCnext Team Accepted Answer Pending Moderation
0
Votes
Undo
Here is the reply from the library developers:

Please try to the the input tUpdateTime of the MB_TCP_FC3.
For example 1 sec.
Please note that it is also possible to discuss this issue directly with the library developers using the "Contact" button on the product page in the PLCnext Store.

.
Phoenix Contact Electronics Headquarters - PLCnext Runtime Product Management and Support
  1. more than a month ago
  2. PLCnext Engineer
  3. # 5
argentumbolo Accepted Answer Pending Moderation
0
Votes
Undo
Thanks Martin,
It seems to work that way.

Please note that it is also possible to discuss this issue directly with the library developers using the "Contact" button on the product page in the PLCnext Store.

Thanks again, will contact there next time.
  1. more than a month ago
  2. PLCnext Engineer
  3. # 6
  • Page :
  • 1


There are no replies made for this post yet.
However, you are not allowed to reply to this post.