Coder Social home page Coder Social logo

Comments (13)

drunsinn avatar drunsinn commented on May 14, 2024

Oh, that seems to be a bug that was introduced with #40. I will look into it and get back to you.

from pylsv2.

drunsinn avatar drunsinn commented on May 14, 2024

Can you please check if there are any warnings or errors in the log?

from pylsv2.

Jul-Sto avatar Jul-Sto commented on May 14, 2024

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.

from pylsv2.

drunsinn avatar drunsinn commented on May 14, 2024

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

from pylsv2.

rafasimple avatar rafasimple commented on May 14, 2024

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

from pylsv2.

npalmerDNX avatar npalmerDNX commented on May 14, 2024

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

from pylsv2.

drunsinn avatar drunsinn commented on May 14, 2024

@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.

grafik

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.

from pylsv2.

npalmerDNX avatar npalmerDNX commented on May 14, 2024

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.
image
image

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]

from pylsv2.

drunsinn avatar drunsinn commented on May 14, 2024

This is very strange. If you look at

def test_comapare_values(address: str, timeout: float):
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.

from pylsv2.

npalmerDNX avatar npalmerDNX commented on May 14, 2024

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 DP
1 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

image
image

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

from pylsv2.

drunsinn avatar drunsinn commented on May 14, 2024

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.

from pylsv2.

npalmerDNX avatar npalmerDNX commented on May 14, 2024

image
image
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)

image

from pylsv2.

drunsinn avatar drunsinn commented on May 14, 2024

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.

from pylsv2.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.