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

C# 读写ABB PLC数据并实现语音报警

1. ABB PLC配置及程序

2. C# OPC读写程序

3. C# 文字转语音

4. 完整程序

先演示一下效果:

PLC程序4个变量分别做加减乘除累计

4个变量值显示

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

1

1. ABB PLC配置及程序

1.1 安装

使用Compact_Control_Builder_AC_800M_5.1.1-1,安装如下几个软件:

1.安装Compact版

2.安装说明书

3.安装OPC服务器,C#通过它来读取PLC数据

4.安装仿真器

1.2 新建工程编写程序

1.新建控制器,IP地址后续会讲

本文主要OPC读取数据,PLC的硬件不介绍

2

由于我们是仿真实现,需要先开启仿真项,如下:

1. 在Tool工具栏开启硬件仿真

2. 在硬件配置里勾选硬件仿真

3

现在可以看到硬件状态多了S,如下:

硬件上都有个下标S,说明开启了硬件仿真

然后在Program1中编写程序,此处写了个1s累计 加减乘除,如下:

最终我们会在C#读取Input1~Input4这4个变量,并可以在C#写入数据。

4

1.3 仿真器设置

1. 打开仿真器,在File文件找到IP地址

2. 根据上面的IP更改PLC的地址

以上全部配置完,然后就可以下载程序了:

点击下载硬件配

置及程序至PLC

可以看到在线程序中数据变化

在线后状态

注意:这个地址可能每次都不一样

输入找到的IP

5

1.4 OPC Server配置

1. 连接成功显示“笑脸”

2. 输入当前IP点击连接

ABB PLC配置至此全部完成。

6

2. C# OPC读写程序

OPC的数据访问方法分别有同步访问、异步访问和订阅式数据采集方式三种。此处我们采用订阅式数据读取,异步写入数据。

由于读取OPC数据采用的是数据变化刷新,在数据没有变化时有点问题,需定义全局数组然后读取放入,这样数据未变化就保持上次的值。

//OPC读取数据 订阅式,在上面PLC我们的4个变量都是Real类型,因此此处定义的都是Double

//不管读和写都是从数组的第二个开始,因此我们第一个数据都是XXX[1],然后依次往后

private void Group_DataChange(int TransactionID, int NumItems, ref Array ClientHandles, ref

Array ItemValues, ref Array Qualities, ref Array TimeStamps)

{

double Value1 = le(ue(1));

double Value2 = le(ue(2));

double Value3 = le(ue(3));

double Value4 = le(ue(4));

}

//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)

{

ShowMessage(ng());

7

C# 文字转语音

引用自带的

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

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

}

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

"当前液位为" + ng() + "液位高报警");

}

8

}

3.

{

= rate;

= volume;

sync(speektext);

{

SpeechVideo_Read(0, 80,

4. 完整程序

Xaml界面设计就不介绍了,以下为代码:

using System;

using c;

using ;

using ;

using ;

using s;

using ls;

using ;

using nts;

using ;

using ;

using g;

using tion;

using ;

using ;

using sis; //需引用自带的文件

using OPCAutomation; //安装Kepserver后会自带这个DLL文件,需引用

namespace ABB语音报警

{

public partial class MainWindow : Window

{

OPCServer Server;

OPCGroups Groups;

OPCGroup Group;

OPCItems Items;

OPCItem Item;

private bool Flag = true;

private string[] s = new string[100];

private int[] GetOpcValue = new int[100];

SpeechSynthesizer speech = new SpeechSynthesizer();

Array strItemIDs;

Array cHandles;

Array sHandles;

Array Erros_read;

Array Errors_Wr;

int TransactionID = 1;

int CancleID;

object RequestDataTypes = null;

9

object AccessPaths = null;

public MainWindow()

{

InitializeComponent();

Server = new OPCServer();

}

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

{

if ( == " ")

{

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

}

else

{

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

try

{

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");

10

ToEnd();

}

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; //OPC写事件

//读取4个变量值

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); //添加需要读取的4个变量

}

11

else

{

nect();

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

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

}

}

catch (Exception err)

{

ShowMessage(ng());

}

}

}

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

{

if (Flag == true)

{

ange += Group_DataChange;

t = "停止读取数据";

ound = ;

Flag = false;

}

else

{

ange -= Group_DataChange;

t = "开始读取数据";

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

Flag = true;

}

}

//OPC读取数据 订阅式

private void Group_DataChange(int TransactionID, int NumItems, ref Array ClientHandles, ref

Array ItemValues, ref Array Qualities, ref Array TimeStamps)

{

double Value1 = le(ue(1));

double Value2 = le(ue(2));

double Value3 = le(ue(3));

double Value4 = le(ue(4));

= ng();

= ng();

= ng();

12

= ng();

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

{

ShowMessage("当前液位为" + ng() + "液位高报警");

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

}

if (Value3 < 10)

{

ShowMessage("当前液位为" + ng() + "液位低报警");

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

}

}

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

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

{

= rate;

= volume;

sync(speektext);

}

// 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;

//将输入数据的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

13

CancleID);

}

catch (Exception e1)

{

ShowMessage(ng());

}

}

//OPC成功写入数据提示

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

ClientHandles, ref Array Errors)

{

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

}

}

}

14