This is a minimal example of B&R PLC simlutor running, and a PC host app connecting to it, reading and writing variables.
The B&R IDE is called Automation Studio, in short AS. The Host app is called Client, developed in .NET in Visual Studio 2022.
The projects intension ins't to demonstrate all the connection possiblities, just the bare minimum.
For the Demo, the PLC has 2 global variables: flag
and gCounter
.
In C++ means, the controller does this:
bool flag;
uint8_t gCounter;
while (true) { // runs forever
if (flag) gCounter++; // can overflow back to 0
}
In AS the global variables are defined at the logical view > Global.var:
VAR
gCounter : USINT;
flag : BOOL := TRUE;
END_VAR
And the program is called Program which has the code file Main.st
.
PROGRAM _INIT
gCounter:=0;
flag :=TRUE;
END_PROGRAM
PROGRAM _CYCLIC
IF flag = TRUE THEN
gCounter := gCounter + 1;
END_IF
END_PROGRAM
PROGRAM _EXIT
(* Nothing happens here *)
END_PROGRAM
The code needs to compile and transfared to the simulator.
The connection between a PLC and a dotnet PC app is by using OPC UA
protocol. This replaces the old (and obsolete) PVI
interface.
Note: why not
PVI
? It isn't supported by modern dotnet, it isn't secure, and it looks as BR doesn't maintain it anymore.OPC UA
is an open protocol adopted by many PLC vendors.
To enable OPC UA
, the PLC server needs to be configured.
Check list:
- Configuration View > your controller > Connectivity > add
OPC UA Nodeset file
- Configuration View > your controller > Connectivity > add
OPC UA Default View file
- Open the new
OPC UA Default view
, find the variables you want to read and write and enable the tags you want. - Physical View > Your controller > right click > configuration > OPC-UA System > Activate
- Physical View > Your controller > right click > configuration > OPC-UA System > Information models > PV > Version > 2.0 (allows reading complex types, ex structs)
The Client App has a simple Winform window that can display the counter, and a checkbox to toggle the flag.
The connection logic is inside PlcClient.BrDevice
. Just follew the Connect()
method and
you'll catch up.
To connect to a variable we need to know its full address, which contains a namespace, the program name and finally the variable name. The variables namespace is 6.
for example if in program MyProgram
the is a variable MyVariable
, the address would be: "ns=6;s=::MyProgram:MyVariable"
.
To connect to a server, there is some certification validation going around,
and for that there are 2 files I copied from the OPC Foundation samples: App.Config
and
Quickstarts.ReferenceClient.Config.xml
.
This demo shows how to transfer structures that exist both in the server and in the client.
They client classes need to reflect the PLC structures, see PlcStructs.cs
.
There is a variable handle IPlcVariableHandle
for reading and writing variables.
It is typesafe, ex. it checks the types match on both sides. Create one by calling
OpcDevice.CreateVariableHandleAsync()
there is more than one option out there:
- unified-automation, commercial.
- QuickOPC, commercial.
- technosoftware, commercial.
- OPCFoundation, I used this one.
https://github.com/joc-luis/OPCUaClient, uses OPCFoundation internally.
- OPC Foundation Forum
- How to activate OPC UA connectivity in B&R mapp View
- OPC UA Simple App
- UaExpert - a client for debugging
- Json Encode/Decoder Usage
- Hadnle PLC not found
- variables from an program, and not global.
PLC | OPC UA | C# |
---|---|---|
BOOL | Boolean | bool |
SINT | SByte | sbyte |
USINT | Byte | byte |
INT | Int16 | short |
UINT | UInt16 | ushort |
DINT | Int32 | int |
UDINT | UInt32 | uint |
LINT | Int64 | long |
ULINT | UInt64 | ulong |
REAL | Float | float |
LREAL | Double | double |
STRING | String | string |
WSTRING | String | string |
TIME | Duration | TimeSpan |
DATE | DateTime | DateTime |
TIME_OF_DAY | Time | TimeSpan |
DATE_AND_TIME | DateTime | DateTime |
BYTE | Byte | byte |
WORD | UInt16 | ushort |
DWORD | UInt32 | uint |
LWORD | UInt64 | ulong |