PLC Input and Output
Experior.Core.Communication.PLC.Input and Experior.Core.Communication.PLC.Output are classes used to communicate with a PLC.
When they are added to an assembly and made available through a property in the Property window then the Experior user will be able to link the Input with an available connection and specify the address or Byte/Bit depending on the Size. By default this is DataSize.BOOL and hence corresponds with one bit.
You can obtain the corresponding connection through the Connection property and get the address/byte/bit through the properties Byte and Bit (in case the Size is not a DataSize.BOOL the starting address can be found in the Byte property and the Bit property will be “None”).
DataSize Size
The Size property returns what type of data is defined to be exchanged using Input/Output. By default this is DataSize.Bool.
Other possible values are:
DataSize.BYTE this is a single byte (8bits)
DataSize.WORD this is unsigned 16 bits
DataSize.INT this is signed 16 bits
DataSize.DWORD this is unsigned 32 bits
DataSize.DINT this is signed 32 bits
DataSize.STRING this is an array of characters
DataSize.ARRAY this is an array of bytes
DataSize.FLOAT this is a floating point
DataSize.REAL this is a floating point
DataSize.REAL32 this is a signed 32 bits
DataSize.LINT this is a signed 64 bits
DataSize.LREAL this is a 64 bit floating point
DataSize.LWORD this is unsigned 64 bit
DataSize.SINT this is a signed 8 bit
When the Size property is either DataSize.STRING or DataSize.ARRAY then the length of the string/array can be specified in the Length property.
In the example below the creation of different input output objects is illustrated. In addition, the usage of events to react upon receiving of input and sending of a string messages is shown.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Media;
using System.Xml.Serialization;
using Experior.Core.Assemblies;
using Experior.Core.Communication.PLC;
using Experior.Interfaces;
[Serializable]
[XmlType(TypeName = "Experior.Catalog.ExampleAssemblies.ExampleInputOutputInfo")]
public class ExampleInputOutputInfo : AssemblyInfo
{
// we add our Output and Input objects into the corresponding info object of
// the assembly so that is completely saved (serialised) and restored (deserialised)
// when saving and loading the model it is in.
public Output outputbit;
public Output outputdata;
public Input inputbit;
public Input inputdata;
public int maxnumberofcharacters = 12;
}
public class ExampleInputOutput : Assembly
{
private ExampleInputOutputInfo info;
public ExampleInputOutput(ExampleInputOutputInfo info)
: base(info)
{
if (info.outputbit == null)
{
//create Output object by default the size is one bit
info.outputbit = new Output();
// give it a description
info.outputbit.Description = "Block/Unblock";
}
//add the output to the environment so that it becomes visible in the Output window
Add(info.outputbit);
// send the initial value
// 0 when NoNC is Normally Open
// 1 whent NoNC is Normally Closed
info.outputbit.Off();
if (info.outputdata == null)
{
info.outputdata = new Output();
info.outputdata.Description = "Send Barcode";
}
info.outputdata.Size = DataSize.STRING;
info.outputdata.Length = MaxNumberOfCharacters;
//add the output to the environment so that it becomes visible in the Output window
Add(info.outputdata);
// create a Input object to receive a signal (usually from the PLC)
if (info.inputbit == null)
{
info.inputbit = new Input();
info.inputbit.Description = "SignalA";
}
info.inputbit.On += new Input.OnEvent(inputbit_On);
info.inputbit.Off += new Input.OnEvent(inputbit_Off);
info.inputbit.OnNoNcChanged += new Register.NoNcChangedEvent(inputbit_NoNcChanged);
//add the input to the environment so that it becomes visible in the Input window
Add(info.inputbit);
// create a Input object to receive a signal (usually from the PLC)
if (info.inputdata == null)
{
info.inputdata = new Input();
info.inputdata.Description = "LoadDestination";
}
// we will receive a string of maximum MaxNumberOfCharacters
info.inputdata.Size = DataSize.STRING;
info.inputdata.Length = MaxNumberOfCharacters;
info.inputdata.OnReceived += new Input.ReceivedEvent(inputdata_Received);
//add the input to the environment so that it becomes visible in the Input window
Add(info.inputdata);
}
void inputdata_Received(Input sender, object value)
{
if (value != null)
{
// because inputdata.Size = DataSize.STRING the value we receive will be a string so we can cast it to a string
string data = (string)value;
Experior.Core.Environment.Log.Debug.Write("Received " + data);
Experior.Core.Environment.Log.Write("Received " + data);
}
Experior.Core.Environment.Diagnostic.Message("Inputdata was defined at address " + sender.ByteNo);
Experior.Core.Environment.Diagnostic.Message("Inputdata has value " + sender.Value);
}
void inputbit_Off(Input sender)
{
// this will be called when we received an Off message for the input bit
// this is 0 when NO (NormallyOpen) or 1 when NC (Normally Closed)
Experior.Core.Environment.Diagnostic.Message("Input " + sender.ToString() + " off value " + sender.Value, System.Windows.Media.Colors.Green, Experior.Core.Environment.DiagnosticAction.STICKY, Experior.Core.Environment.Signs.Warning);
}
void inputbit_On(Input sender)
{
// this will be called when we received an Off message for the input bit
// this is 0 when NO (NormallyOpen) or 1 when NC (Normally Closed)
Experior.Core.Environment.Diagnostic.Message("Input " + sender.ToString() + " on value " + sender.Value, System.Windows.Media.Colors.Green, Experior.Core.Environment.DiagnosticAction.TEMPORARY, Experior.Core.Environment.Signs.Check);
// send a message to info.outputdata
OutputData.Send("Hello World!");
}
void inputbit_NoNcChanged(IRegister sender)
{
Experior.Core.Environment.Diagnostic.Message("Input " + sender.ToString() + " changing NO/NC value to " + sender.NormallyClose, System.Windows.Media.Colors.Green, Experior.Core.Environment.DiagnosticAction.ALARM, Experior.Core.Environment.Signs.None);
Experior.Core.Environment.Diagnostic.Message("Input was defined for byte " + ((Register)sender).ByteNo + " and bit " + sender.BitNo);
}
public override void Dispose()
{
if (((ExampleInputOutputInfo)info).inputbit != null)
{
((ExampleInputOutputInfo)info).inputbit.On -= new Input.OnEvent(inputbit_On);
((ExampleInputOutputInfo)info).inputbit.Off -= new Input.OnEvent(inputbit_Off);
((ExampleInputOutputInfo)info).inputbit.OnNoNcChanged -= new Register.NoNcChangedEvent(inputbit_NoNcChanged);
}
if (((ExampleInputOutputInfo)info).inputdata != null)
{
((ExampleInputOutputInfo)info).inputdata.OnReceived -= new Input.ReceivedEvent(inputdata_Received);
}
base.Dispose();
}
public Input InputBit
{
get { return ((ExampleInputOutputInfo)info).inputbit; }
set { ((ExampleInputOutputInfo)info).inputbit = value; }
}
public Input InputData
{
get { return ((ExampleInputOutputInfo)info).inputdata; }
set { ((ExampleInputOutputInfo)info).inputdata = value; }
}
public Output OutputBit
{
get { return ((ExampleInputOutputInfo)info).outputbit; }
set { ((ExampleInputOutputInfo)info).outputbit = value; }
}
public Output OutputData
{
get { return ((ExampleInputOutputInfo)info).outputdata; }
set { ((ExampleInputOutputInfo)info).outputdata = value; }
}
public int MaxNumberOfCharacters
{
get { return ((ExampleInputOutputInfo)info).maxnumberofcharacters; }
set { ((ExampleInputOutputInfo)info).maxnumberofcharacters = value; }
}
public override string Category
{
get { return "ExampleInputOutput"; }
}
public override ImageSource Image { get; } = Common.EmbeddedImageLoader.Get("Cube");
}