stlehmann / pyads

Python wrapper for TwinCAT ADS
MIT License
253 stars 94 forks source link

PyADS (3.3.4) Library to read Data from Beckhoff PLC - pyads.pyads_ex.ADSError Parameter Size not correct (1797) #232

Closed AjayBile closed 3 years ago

AjayBile commented 3 years ago

Hi, I want to communicate with the Beckhoff PLC, but i am facing an issue while reading multiple register using "read_list_by_name" pyads api. Reference code :

import pyads
import time
import random 

REMOTE_AMS_NET_ID = '********' #PLC's AMS NET ID
REMOTE_PLC_IP = '*********'       #PLC's IP Address

adr = pyads.AmsAddr(REMOTE_AMS_NET_ID, pyads.PORT_TC3PLC1)
pyads.add_route(REMOTE_AMS_NET_ID, REMOTE_PLC_IP)
plc = pyads.Connection(REMOTE_AMS_NET_ID, pyads.PORT_TC3PLC1, REMOTE_PLC_IP)

var_list = ["GVL_PC_2_PLC.home","GVL_PC_2_PLC.process_complete"]
value = plc.read_list_by_name(var_list)
print(value)

Error Screenshot

Screenshot from 2021-03-25 11-09-17

Please help if you can

Thanks in advance

chrisbeardy commented 3 years ago

Hi, it appears from your screenshot that the code running on line 81, is read_list_by_name(var_list, pyads.PLCTYPE_BOOL). You do not need to provide the type when using read list. Using read_list_by_name(var_list) should be sufficient.

AjayBile commented 3 years ago

Hi, sorry my mistake i was doing some trials and errors so i paste that screenshot... even i tried with the list as well...but i am getting same error. screenshot of the same have attached.

code :

import pyads
import time
import random

REMOTE_AMS_NET_ID = '' #PLC's AMS NET ID
REMOTE_PLC_IP = '*' #PLC's IP Address

adr = pyads.AmsAddr(REMOTE_AMS_NET_ID, pyads.PORT_TC3PLC1)
pyads.add_route(REMOTE_AMS_NET_ID, REMOTE_PLC_IP)
plc = pyads.Connection(REMOTE_AMS_NET_ID, pyads.PORT_TC3PLC1, REMOTE_PLC_IP)

var_list = ["GVL_PC_2_PLC.home","GVL_PC_2_PLC.process_complete"]
value = plc.read_list_by_name(var_list)
print(value)

Screenshot from 2021-03-26 11-36-54

chrisbeardy commented 3 years ago

It also looks like you are missing a call to plc.open() after plc = pyads Connection. Are you working on Linux trying to connect to the PLC or Windows? There may be a route setup issue.

AjayBile commented 3 years ago

Hi @chrisbeardy, Sorry i missed to paste plc.open() statement in above code while putting it in issue...i have used it in my code...but getting the same error...i have attached my code screenshot for your reference...also i am using Linux to connect to PLC...

Screenshot from 2021-03-28 10-07-08

chrisbeardy commented 3 years ago

Have you set up the route from the PLC to the Linux PC, either on the PLC or using the add_route_to_plc function? See https://pyads.readthedocs.io/en/latest/documentation/routing.html#adding-routes-to-a-target

If the routing is correct, can you show me the PLC variable declaration?

AjayBile commented 3 years ago

Hi, yes we have set up the route from PLC to Linux PC on PLC using TwinCAT static Routes. Also we have performed read and write operations on array using read_by_name and write_by_name API. its is working fine also we have tried write_list _by_name and we are able to write multiple values using single command API. but we are not able read multiple values from single command i.e. by using read_list_by_name as shown in above code.

Attaching PLC Variable declaration screenshot

MicrosoftTeams-image (1)

Attched Static Routes screemshot - Ethercat Test is the route name

MicrosoftTeams-image (2)

chrisbeardy commented 3 years ago

If you can succesfully write_list_by_name and read_by_name, I am not sure what is causing this ADS size error. The only last I can think of is you could try is setting cache_symbol_info to False when reading in case the plc symbol changed between a write and a read. But this should not be causing that error on such a small sample where you are creating a new instance of the connection class. Sorry I can not be of further use, what version of TwinCat and pyads are you using? I suggest that this gets logged as a bug, @stlehmann or @pylipp may have a better idea of what could be causing this.

stlehmann commented 3 years ago

@AjayBile did setting the cache_symbol_info to False resolve the issue for you? An I right that both values are Boolean?

rmeister commented 3 years ago

Hi, I'm getting the same error with Pyads 3.3.5 and TwinCAT 2 (2304). ADS route is set up and symbols do exist (read_by_name returns values). Setting cache_symbol_info to False did not resolve the problem.

import pyads

amsTarget = 'xxx'
amsSource = 'xxx'
port = pyads.PORT_TC2PLC1

pyads.set_local_address(amsSource)
plc = pyads.Connection(amsTarget, port)
plc.open()

structure_def = {
    '.aaa[1,1].xxx.yyy' : ('.stCellCom[1,1].xxx.yyy', pyads.PLCTYPE_WORD, 1),
    '.aaa[1,1].xxx.zzz' : ('.stCellCom[1,1].xxx.zzz', pyads.PLCTYPE_WORD, 1)
}

plc.read_list_by_name(['.aaa[1,1].xxx.yyy', '.aaa[1,1].xxx.zzz'], cache_symbol_info=False, structure_defs=structure_def)
plc.read_list_by_name(['.aaa[1,1].xxx.yyy', '.aaa[1,1].xxx.zzz'], cache_symbol_info=False)

grafik

stlehmann commented 3 years ago

@rmeister Does this only happen for nexted variables?

rmeister commented 3 years ago

No, that doesn't seem to matter either.

