epics-modules / ether_ip

EtherIP support for EPICS, supports Allen Bradley PLCs
Other
45 stars 25 forks source link

UINT Support #24

Closed matt-shawsda closed 1 year ago

matt-shawsda commented 1 year ago

Hi, I'm trying to use this module to pull a UNIT value from a PLC, the changes file suggests that this has been added, but when I have set up a record to get this data it flags as an unknown type. Does anyone have any advice? Cheers

kasemir commented 1 year ago

Yes, https://github.com/epics-modules/ether_ip/commit/9cd4d83109553140e25e9a8c0a015e7d825f9468 suggests that it supports UINT. What's the exact data type of the tag on the PLC (UINT? UDINT? USINT?), what's the record type (ai? mbbi? ...) and what's the error message?

matt-shawsda commented 1 year ago

Hi, thanks for your reply The exact data type of the PLC is UINT, the record type is currently int64in but I have also tried ai, longin and mbbi. The error message is: EIP get_CIP_DINT: unknown type 0x00D2 Cheers

kasemir commented 1 year ago

EIP get_CIP_DINT: unknown type 0x00D2

Well, when Basil added support for UINT, he defined T_CIP_UINT = 0x00C7 but your system shows UINT as 0xD2?

The documentation I used to originally implement this doesn't list any "unsigned" data types at all:

Screen Shot 2022-11-28 at 2 51 29 PM

Looks like we need better documentation of the protocol.

kasemir commented 1 year ago

This python implementation also uses 0xC7 for UINT: https://docs.pycomm3.dev/en/latest/api_reference/data_types.html

In there, data type 0xD2 would be a "WORD" type, 16 bit. So both UINT and WORD are 16 bit unsigned integers, but different type names. Can you change between WORD and UINT on your PLC tag type?

matt-shawsda commented 1 year ago

Sorry my bad, that should have said 0x00C7, not 0x00D2

kasemir commented 1 year ago

Try ai record once more after applying this change:

diff --git a/ether_ipApp/src/ether_ip.c b/ether_ipApp/src/ether_ip.c
index dda1228..25276de 100644
--- a/ether_ipApp/src/ether_ip.c
+++ b/ether_ipApp/src/ether_ip.c
@@ -1251,6 +1251,7 @@ eip_bool get_CIP_DINT(const CN_USINT *raw_type_and_data,
             *result = (CN_DINT) vs;
             return true;
         case T_CIP_INT:
+        case T_CIP_UINT:
             unpack_UINT(buf, (CN_UINT *)&vi);
             *result = (CN_DINT) vi;
             return true;
matt-shawsda commented 1 year ago

That has worked thank you very much. I don't suppose you have a solution for using vendor specific datatypes? I'm also trying to pull some ENUMS (0x0007) from an omron PLC. Thanks again for your help

kasemir commented 1 year ago

At this time we don't support ENUMS or other custom data types. Support could be added if their format were documented, but note that you probably want to avoid reading some individual ENUM anyway. The amount of time for reading one INT or an array of INT[40] is the same, while reading 40 separate INT basically takes 40 times as long as reading a single INT. So you really want to combine your data into "transfer arrays", allowing the driver to read/write the whole array in one transaction.

See "Allen Bradley PLCs" on https://controlssoftware.sns.ornl.gov/training/2022_USPAS/ or https://github.com/epics-modules/ether_ip/blob/master/Manual.md#epics-record-guidelines