drunsinn / pyLSV2

A pure Python3 implementation of the LSV2 protocol
MIT License
64 stars 24 forks source link

pyLSV2.err.LSV2InputException: highest address is 15000 but address of last requested element is 26733 #61

Closed MountainKing91 closed 5 months ago

MountainKing91 commented 7 months ago

Hi,

Library: pyLSV2 1.3.3

Controller: TNC-Type: TNC640 NC-Version: 340590 08 SP7 PLC-Version: 17-M008-V01SP11

I am trying to read DWord 26732, which for my TNC 640 holds the actual tool number, and i get this error

>>> print(con.read_plc_memory(26732, lsv.const.MemoryType.DWORD, 1)) Traceback (most recent call last): File "<stdin>", line 1, in <module> File "C:\Users\bernardi\virtual-env\heidenhain\lib\site-packages\pyLSV2\client.py", line 1286, in read_plc_memory raise LSV2InputException( pyLSV2.err.LSV2InputException: highest address is 15000 but address of last requested element is 26733

I checked the source code "const.py", and I am not sure why for DWORD the max elements is

max_elements = self._sys_par.number_of_words / 4

instead of

max_elements = self._sys_par.number_of_words / 2

image

Is this correct? As far as i know 1 DWORD = 2 WORD = 4 BYTE --> if I get a total of 100 words in my controller, I should be able to see them also as 200 bytes or 50 dwords.

This is from the actual SYS_\runtime\PlcDataMarker.txt file in the service data generated by the controller, just to show where I found the memory address: <Global>\NN_DG_TOOL_NUMBER D26732 D=0

Thanks

drunsinn commented 7 months ago

Ho @MountainKing91,

yes, the sizes for WORD and DWORD are correct. The D indicates that it is a double word so two words stuck together.

From your explanation it seems to be the same problem that was discussed in #48. You should be able to get the value you are expecting by reading number 6683 (= 26732 / 4). This is because of a bad assumption on my part on how the addressing of the memory location works.

Technical explanation: We now know that the control has one big memory area shared between all numerical data values (BYTE, WORD, DWORD etc.). Byte 0 together with Byte 1 are the same as Word 0. read_plc_memory takes the size of the value into account so all values can be accessed sequentially. The control instead uses a format like D26732 where the number is the address of the first byte that makes up the actual value. In one of the next releases I will add a new function that accepts the addressing scheme used by the control to reduce the confusion.

MountainKing91 commented 7 months ago

Hi,

We now know that the control has one big memory area shared between all numerical data values (BYTE, WORD, DWORD etc.). Byte 0 together with Byte 1 are the same as Word 0.

Yes, this is also how many PLCs work or used to work (older Siemens models, Delta, etc.). I did not try the read_data_path method so I did not double check what I was reading, but I noticed something looked like being "offset" comparing what I read with pyLSV2 and the actual table in the controller. Tomorrow I should have access to the machine and I will try read_plc_memory according to your advice and also read_data_path.

Thanks for your detailed explanation.

drunsinn commented 5 months ago

The latest release, v1.4 introduced a new function read_plc_address(self, address: str) which adds support for using the nativ addressing scheme. This should behave more like what you expected at first. see #68