2024年1月24日发(作者:)

C# 读写西门子 PLC数据并实现语音报警

1. 西门子 PLC配置及程序

2. Wincc和西门子通讯配置

3. C# OPC读取PLC数据(通过WINCC)

4. C# 文字转语音

5. 完整程序

先演示一下效果:

选择Wincc做OPCserver

4个变量值显示

点击“写数据”,会把上面textbox的3写入变量1和变量2,程序中设定的只能写这2个

1

1. 西门子 PLC配置及程序

1.1 硬件配置

新建一个工程,插入一个带以太网的CPU(和WINCC通过以太网连接),如下:

IP地址设置

1.2 软件设计

简易程序实现加减乘除累计

CPU设置M0.5每

1S触发一次

以上做完后,我们下载到S7-PLCSIM就可以开始仿真了。

2

2. Wincc和西门子通讯配置

新建一个Wincc工程,打开变量管理:

3. C# 文字转语音

引用自带的

选择“添加新的驱动程序”->S7 Protocol Suite,然后新建一个TCP/IP 连接:

添加变量:

此处我们仅仅是测试C#读取PLC数据,Wincc只是用作OPC服务器,因此只需要配置到这边就结束了,其它画面编辑什么的这里不做介绍。

3

3. C# OPC读取PLC数据(通过WINCC)

OPC的数据访问方法分别有同步访问、异步访问和订阅式数据采集方式三种。之前在ABB

PLC和C#通讯介绍了订阅式数据采集,此处再介绍一下异步读取数据,写入数据还是通过异步方法。

//OPC异步读取数据

private void Group_AsyncReadComplete(int TransactionID, int NumItems, ref Array

ClientHandles, ref Array ItemValues, ref Array Qualities, ref Array TimeStamps, ref Array

Errors)

{

for (int i = 1; i < NumItems+1; i++)

{

d[32(ue(i))] =

le(ue(i));

}

= d[1].ToString();

= d[2].ToString();

= d[3].ToString();

= d[4].ToString();

}

此处需要注意,ClientHandles当我每次重新换变量读取数据是,不是1~4这个顺序—_—,避免界面显示的变量值对于不上(如果直接D[i]= le(ue(i)); 变量和值就对于不上了…)因此按照客户端句柄来读取。

//OPC异步写入数据

private void WBtn_Click(object sender, RoutedEventArgs e)

