Open Jul-Sto opened 1 year ago
Oh, that seems to be a bug that was introduced with #40. I will look into it and get back to you.
Can you please check if there are any warnings or errors in the log?
I'm not getting any warnings or errors.
The output for addresses 356, 364, 368 and 360 doesn't change, it's always [4210752250] when reading via read_plc_memory()
function.
Ok, this seems to be more of a problem with the documentation than with th e code.
To get the same results with read_plc_memory
and read_data_path
you have to adjust for the actual size of the data type in memory. The current implementation of read_plc_memory
is taking care of that but the data path doesn't since it is decoded on the control. A double word (DWORD) is four bytes long, therefore the address has to be multiplied by four.
Example:
for mem_address in [0, 1, 2, 4, 8, 12, 68, 69, 151, 300, 368]:
v1 = lsv2.read_plc_memory(mem_address, pyLSV2.MemoryType.DWORD, 1)[0]
v2 = lsv2.read_data_path("/PLC/memory/D/%d" % (mem_address * 4))
assert v1 == v2
WHEN im trying this print("## double word: {}".format(con.read_plc_memory(8016, MemoryType.DWORD, 50))), return only 0 values i dont know why,this is the value in the cnc +66977274
I am seeing this same problem just with WORD as well, both calls worked and returned the same non-zero value in 0.7.7 but the latest versions are hitting this.
>>> con.read_plc_memory(39416, mem_type=MemoryType.WORD)
DEBUG:LSV2 Client:system parameters already in memory, return previous values
DEBUG:LSV2 TCP:telegram to transmit: command CMD.A_LG payload length 9 bytes data: bytearray(b'\x00\x00\x00\tA_LGPLCDEBUG\x00')
DEBUG:LSV2 TCP:received block of data with length 8
DEBUG:LSV2 Client:expected response received: RSP.T_OK
DEBUG:LSV2 Client:login executed successfully for login PLCDEBUG
DEBUG:root:memory type allows 126 elements per telegram, split request into 1 group(s)
DEBUG:root:current transfer group 0 has 1 elements
DEBUG:LSV2 TCP:telegram to transmit: command CMD.R_MB payload length 5 bytes data: bytearray(b'\x00\x00\x00\x05R_MB\x00\x0140\x02')
DEBUG:LSV2 TCP:received block of data with length 10
DEBUG:LSV2 Client:expected response received: RSP.S_MB
DEBUG:root:read 1 value(s) from address 39416
DEBUG:root:read a total of 1 value(s)
[0]
>>> con.read_data_path("/PLC/memory/W/39416")
DEBUG:LSV2 TCP:telegram to transmit: command CMD.A_LG payload length 5 bytes data: bytearray(b'\x00\x00\x00\x05A_LGDATA\x00')
DEBUG:LSV2 TCP:received block of data with length 8
DEBUG:LSV2 Client:expected response received: RSP.T_OK
DEBUG:LSV2 Client:login executed successfully for login DATA
DEBUG:LSV2 TCP:telegram to transmit: command CMD.R_DP payload length 24 bytes data: bytearray(b'\x00\x00\x00\x18R_DP\x00\x00\x00\x00\\PLC\\memory\\W\\39416\x00')
DEBUG:LSV2 TCP:received block of data with length 14
DEBUG:LSV2 Client:expected response received: RSP.S_DP
INFO:LSV2 Client:successfully read data path: \PLC\memory\W\39416 and got value '21'
21
@npalmerDNX as mentioned in an earlier comment, the addressing works different between the data_path and plc_memory. In the case of a WORD, the factor is two.
In earlier versions of pyLSV2 the calculation of the correct memory address of the read_plc_memory function was wrong which lead to an offset. This meant that bigger chunks of memory returned broken values. For read_data_path the calculation of the offset has to be done by the application.
I am including 2 screenshots of behavior that I am seeing and trying to validate against. I used the Inventcom testing tool for PLC data and noticed that my W20 shows 0 and W40 show 8.
I ran some test code using the pyLSV2 library to see if I could map those properly, but I noticed that the PLC call in the library returns an 8 not a 0 where as the datapath W20 instance (without changing the memory address like you show above) results in 0. If I apply the address adjustment like you mentioned it would get getting datapath W40 which is 8. I believe that the memory addressing used for the read_plc_memory is double the value that it should be.
def scan_plc(con, start=10000, end=19999):
results = []
for wnum in range(start, end, 1):
count = con.read_plc_memory(first_element=wnum, mem_type=MemoryType.WORD)
print(f"PLC W{wnum} = {count}")
results.append((wnum,count))
return results
def scan_datapath(con, start=10000, end=19999):
results = []
for wnum in range(start, end, 1):
if (wnum % 2) != 0:
continue
count = con.read_data_path(f"/PLC/memory/W/{wnum}")
print(f"Datapath W{wnum} = {count}")
results.append((wnum,count))
return results
res = scan_datapath(conObj, 10, 42) Datapath W10 = 0 Datapath W12 = 30776 Datapath W14 = 25901 Datapath W16 = 0 Datapath W18 = 0 Datapath W20 = 0 Datapath W22 = 0 Datapath W24 = 0 Datapath W26 = 0 Datapath W28 = 0 Datapath W30 = 0 Datapath W32 = 2 Datapath W34 = 0 Datapath W36 = 0 Datapath W38 = 8 Datapath W40 = 8 res = scan_plc(conObj, 10, 42) PLC W10 = [0] PLC W11 = [0] PLC W12 = [0] PLC W13 = [0] PLC W14 = [0] PLC W15 = [0] PLC W16 = [2] PLC W17 = [0] PLC W18 = [0] PLC W19 = [8] PLC W20 = [8] PLC W21 = [0] PLC W22 = [0] PLC W23 = [32767] PLC W24 = [0] PLC W25 = [0] PLC W26 = [0] PLC W27 = [0] PLC W28 = [0] PLC W29 = [0] PLC W30 = [0] PLC W31 = [0] PLC W32 = [0] PLC W33 = [0] PLC W34 = [0] PLC W35 = [0] PLC W36 = [0] PLC W37 = [0] PLC W38 = [0] PLC W39 = [0] PLC W40 = [0] PLC W41 = [0]
This is very strange. If you look at https://github.com/drunsinn/pyLSV2/blob/dc06e43c1f826be84169fb6b6058f804fc689688/tests/test_plc_read.py#L112 you can see the test I added to make sure the memory addressing works as intended. I would have expected this test to fail if there was a problem. Even changing the list of more or less random values to range(0, 500)
for all three tests still does not fail.
I think you also have a bit of a problem in your code. The modulo comparison basically skips every second element which results in an offset. Take a look at this and its output:
import pyLSV2
lsv2 = pyLSV2.LSV2("192.168.56.102", port=19000, timeout=5, safe_mode=False)
lsv2.connect()
for wnum in range(0, 42, 1):
v1 = lsv2.read_plc_memory(first_element=wnum, mem_type=pyLSV2.MemoryType.WORD)[0]
if (wnum % 2) == 0:
v2 = lsv2.read_data_path(f"/PLC/memory/W/{wnum}")
else:
v2 = "skipp"
v3 = lsv2.read_data_path(f"/PLC/memory/W/{wnum*2}")
print(f"Address {wnum:>5}: PLC {v1:>7} - DP*1 {v2:>7} - DP*2 {v3:>7}")
Address 0: PLC 0 - DP*1 0 - DP*2 0
Address 1: PLC 0 - DP*1 skipp - DP*2 0
Address 2: PLC 256 - DP*1 0 - DP*2 256
Address 3: PLC 770 - DP*1 skipp - DP*2 770
Address 4: PLC 255 - DP*1 256 - DP*2 255
Address 5: PLC 0 - DP*1 skipp - DP*2 0
Address 6: PLC 150 - DP*1 770 - DP*2 150
Address 7: PLC 0 - DP*1 skipp - DP*2 0
Address 8: PLC 0 - DP*1 255 - DP*2 0
Address 9: PLC 0 - DP*1 skipp - DP*2 0
Address 10: PLC 0 - DP*1 0 - DP*2 0
Address 11: PLC 0 - DP*1 skipp - DP*2 0
Address 12: PLC 0 - DP*1 150 - DP*2 0
Address 13: PLC 0 - DP*1 skipp - DP*2 0
Address 14: PLC 0 - DP*1 0 - DP*2 0
Address 15: PLC 0 - DP*1 skipp - DP*2 0
Address 16: PLC 0 - DP*1 0 - DP*2 0
Address 17: PLC 0 - DP*1 skipp - DP*2 0
Address 18: PLC 0 - DP*1 0 - DP*2 0
Address 19: PLC 0 - DP*1 skipp - DP*2 0
Address 20: PLC 0 - DP*1 0 - DP*2 0
Address 21: PLC 0 - DP*1 skipp - DP*2 0
Address 22: PLC 10080 - DP*1 0 - DP*2 10080
Address 23: PLC 0 - DP*1 skipp - DP*2 0
Address 24: PLC 0 - DP*1 0 - DP*2 0
Address 25: PLC 0 - DP*1 skipp - DP*2 0
Address 26: PLC 0 - DP*1 0 - DP*2 0
Address 27: PLC 0 - DP*1 skipp - DP*2 0
Address 28: PLC 0 - DP*1 0 - DP*2 0
Address 29: PLC 0 - DP*1 skipp - DP*2 0
Address 30: PLC 0 - DP*1 0 - DP*2 0
Address 31: PLC 0 - DP*1 skipp - DP*2 0
Address 32: PLC 0 - DP*1 0 - DP*2 0
Address 33: PLC 0 - DP*1 skipp - DP*2 0
Address 34: PLC 0 - DP*1 0 - DP*2 0
Address 35: PLC 0 - DP*1 skipp - DP*2 0
Address 36: PLC 0 - DP*1 0 - DP*2 0
Address 37: PLC 0 - DP*1 skipp - DP*2 0
Address 38: PLC 0 - DP*1 0 - DP*2 0
Address 39: PLC 0 - DP*1 skipp - DP*2 0
Address 40: PLC 0 - DP*1 0 - DP*2 0
Address 41: PLC 0 - DP*1 skipp - DP*2 0
As I see it, by multiplying the address for the data path with two I get the same result as with 'read_plc_memory'. The approach of skipping every other address gives an offset.
I ran your test script and I see that the values of PLC and DP2 are the same, but they are not the representation of what the W# is. I have included the screenshot run at the same time to show that the PLC tool is showing a value that equals DP1 for W20 while the values shown from the test script PLC and DP2 are equal to DP1 of W40 You can see this pattern hold true for W6 PLC, DP2 vs W12 DP1 and W7 PLC,DP2 vs W14 DP1
Address 0: PLC 0 - DP*1 0 - DP*2 0
Address 1: PLC 0 - DP*1 skipp - DP*2 0
Address 2: PLC 0 - DP*1 0 - DP*2 0
Address 3: PLC 0 - DP*1 skipp - DP*2 0
Address 4: PLC 0 - DP*1 0 - DP*2 0
Address 5: PLC 0 - DP*1 skipp - DP*2 0
Address 6: PLC -21487 - DP*1 0 - DP*2 -21487
Address 7: PLC 25901 - DP*1 skipp - DP*2 25901
Address 8: PLC 0 - DP*1 0 - DP*2 0
Address 9: PLC 0 - DP*1 skipp - DP*2 0
Address 10: PLC 0 - DP*1 0 - DP*2 0
Address 11: PLC 0 - DP*1 skipp - DP*2 0
Address 12: PLC 0 - DP*1 -21487 - DP*2 0
Address 13: PLC 0 - DP*1 skipp - DP*2 0
Address 14: PLC 0 - DP*1 25901 - DP*2 0
Address 15: PLC 0 - DP*1 skipp - DP*2 0
Address 16: PLC 2 - DP*1 0 - DP*2 2
Address 17: PLC 0 - DP*1 skipp - DP*2 0
Address 18: PLC 0 - DP*1 0 - DP*2 0
Address 19: PLC 10 - DP*1 skipp - DP*2 10
Address 20: PLC 10 - DP*1 0 - DP*2 10
Address 21: PLC 0 - DP*1 skipp - DP*2 0
Address 22: PLC 0 - DP*1 0 - DP*2 0
Address 23: PLC 32767 - DP*1 skipp - DP*2 32767
Address 24: PLC 0 - DP*1 0 - DP*2 0
Address 25: PLC 0 - DP*1 skipp - DP*2 0
Address 26: PLC 0 - DP*1 0 - DP*2 0
Address 27: PLC 0 - DP*1 skipp - DP*2 0
Address 28: PLC 0 - DP*1 0 - DP*2 0
Address 29: PLC 0 - DP*1 skipp - DP*2 0
Address 30: PLC 0 - DP*1 0 - DP*2 0
Address 31: PLC 0 - DP*1 skipp - DP*2 0
Address 32: PLC 0 - DP*1 2 - DP*2 0
Address 33: PLC 0 - DP*1 skipp - DP*2 0
Address 34: PLC 0 - DP*1 0 - DP*2 0
Address 35: PLC 0 - DP*1 skipp - DP*2 0
Address 36: PLC 0 - DP*1 0 - DP*2 0
Address 37: PLC 0 - DP*1 skipp - DP*2 0
Address 38: PLC 0 - DP*1 10 - DP*2 0
Address 39: PLC 0 - DP*1 skipp - DP*2 0
Address 40: PLC 0 - DP*1 10 - DP*2 0
Address 41: PLC 0 - DP*1 skipp - DP*2 0
I still quite follow your reasoning. According to the memory tables on the control the address values are correct. If you check the screenshot I posted here, word 11 is the same as via the library as on the control.
If you are not happy with the current state you are more than welcome to create pull request for a new function that use another addressing scheme. Please note that since the current implementation works as far as I can see, and some other application might already use it the way it is now, I don't want to break compatibility.
I ran your test against my 530 simulator and I am still seeing the same results where the Address of IDX 20 returns 0 based on the PLC call but IDX10 shows the correct part count value. This also led me to review your screenshot a bit more to see where I was going wrong when I noticed that you were requesting W11 but the screenshot shows that the value is stored in W22 (second line Word 20 Column +2)
I interpreted the blue column numbers a bit differently. Since I have no manual I assume that these numbers count the number of bytes from the start of memory. The increments change when switching between byte, word and double from 1 to 2 to 4 but the line numbers only change when switching from byte to word or double. This lead me to believe that they count the number of bytes instead of the address of the memory value. Again, if you prefer a function that uses the numbering scheme that counts bytes instead of the memory values I have no problem integrating a pull request. The current behavior is not broken, it works for all intents and purposes. Changing the existing behaviour is not a direction I want to take.
Reading PLC memory via memory address like
con.read_plc_memory(356, pyLSV2.MemoryType.DWORD, 1)
returns the following:
when accessing the same addresses via data path at the same time it returns the following:
con.read_data_path("/PLC/memory/D/356")
I'm not sure if I've missed anything, but up to pyLSV2 version 0.7.7 the values were the same.
I've discovered this on an iTNC530 / 606420 04 SP20. Help would be much appreciated.