Home / PLC / Communication with Siemens S7 Plc with C# and S7.Net plc driver Communication with Siemens S7 Plc with C# and S7.Net plc driver

Communication with Siemens S7 Plc with C# and S7.Net plc driver

 

In this article I explain how to implement a Siemens S7 plc driver by using the open source driver S7.Net.

You can find S7.Net sources on GitHub: https://github.com/killnine/s7netplus.

How to video

Summary

Why S7.Net: features and capabilities of the driver

S7.Net is a plc driver written in C#, this means that you don’t have to handle any interoperability with native code, but it just use OO programming and all the .Net features that you are familiar with.

Basic capabilities:
• Can connect and disconnect with the plc using sockets
• Can read and write bytes from a single area of memory, given a starting address and the number of bytes.

High level features:
• Can directly map DBs to classes and structs
• The types of C# are mapped into types of S7 and there are converters for every type (double to REAL, int to DEC, etc)
• It is easy to use, well written and perfectly readable
• It’s open source, MIT license permit you to use it in every commercial application
• Did I already say that it’s written in C#, no interop at all?

What it’s not good about S7.Net, roadmap for future upgrades:
• Lack of documentation
• Lack of a function that permit to read/write multiple non-connected variables with a single request to the plc.

Documentation on the driver and S7 protocol

The documentation of S7.Net is here.

S7.Net exposes a class called Plc that contains all the methods that we can use to communicate with the plc:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
public class Plc
{
    public string IP { get; set; }
    public bool IsConnected { get; }
    public CpuType CPU { get; set; }
    public Int16 Rack { get; set; }
    public Int16 Slot { get; set; }
    public string Name { get; set; }
    public object Tag { get; set; }
    public bool IsAvailable { get; }
    public ErrorCode Open(){...}
    public void Close(){...}
    public byte[] ReadBytes(DataType dataType, int DB, int startByteAdr, int count){...}
    public object Read(DataType dataType, int db, int startByteAdr, VarType varType, int varCount){...}
    public object Read(string variable){...}
    public object ReadStruct(Type structType, int db){...}
    public void ReadClass(object sourceClass, int db){...}
    public ErrorCode WriteBytes(DataType dataType, int db, int startByteAdr, byte[] value){...}
    public object Write(DataType dataType, int db, int startByteAdr, object value){...}
    public object Write(string variable, object value){...}
    public ErrorCode WriteStruct(object structValue, int db){...}
    public ErrorCode WriteClass(object classValue, int db){...}
    public string LastErrorString { get; }
    public ErrorCode LastErrorCode { get; }
}

To connect and disconnect you can use the Open() and Close() functions, to communicate you can use any of the methods to read and write variables from the plc memory.

Every method return an ErrorCode, or the object that it’s supposed to return if there are no errors.

Unfortunately this is quite a messy concept, because usually drivers throws exceptions in case of errors, or returns a value indicating the error and put the requested values inside a memory area passing a pointer to that area.

Here there is the documentation of the protocol, in german: http://www.bj-ig.de/service/verfuegbare-dokumentationen/s7-kommunikation/index.html

Some more documentation about the S7 protocol can be found at the snap7 website: http://snap7.sourceforge.net/ or inside the package of Snap7 full (latest full: http://sourceforge.net/projects/snap7/files/1.2.1/ )

Also some documentation on S7 protocol can be found inside LibNoDave.

Getting started with S7.Net

This paragraph explains how to get S7.Net driver and all the steps from compile the driver to add it into your application.

You can choose to add download it from NuGet (fastest way) or to include the full sources in your project.

The steps to download from NuGet are:

1) Right click on the project and select “Manage NuGet packages”NuGet 1

2) Search for S7.Net in the online tab, then install it.
NuGet 2

3) Repeat for every project where you need the dll.

These steps are to include the sources in your application:

1) Download the driver from the Github repository https://github.com/killnine/s7netplus.
S7 net download

2) Copy the S7.Net project folder in the folder that contain your project

3) Add the S7.Net project to the solution

4) Add the references

S7 Net solution reference

A simple application with S7.Net

I know that create an application to showcase the use of the driver is difficult and will not meet everyone requirements, that’s why i tried to keep it as simple as possible, just to show how to create a PLC object, how to handle a polling to refresh the data read from the PLC and how to visualize the data around the application in a simple way. Also how to write data to the PLC.

The sample application is a WPF application that can connect and disconnect from the PLC, read and write the DB1 variables on the PLC and visualize the values.

The application contains 2 projects, one is a wrapper for the plc driver, the other one is a project that contains all the graphic pages.

You can download the sample application on GitHub: https://github.com/mesta1/S7.Net-example.

S7 Net UI example

