This is is a short demonstration of a co-simulation between Siemens PLCSIM Advanced and C#.
The goal is simple : have the ability to conditionally change inputs.
We’ll do a proof of concept with a small exemple for a safety relay monitored by a feedback.

1 Configuration
We’ll run the simulator and the editor on two computers :
Simulation configuration
2 Simulator configuration
First let’s start an instance with the following parameters :

Once started, it should be like that :

3 PLC Programming
3.1 Hardware configuration
Let’s do a simple configuration as follow :

Network configuration :
– PLC_1 : 192.168.1.1/24
– IO device_1 : 192.168.1.2/24Note : On the simulator, we have different IP addresses for all the network interfaces : Ethernet adapter, PLCSIM virtual ethernet adapter, PLC and I/Os !
With the following I/Os :

Note that you’ll need to activate this option in the project settings :

3.2 Program
Our program will be very simple !
OB1 will toggle a bit every second :

And FB1 will do a safety check between the relay output and the input feedback :

3.3 Compiling and loading
You should be able to compile and load :

4 Simulation
As soon as you’ll run the program, you should have an error on the feedback monitoring :
5 C# Co-simulation
To solve this issue, we’ll running co-simulation with C#. The script will check the output value (%Q9.0) and set the feedback (%I0.0) accordingly.
We’ll be using sharpdevelop as IDE.
5.1 Import DLL
Importing the DLL is easy :

Then we write a short program :
/*
* Created by SharpDevelop.
*/
using System;
using System.Threading;
using Siemens.Simatic.Simulation.Runtime;
namespace CPU1515F
{
class Program
{
public static void Main(string[] args)
{
Console.WriteLine("Starting simulation");
//Use it for local instance
//IInstance myInstance = SimulationRuntimeManager.CreateInterface("Golf8");
//Use it for remote instance
IRemoteRuntimeManager myRemoteInstance = SimulationRuntimeManager.RemoteConnect("192.168.1.101:50000");
IInstance myInstance = myRemoteInstance.CreateInterface("1515F");
//Update tag list from API
Console.WriteLine("Tags synchronization");
myInstance.UpdateTagList();
//Start a thread to synchronize feedbacks inputs
Thread tFeedbacks = new Thread(()=>synchroFeedbacks(myInstance));
tFeedbacks.Start();
//Allow the user to quit simulation
Console.WriteLine("Simulation running");
Console.WriteLine("Press any key to quit . . . ");
Console.ReadKey(true);
}
static void synchroFeedbacks(IInstance myInstance)
{
while(true){
//Keep %I and %Q opposite
myInstance.WriteBool("FB_KA1", !myInstance.ReadBool("KA1"));
}
}
}
}
And run it :

Once acknowledged, we should not have any issue.
Using the trace tool, we can confirm that it’s running perfectly fine, updating the input in around 100ms.