{

Array AsycWr_Value;

Array SerHandles;

object[] tempWrData = new object[3];//写入的数据必须是object类型的

int[] tempSerHandles = new int[3];

//将输入的数据赋给数组,然后转成Array给AsycWr_Value

tempWrData[1] = (object);

tempWrData[2] = (object);

AsycWr_Value = (Array)tempWrData;

//将输入数据对应的服务器句柄赋给变量,然后转成Array类型给SerHandles

tempSerHandles[1] = 32(ue(1));

tempSerHandles[2] = 32(ue(2));

SerHandles = (Array)tempSerHandles;

try

{

rite(2, ref SerHandles, ref AsycWr_Value, out Errors_Wr, TransactionID, out

CancleID);

}

catch (Exception e1)

4

{

ShowMessage(ng());

}

4. C# 文字转语音

引用自带的

//三个参数:语速,音量,内容

public void SpeechVideo_Read(int rate, int volume, string speektext)

{

= rate;

= volume;

sync(speektext);

}

if (Value1>80) //语音报警测试

{

SpeechVideo_Read(0, 80, "当前液位为" + ng() + "液位高报警");

}

5

5. 完整程序

using System;

using s;

using ;

using sis;

using OPCAutomation;

using ;

using ing;

namespace ABB语音报警

{

public partial class MainWindow : Window

{

OPCServer Server;

OPCGroups Groups;

OPCGroup Group;

OPCItems Items;

private bool Flag = true;

double[] d = new double[100];

SpeechSynthesizer speech = new SpeechSynthesizer();

Array strItemIDs;

Array cHandles;

Array sHandles;

Array Erros_read;

Array Errors_Wr;

int TransactionID = 1;

int CancleID;

bool Read_Flag;

object RequestDataTypes = null;

object AccessPaths = null;

public MainWindow()

{

InitializeComponent();

Server = new OPCServer();

}

6

private void Btn2_click(object sender, RoutedEventArgs e)//获取OPC服务器

{

if ( == " ")

{

("请先输入IP地址!");

}

else

{

string ip = ();//去除两端空格

try

{

//过去计算机名Win7貌似新的不行,Win10可以,因此此处还是采用老的方法

object progIds = Servers(tByAddress(ip).HostName);

foreach (var item in (Array)progIds)

{

(item);//所有OPC服务器放入Combox中

}

edIndex = 0;//默认选择第一个OPC服务器

if ( == null)

{

ShowMessage("获取服务器失败,请检查OPC服务器是否启动!");

}

else

{

ShowMessage("成功获取OPC服务器!");

}

}

catch (Exception err)

{

ShowMessage(ng());

}

}

}

private void ShowMessage(string str)//文本框消息提示

{

Text(str + "rn");

ToEnd();

}

7

private void Btn3_Click(object sender, RoutedEventArgs e)//连接OPC服务器

{

if ( == "")

{

("请先选择OPC服务器!");

}

else

{

try

{

if (State == 32(connected))

{

t();

t = "断开OPC服务器";

ShowMessage("成功连接OPC服务器!");

Groups = ups;

tGroupDeadband = 0;//缓冲区死区

tGroupIsActive = true;//缓冲区活动激活

tGroupUpdateRate = 1000;//缓冲区刷新时间

Group = ("group1");

cribed = true; //缓冲区订阅Datachange事件

Items = ms;

riteComplete += Group_AsyncWriteComplete;//异步写入数据事件

eadComplete += Group_AsyncReadComplete;//异步读取数据事件

string[] tmpIDs = new string[5];

int[] tmpCHandle = new int[5];

for (int i = 1; i < 5; i++)

{

tmpCHandle[i] = i;

}

tmpIDs[1] = ;

tmpIDs[2] = ;

tmpIDs[3] = ;

tmpIDs[4] = ;

strItemIDs = (Array)tmpIDs;

cHandles = (Array)tmpCHandle;

ms(4, ref strItemIDs, ref cHandles, out sHandles, out Erros_read,

RequestDataTypes, AccessPaths);

}

8

else

{

nect();

t = "连接OPC服务器"; ;

ShowMessage("OPC服务器连接已断开!");

}

}

catch (Exception err)

{

ShowMessage(ng());

}

}

}

private void Btn4_click(object sender, RoutedEventArgs e)//开始/停止 读取数据{

if (Flag == true)

{

Thread th1 = new Thread(Asyc_Read) //新建读取数据线程

{

IsBackground = true

};

();

t = "停止读取数据";

ound = ;

Flag = false;

Read_Flag = true;

}

else

{

t = "开始读取数据";

ound = new SolidColorBrush(b(221,221,221));

Flag = true;

Read_Flag = false;

}

}

9

private void Asyc_Read()//异步读取数据,间隔1秒

{

while (Read_Flag)

{

ead(4, ref sHandles, out Erros_read, TransactionID, out CancleID);

(1000);

}

}

//异步读取数据完成,数据处理

private void Group_AsyncReadComplete(int TransactionID, int NumItems, ref Array

ClientHandles, ref Array ItemValues, ref Array Qualities, ref Array TimeStamps, ref Array

Errors)

{

for (int i = 1; i < NumItems+1; i++)

{

d[32(ue(i))] =

le(ue(i));

}

= d[1].ToString();

= d[2].ToString();

= d[3].ToString();

= d[4].ToString();

if (d[1] > 80)

{

ShowMessage("当前液位为" + d[1].ToString() + "液位高报警");

SpeechVideo_Read(0, 80, "当前液位为" + d[1].ToString() + "液位高报警");

}

if (d[2] < 10)

{

ShowMessage("当前液位为" + d[2].ToString() + "液位低报警");

SpeechVideo_Read(0, 80, "当前液位为" + d[2].ToString() + "液位低报警");

}

}

// rate:范围为:-10~10; volume:范围为:0~100; speektext:待转换声音的文字

public void SpeechVideo_Read(int rate, int volume, string speektext) // 语速,音量,内容

{

10

= rate;

= volume;

sync(speektext);

}

private void WBtn_Click(object sender, RoutedEventArgs e)//OPC异步写数据

{

Array AsycWr_Value;

Array SerHandles;

object[] tempWrData = new object[3];//写入的数据必须是object类型的

int[] tempSerHandles = new int[3];

//将输入的数据赋给数组,然后在转成Array给AsycWr_Value、

tempWrData[1] = (object);

tempWrData[2] = (object);

AsycWr_Value = (Array)tempWrData;

//将输入数据的Item对于服务器句柄赋给数据,然后转成Array类型给SerHandles

tempSerHandles[1] = 32(ue(1));

tempSerHandles[2] = 32(ue(2));

SerHandles = (Array)tempSerHandles;

try

{

rite(2, ref SerHandles, ref AsycWr_Value, out Errors_Wr, TransactionID, out

CancleID);

}

catch (Exception e1)

{

ShowMessage(ng());

}

}

private void Group_AsyncWriteComplete(int TransactionID, int NumItems, ref Array

ClientHandles, ref Array Errors)

{

ShowMessage(ng() + "个数据写入成功!");

}

}

}

11