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
发布评论