Creating a wrapper of S7.Net

Using a wrapper for the plc driver is a strategy that I usually use to implement features that the plc driver doesn’t contain, and to abstract the most of the code required to interface the application with the plc driver.

The wrapper exposes an interface IPlcSyncDriver that contains all the methods needed to communicate with the PLC:

  • connect/disconnect and connection state
  • read/write single and multiple variables, called Tags (a Tag is an object that contains an address and a value)
  • read/write a class (special feature of the S7.Net protocol)
1
2
3
4
5
6
7
8
9
public interface IPlcSyncDriver
{       
    ConnectionStates ConnectionState { get; }   
    void Connect();
    void Disconnect();     
    List<Tag> ReadItems(List<Tag> itemList);
    void ReadClass(object sourceClass, int db);
    void WriteItems(List<Tag> itemList);
}  

As you can see this methods are less and differents from the ones named inside the IPlc interface of the driver, and the reason is because I handle the communication errors by throwing exceptions, so the returned values can be just the objects that i need.

Also I just use the highest level features of the driver, and handle all the complexity inside the wrapper.

I use the concept of Tags inside my wrapper, where a Tag is an object containing an address and a value. This is familiar if you already used OPC Servers and Clients, but here it is much more simple and basic.

Creation of PLC class inside the main project

In the main project I usually define the class that contains the PLC values and communication thread in a singleton.

You can read more about it in this article:
https://www.mesta-automation.com/writing-your-first-hmi-project-in-c-wpf/

You can find the plc class inside PlcConnectivity folder.

The class exposes the properties and methods that are used in all application to communicate with the PLC:

1
2
3
4
5
6
7
8
public ConnectionStates ConnectionState
public DB1 Db1 
public TimeSpan CycleReadTime
 
public void Connect(string ipAddress)
public void Disconnect()
public void Write(string name, object value)
public void Write(List<Tag> tags)

Inside the class there is a multi-threaded timer that will poll the plc once every 100 ms (see constructor).

The timer callback is responsible to refresh the tags and to calculate the time passed after every read.

You can of course use multiple timers, with different Interval value, to better manage the network resources.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
private void timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{           
    if (plcDriver == null || plcDriver.ConnectionState != ConnectionStates.Online)
    {
        return;
    }
    timer.Enabled = false;
    CycleReadTime = DateTime.Now - lastReadTime;
    try           
    {               
        RefreshTags();
    }           
    finally
    {
        timer.Enabled = true;
        lastReadTime = DateTime.Now;
    }
}

To read values from the PLC I use the feature that read a class directly from a DB.

1
2
3
4
private void RefreshTags()
{
    plcDriver.ReadClass(Db1, 1);
}

Write values on the PLC

To write the variables I use the method that permit to write a single object by giving an address and a value:

1
2
     
Plc.Instance.Write(PlcTags.DwordVariable, dwordVar);

You can read an example of write and read in the handlers of the MainWindow page.

PLC data visualization

To visualize the values I used a DispatcherTimer (but you can use also MVVM and DataBinding):

1
2
3
4
5
6
7
8
9
10
11
12
13
void timer_Tick(object sender, EventArgs e)
{
    btnConnect.IsEnabled = Plc.Instance.ConnectionState == ConnectionStates.Offline;
    btnDisconnect.IsEnabled = Plc.Instance.ConnectionState != ConnectionStates.Offline;
    lblConnectionState.Text = Plc.Instance.ConnectionState.ToString();
    ledMachineInRun.Fill = Plc.Instance.Db1.BitVariable0 ? Brushes.Green : Brushes.Gray;
    lblSpeed.Content = Plc.Instance.Db1.IntVariable;
    lblTemperature.Content = Plc.Instance.Db1.RealVariable;
    lblAutomaticSpeed.Content = Plc.Instance.Db1.DIntVariable;
    lblSetDwordVariable.Content = Plc.Instance.Db1.DWordVariable;
    // statusbar
    lblReadTime.Text = Plc.Instance.CycleReadTime.TotalMilliseconds.ToString(CultureInfo.InvariantCulture);
}

Sample code and testing

You can download the sample application on GitHub: https://github.com/mesta1/S7.Net-example.

You can also download the sample application for plc created with Step7 5.5: S7_pro1

To test the application you can use Step7 PLCSim, the guide to connect to it via NetToPlcSim is here: https://www.mesta-automation.com/nettoplcsim-how-to-connect-step-7-plc-sim-to-scadas/

Home / PLC / Communication with Siemens S7 Plc with C# and S7.Net plc driver

Communication with Siemens S7 Plc with C# and S7.Net plc driver

原文地址:https://www.cnblogs.com/BBBLANK/p/7193213.html