chrisbeardy commented 3 years ago

I'm wondering if this is a problem that only faces GLOBAL variables

rmeister commented 3 years ago

I don't know too much about PLC programming, but in this example program the variables are non-global I guess?

PROGRAM MAIN
VAR
    FB_Test     : FB_Test;
    FB_InOut        : FB_InOut;
    TOGGEL      : BOOL;
         ARR        : ARRAY [1..800] OF INT;
    PLCVar      : DWORD := 0;
    TP_1        : TP;
END_VAR
chrisbeardy commented 3 years ago

@rmeister yes that would be correct. To access thos vars over ads you would use MAIN.TOGGEL etc.

To create Global vars you create a GVL and/or have the defindtion like:

VAR_GLOBAL
    aGlobalVar : BOOL;
END_VAR

I think only with Twincat2 you can access global variables using the .xxx way, on TwinCAT 3 you would have to say GVL.aGlobalVar replacing GVL with whatever the GVL is called.

rmeister commented 3 years ago

@chrisbeardy thank you for the explanation. I can observe the same behavior for global and local variables.

chrisbeardy commented 3 years ago

it appears this issue has also been found by @ako-kft in #257.

I am wondering if this issue is linux and or PLC platform specific, it appears @AjayBile is using WIndows CE, so I'm wondering if there may be some platform specific byte order / size / 32bit, 64bit isssue occuring somewhere when checking the parameters size?

The classic "it works on my machine", i always use windows 10 64 bit on the beckhoff PLCs and tend to run pyads locally or through a windows remote machine and have never had issues with read list by name.

pylipp commented 3 years ago

Sorry I can't be much of a help here, I don't have access to a TwinCAT installation nor a PLC anymore.

stlehmann commented 3 years ago

@AjayBile Am I assuming right that you are on Linux? I finally have the same problem from a Ubuntu Docker container.

Python 3.8.7 (default, Feb  9 2021, 08:08:20)
[GCC 8.3.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import pyads
>>> pyads.open_port()
30000
>>> pyads.set_local_address("1.2.3.4.1.1")
>>> c = pyads.Connection("172.18.212.61.1.1", 851, "10.18.0.40")
>>> c.open()
2021-09-06T11:17:00+0000 Info: Connected to 10.18.0.40
>>> c.read_state()
(5, 0)
>>> c.read_list_by_name(["MSGW.C0B2_home_pos", "MSGW.C1B1_machine_clear"])
Traceback (most recent call last):
    File "<stdin>", line 1, in <module>
    File "/usr/local/lib/python3.8/site-packages/pyads/ads.py", line 930, in read_list_by_name
return sum_read(self._port, self._adr, data_names, data_symbols)
    File "/usr/local/lib/python3.8/site-packages/pyads/ads.py", line 922, in sum_read
result = adsSumRead(port, adr, data_names, data_symbols, list(structure_defs.keys()))  # type: ignore
    File "/usr/local/lib/python3.8/site-packages/pyads/pyads_ex.py", line 893, in adsSumRead
sum_response = adsSyncReadWriteReqEx2(
    File "/usr/local/lib/python3.8/site-packages/pyads/pyads_ex.py", line 694, in adsSyncReadWriteReqEx2
raise ADSError(err_code)
pyads.pyads_ex.ADSError: ADSError: parameter size not correct (1797).
>>>

I assume it has something to do with the Linux ADS library.

stlehmann commented 3 years ago

I did some Sherlocking with Wireshark: grafik

Seems that the transmitted ReadLength on Linux is bigger than on Windows.

stlehmann commented 3 years ago

Fun fact: c_ulong is longer on Linux than on Windows:

On Linux:

>>> import ctypes
>>> ctypes.sizeof(c_ulong)
8

On Windows:

>>> import ctypes
>>> ctypes.sizeof(c_ulong)
4
ako-kft commented 3 years ago

Thank you, Stefan! Great detective work.

-Adrian

Von: Stefan Lehmann @.> Gesendet: Montag, 6. September 2021 14:14 An: stlehmann/pyads @.> Cc: ako-kft @.>; Mention @.> Betreff: Re: [stlehmann/pyads] PyADS (3.3.4) Library to read Data from Beckhoff PLC - pyads.pyads_ex.ADSError Parameter Size not correct (1797) (#232)

I did some Sherlocking with Wireshark: https://user-images.githubusercontent.com/4641542/132215822-2741ff43-b884-4a00-9a45-d813fd9de2a2.png

Seems that the transmitted ReadLength on Linux is bigger than on Windows.

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/stlehmann/pyads/issues/232#issuecomment-913601114 , or unsubscribe https://github.com/notifications/unsubscribe-auth/AMOMWAJWTLZPWJ3TW7ZNS6DUASWA3ANCNFSM4ZZM543Q . Triage notifications on the go with GitHub Mobile for iOS https://apps.apple.com/app/apple-store/id1477376905?ct=notification-email&mt=8&pt=524675 or Android https://play.google.com/store/apps/details?id=com.github.android&referrer=utm_campaign%3Dnotification-email%26utm_medium%3Demail%26utm_source%3Dgithub . https://github.com/notifications/beacon/AMOMWAIQ4Y6QI557RPVULQ3UASWA3A5CNFSM4ZZM5432YY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOGZ2HEWQ.gif

stlehmann commented 3 years ago

Fixed it with #264 by using a fixed size of 4 bytes instead of ulong.

chrisbeardy commented 3 years ago

Great find Stefan. To satisfy my curiosity I did a quick search. This SO answer seemes to give a good explanation of why they are different

http://stackoverflow.com/questions/384502/ddg#384672

stlehmann commented 3 years ago

Thanks for investigating @chrisbeardy. This brings some light in the darkness 💡