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. [i]slave-server-ex.py/i 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? * [i]slave-server-ex.py/i - https://pastebin.com/BWA9cE1i * ExampleMachine_1 (modified version) - https://pastebin.com/qWcnkTsT
Here is the answer from the library developer: [quote]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. [/quote]I hope this helps. .
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
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'
Thanks for the update. I have passed this information to the developers of that library, who are investigating this problem.
Here is the reply from the library developers: [quote]Please try to the the input tUpdateTime of the MB_TCP_FC3. For example 1 sec.[/quote]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 Martin, It seems to work that way. [quote]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.[/quote] Thanks again, will contact there next time.