目录
一、PLC硬件配置
1、创建PLC程序
(1)程序工程选择
(2)变量和程序
2、配置程序在模拟器中运行
(1)打开RSLkin Classic
(2)仿真器配置
(3)PLC程序下载
(4)使用OPCTools测试工具测试
(5)第三方OPC工具测试OK
二、C#上位机程序实现
1、创建C#工程
(1)界面创建
(2)添加OPC动态链接库文件
2、关键代码实现
(1)全局变量定义
(2)刷新
(3)连接
(4)批量方式-同步读操作
(5)批量方式-同步写操作
3、软件测试
(1)测试环境设置
(2)搜索和连接OPC服务器
(3)读写操作
三、工程下载链接
一、PLC硬件配置
1、创建PLC程序
(1)程序工程选择
没有PLC硬件,那么就创建模拟器程序
CPU的位置和模拟器要一致
(2)变量和程序
变量创建
PLC程序
2、配置程序在模拟器中运行
(1)打开RSLkin Classic
RSLkin Classic里链接控制器选择模拟器,然后连接
(2)仿真器配置
(3)PLC程序下载
然后在仿真器模块2上鼠标右击运行
3、应用RSLinx Classic建立OPC通信
(1)在RSLinx Classic中创建组和PLC程序关联
(4)使用OPCTools测试工具测试
安装了AB的Studio5000软件即自带OPCTools测试工具
测试工具根目录位置
OPC测试
Step1
Step2
Step3
Step4
(5)第三方OPC工具测试OK
第三方OPC工具测试OK后,说明硬件方面就没问题了,此时就可以较给C#上位机去操作了。
二、C#上位机程序实现
1、创建C#工程
创建C# Winform工程。
(1)界面创建
(2)添加OPC动态链接库文件
2、关键代码实现
(1)全局变量定义
/// <summary>
/// 要操作的PLC变量个数
/// </summary>
int nVaribaleNum = 5;
/// <summary>
/// OPC服务器对象
/// </summary>
OPCServer opcServer;
/// <summary>
/// OPC组集合对象
/// </summary>
OPCGroups opcGroups;
/// <summary>
/// OPC组对象
/// </summary>
OPCGroup opcGroup;
/// <summary>
/// OPC多变量添加项目
/// </summary>
OPCItems opcItems;
/// <summary>
/// OPC单变量添加项目数组
/// </summary>
OPCItem[] opcItem;
/// <summary>
/// 主机名
/// </summary>
string strHostName = "";
/// <summary>
/// OPC服务器名
/// </summary>
string strOPCServerName = "";
/// <summary>
/// OPC服务器连接状态
/// </summary>
bool bIsConnect = false;
(2)刷新
该功能实现:搜索OPC服务器、OPC服务器IP地址
private void btnRefrush_Click(object sender, EventArgs e)
{
//获取客户端名称和IP
GetLocaIp();
//获取OPC服务器
GetLocalOPCServer();
//初始化客户端名和OPC服务器名的选择
this.cbClientName.SelectedIndex = 0;
this.cbOPCServerName.SelectedIndex = 0;
}
/// <summary>
/// 获取客户端名称和IP
/// </summary>
/// <param name="hostName"></param>
/// <returns></returns>
private void GetLocaIp()
{
//获取本地计算机名
strHostName = Dns.GetHostName();
this.cbClientName.Items.Add(strHostName);
//获取本机IP地址
try
{
IPHostEntry ipHostEntry = Dns.GetHostEntry(strHostName);
for (int i = 0; i < ipHostEntry.AddressList.Length; i++)
{
//从IP地址列表中筛选出IPv4类型的IP地址
//AddressFamily.InterNetwork表示此IP为IPv4,
//AddressFamily.InterNetworkV6表示此地址为IPv6类型
if (ipHostEntry.AddressList[i].AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork)
{
cbClientName.Items.Add(ipHostEntry.AddressList[i].ToString());
}
}
}
catch (Exception ex)
{
MessageBox.Show("获取本地IP出错:" + ex.Message);
}
//添加空字符串作为客户端名实现与OPC服务器的连接
if (!this.cbClientName.Items.Contains(""))
{
this.cbClientName.Items.Add("");
}
}
/// <summary>
/// 获取OPC服务器
/// </summary>
private void GetLocalOPCServer()
{
try
{
opcServer = new OPCServer();
object opcServerList = opcServer.GetOPCServers(strHostName);
foreach (string server in (Array)opcServerList)
{
cbOPCServerName.Items.Add(server);
}
}
catch (Exception ex)
{
MessageBox.Show("获取OPC服务器出错:" + ex.Message);
}
}
(3)连接
private void btnConnect_Click(object sender, EventArgs e)
{
if (bIsConnect == false)
{
try
{
//连接选择的OPC服务器
strOPCServerName = this.cbOPCServerName.Text;
opcServer.Connect(strOPCServerName, strHostName);
//服务器先行断开
opcServer.ServerShutDown += OPCServerShutDown;
btnConnect.Text = "断开";
btnConnectState.BackColor = Color.Lime;
//创建组集合对象
CreateGroups();
bIsConnect = true;
}
catch (Exception ex)
{
bIsConnect = false;
btnConnectState.BackColor = Color.Red;
MessageBox.Show("OPC服务器连接出错:" + ex.Message);
}
}
else
{
opcServer.Disconnect();
bIsConnect = false;
btnConnect.Text = "连接";
btnConnectState.BackColor = Color.Red;
}
}
/// <summary>
/// 创建组集合
/// </summary>
/// <returns></returns>
private bool CreateGroups()
{
try
{
//获取OPC服务器的组集合
opcGroups = opcServer.OPCGroups;
//获取OPC服务器组集合的组
opcGroup = opcGroups.Add("测试1"); //名字可以随便取
//设置组集合属性
opcGroups.DefaultGroupIsActive = true; //激活组集合
opcGroups.DefaultGroupDeadband = 0; // 死区值,设为0时,服务器端该组内任何数据变化都通知组。
opcGroups.DefaultGroupUpdateRate = 200; // 默认组集合的刷新频率为200ms
//设置组属性
opcGroup.UpdateRate = 1; //刷新频率为1秒。
opcGroup.IsSubscribed = true; //使用订阅功能,即可以异步,默认false
//设置组的读写事件
opcGroup.DataChange += OpcGroup_DataChange;
opcGroup.AsyncWriteComplete += OpcGroup_AsyncWriteComplete;
opcGroup.AsyncReadComplete += OpcGroup_AsyncReadComplete;
//组对象添加项目
AddGroupItems();
}
catch (Exception ex)
{
MessageBox.Show("创建组出错:" + ex.Message);
return false;
}
return true;
}
/// <summary>
/// //组对象添加项目
/// </summary>
private void AddGroupItems()
{
//组对象的项目集合
opcItems = opcGroup.OPCItems;
//[aaa]Program:MainProgram.bTest1
//opcItems.AddItems()//多个变量一起添加
//项目集合中的项目
opcItem[0] = opcItems.AddItem("[aaa]Program:MainProgram.bTest1", 0); //bool
opcItem[1] = opcItems.AddItem("[aaa]Program:MainProgram.bTest2", 1); //bool
opcItem[2] = opcItems.AddItem("[aaa]Program:MainProgram.Temp1", 2); //int
opcItem[3] = opcItems.AddItem("[aaa]Program:MainProgram.Temp2", 3); //int
opcItem[4] = opcItems.AddItem("[aaa]Program:MainProgram.Temp3", 4); //int
//组内项目句柄:由于Array和数组的索引值差1,所以数组的第一个元素用0填充占位
int[] temp0 = new int[] { 0, opcItem[0].ServerHandle };
int[] temp1 = new int[] { 0, opcItem[1].ServerHandle };
int[] temp2 = new int[] { 0, opcItem[2].ServerHandle };
int[] temp3 = new int[] { 0, opcItem[3].ServerHandle };
int[] temp4 = new int[] { 0, opcItem[4].ServerHandle };
//移除组内项目
Array serverHandle = temp3.ToArray();
Array errors;
opcItems.Remove(1, ref serverHandle, out errors);
//重新添加删除的项目
opcItem[3] = opcItems.AddItem("[aaa]Program:MainProgram.Temp2", 3); //int
}
(4)批量方式-同步读操作
/// <summary>
/// 同步-读
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void btnSynRead_Click(object sender, EventArgs e)
{
if (this.opcServer == null || bIsConnect == false)
{
MessageBox.Show("请先连接服务器!");
return;
}
//组的同步读取
string[] itemId = {
"",
"[aaa]Program:MainProgram.bTest1",
"[aaa]Program:MainProgram.bTest2",
"[aaa]Program:MainProgram.Temp1",
"[aaa]Program:MainProgram.Temp2" ,
"[aaa]Program:MainProgram.Temp3"
}; //""用于占位
int[] clientHandle = { 0, 1, 2, 3, 4, 5 };
Array itemIds = itemId.ToArray();
Array clientHandles = clientHandle.ToArray();
Array serverHandles;
Array errors;
Array values;
object qualities;
object timeStamps;
opcGroup.OPCItems.AddItems(nVaribaleNum, ref itemIds, ref clientHandles, out serverHandles, out errors);
opcGroup.SyncRead(2, nVaribaleNum, ref serverHandles, out values, out errors, out qualities, out timeStamps);//第一个参数为2才可以
object[] valueList = new object[nVaribaleNum];
for (int i = 1; i <= nVaribaleNum; i++)
{
valueList[i - 1] = values.GetValue(i);
}
txt_bTest1.Text = valueList[0].ToString();
txt_bTest2.Text = valueList[1].ToString();
txt_Temp1.Text = valueList[2].ToString();
txt_Temp2.Text = valueList[3].ToString();
txt_Temp3.Text = valueList[4].ToString();
}
(5)批量方式-同步写操作
/// <summary>
/// 同步-写
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void btnSyncWrite_Click(object sender, EventArgs e)
{
if (this.opcServer == null || bIsConnect == false)
{
MessageBox.Show("请先连接服务器!");
return;
}
//组的同步写入
int[] temp = new int[] {
0,
opcItem[0].ServerHandle,
opcItem[1].ServerHandle,
opcItem[2].ServerHandle,
opcItem[3].ServerHandle,
opcItem[4].ServerHandle
}; //0用于占位
Array serverHandles = temp.ToArray();
object[] tempValue = new object[]
{ "",
txt_bTest1.Text == "1" ? true : false,
txt_bTest2.Text == "1" ? true : false,
Convert.ToInt16(this.txt_Temp1.Text),
Convert.ToInt16(this.txt_Temp2.Text),
Convert.ToInt16(this.txt_Temp3.Text),
}; //""用于占位
Array values = tempValue.ToArray();
Array errors;
opcGroup.SyncWrite(nVaribaleNum, serverHandles, values, out errors);
}
3、软件测试
(1)测试环境设置
Step1:设置本地Ip固定地址192.168.1.33
Step2:PLC程序在本地模拟器上处于运行模式。
Step3:PLC程序中给OPC客户端访问的量在RSLinkClassic中已成功配置,并且RSLink Classic软件打开处于运行中
(2)搜索和连接OPC服务器
点刷新,然后如图所示依次选择,成功连接服务器
(3)读写操作
读操作
写操作
三、工程下载链接
包括PLC程序、C#程序、OPC动态链接库文件
https://download.csdn.net/download/panjinliang066333/89598823
参考:
https://blog.csdn.net/zlbdmm/article/details/108574133
C#之OPC通信_c# opc-CSDN博客