-
Notifications
You must be signed in to change notification settings - Fork 11
Attribute handled reading
In order to automatically poll all the registers you need to read back from the PLC and simultaniously handle the communication flow with the PLC you have the following options:
- Manually registering all registers and reading them back
- Deriving from a class that handles all the boilerplate for you
This page shows how to handle the second option
This feature reduces boilerplate code for reading and writing every single register of your PLC. Therefore makes it more read- and maintainable.
If you define a property the library will try to convert it to an IEC type and read it back as fast as possible.
In addition to that, every register bound property implements INotifyPropertyChanged for easy WPF UI updates.
Create a new class that derives from RegisterCollectionBase and create your register types in there.
⚠ Important Note: When setting the property names make sure they dont overlap with manually added register names
Your type definitions get automatically converted into the correct PLC values. Every register you want to poll needs an
[Register()] attribute in which you can define detailes on what address the register is located in the PLC and as which type it should be read back.
Your options for the attributes are:
If just the address is defined the type of the property needs to be one of the following numerical ones
| C# Type | PLC Type | Size | Address Prefix |
|---|---|---|---|
| short | INT/WORD | 16bit | DT |
| ushort | UINT/WORD | 16bit | DT |
| Enum | INT/WORD | 16bit | DT |
| int | DINT/DWORD | 32bit | DDT |
| uint | UDINT/DWORD | 32bit | DDT |
| float | REAL/DWORD | 32bit | DDT |
| TimeSpan | TIME/DWORD | 32bit | DDT |
//the memory adress of a normal DT or DDT area register
[Register(7000)]Registers types include inputs outputs and internal relays,
if no special type is defined and the property type is bool its always a R type register
//the memory adress of a R, X, or Y type register (relays and internal relays)
[Register(100, RegisterType.R)]
//example for input X0
[Register(0, RegisterType.X)]
//example for output Y9
[Register(9, RegisterType.Y)]Special combinations include inputs and outputs for example XD or YA
//the input contact XD of the PLC
[Register(RegisterType.X, SpecialAddress.D)]Strings need an DT adress and a predifined length
//corresponds to a DT1101 - DT1104 string register in the PLC with (STRING[4])
[Register(1101, 4)]You can also define an enum and let the library assign it
public enum CurrentState {
Undefined = 0,
State1 = 1,
State2 = 2,
}
//this will read the integer in DT50 as an enum
[Register(50)]
public CurrentState TestEnum { get; set; }You have the option to read bytes or words bitwise (for status bytes etc). You have to options:
As a BitArray
[Register(7010)]
public BitArray TestBitRegister { get; set; }As a single bit
//register 7010 is a WORD type in the PLC and want bit index 9 to be read
//also we have to define the bitcount of the target address
[Register(7010, 9, BitCount.B16)]
public bool BitValue { get; set; }using System;
using System.Collections;
using MewtocolNet;
using MewtocolNet.RegisterAttributes;
public class YourRegisterClass : RegisterCollectionBase {
//corresponds to a R100 boolean register in the PLC
[Register(100, RegisterType.R)]
public bool TestBool1 { get; private set; }
//corresponds to a XD input of the PLC
[Register(RegisterType.X, SpecialAddress.D)]
public bool TestBoolInputXD { get; private set; }
//corresponds to a DT1101 - DT1104 string register in the PLC with (STRING[4])
[Register(1101, 4)]
public string TestString1 { get; private set; }
//corresponds to a DT7000 16 bit int register in the PLC
[Register(7000)]
public short TestInt16 { get; private set; }
//corresponds to a DTD7001 - DTD7002 32 bit int register in the PLC
[Register(7001)]
public int TestInt32 { get; private set; }
//corresponds to a DTD7001 - DTD7002 32 bit float register in the PLC (REAL)
[Register(7003)]
public float TestFloat32 { get; private set; }
//corresponds to a DT7005 - DT7009 string register in the PLC with (STRING[5])
[Register(7005, 5)]
public string TestString2 { get; private set; }
//corresponds to a DT7010 as a 16bit word/int and parses the word as single bits
[Register(7010)]
public BitArray TestBitRegister { get; private set; }
//corresponds to a DT1204 as a 16bit word/int takes the bit at index 9 and writes it back as a boolean
[Register(1204, 9, BitCount.B16)]
public bool BitValue { get; private set; }
//corresponds to a DT7012 - DT7013 as a 32bit time value that gets parsed as a timespan (TIME)
//the smallest value to communicate to the PLC is 10ms
[Register(7012)]
public TimeSpan TestTime { get; private set; }
}⚠ This step is needed in order for attribute handling to work
Attach the register collection object and auto poller to the interface before calling the connect method
//setting up a new PLC interface and register collection
MewtocolInterface interf = new MewtocolInterface("192.168.115.5");
YourRegisterClass registers = new YourRegisterClass();
//attaching the register collection and an automatic poller
interf.WithRegisterCollection(registers).WithPoller();⚠ When writing to registers never use the property set method, always use one of the SetRegister() methods
Make sure the value you want to write is casted to the correct data type and use one of the methods provided:
//adds 10 each time the plc connects to the PLCs INT register
interf.SetRegister(nameof(registers.TestInt16), (short)(registers.TestInt16 + 10));//adds 10 each time the plc connects to the PLCs INT register and awaits the operation result
var res = await interf.SetRegisterAsync(nameof(registers.TestInt16), (short)(registers.TestInt16 + 10));
if(res) {
Console.WriteLine("Register was set");
}