Write User-defined Data Types More Easily

When communicating a PLC with external peripherals you often get a size in bytes of the data that is to be transferred, e.g., 100 Bytes, and within that array of bytes you can find the memory addresses that that specific device sends and receives, which normally contains several different data types.

To address the fields you could just make an ARRAY[0..100] OF BYTE and address the bits and bytes directly, the downside is that to anyone unfamiliar with that specific device, or when the amount of attributes is large, it will become confusing.

Instead of doing that, I like to create UDTs that contain each field within the array separate, after all, it is much clearer to make sense of a rung that energizes coil PlcToVisionSys.Trigger that of a coil PlcToVisionSys[63].0. The downside is that the setup takes a bit more effort, as you have to define all of the fields that you are going to use and make sure that the entire data type amounts to 100 Bytes or whatever size is.

UDT generator

To make the process a little easier, I wrote a small script that makes it a little more effortless.

What it does

  • Checks for duplicate names.
  • Re-writes the name in pascal case.
  • Optionally prefixes the name with the data type abbreviation (hungarian notation).
  • Sums the size of each object to get the size of the UDT.
  • Indicates the byte in which each object is located.

To use it:

  1. Install python.
  2. Clone the repo.
  3. Define the data type according to the peripheral’s manual. I recommend using spreadsheet software.
    • There is a sample file in the repo that I wrote for a keyence module.
    • Fields are not case sensitive and can contain spaces (they are removed by the script).
    • Name, size and array size can be left blank. Sizes default to 1; blank names are treated as an unused field and renamed to _ReservedN.
    • Name is the name you want the attribute to have.
    • Type is the data type of the attribute, there is a list of the accepted data types dataTypes.csv, if the data type you want is missing, you can add it there.
    • Size only applies to strings, it is the string size.
    • Array size is to make an attribute of type array, no array is created if the value is 1 or blank.
  4. Run the script (python udtGen.py).
  5. Verify that your definition results in a UDT size that is what your device requires, the script prints the UDT size to the screen.
    • If not, the first column of the udt.csv file contains the start byte and bit of each attribute to help you debug.
  6. You can find your UDT in udt.csv.

Example

I wrote a definition for a keyence DL-EP1 module, which is used to communicate via Ethernet/IP with their X series code scanners.

The table in the manual includes the following table (continued): Data map for the DL-EP1 (continues)

The definition looks like this (continued): Definition table

The script execution and result:

$ python udtGen.py
Size of UDT (bits): 1344
Size of UDT (Bytes.bits): 168.0
Size of UDT (Words.bits): 84.0

The result looks like this (continued): UDT table (result)