C#使用OPC组件方式和AB的PLC通信

news2024/12/23 17:26:22

目录

一、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博客

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1963243.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

我终于搭建完成了我的个人网站!(仅分享,非教程)

先看看我的个人网站~ https://yaoqx.pages.devhttps://yaoqx.pages.dev 来看看我搭建的过程吧&#xff01; &#xff08;仅分享&#xff0c;非教程&#xff09; 网站技术 前端框架&#xff1a;Astro主题&#xff1a;Frosti代码托管&#xff1a;Github网页部署&#xff1a;Cl…

Vscode ssh Could not establish connection to

错误表现 上午还能正常用vs code连接服务器看代码&#xff0c;中午吃个饭关闭vscode再重新打开输入密码后就提示 Could not establish connection to 然后我用终端敲ssh的命令连接&#xff0c;结果是能正常连接。 解决方法 踩坑1 网上直接搜Could not establish connectio…

浮点数如何存储

一、浮点数存储格式 符号&#xff08;sign&#xff09; s是符号位&#xff0c;1表示负&#xff0c;0表示正阶码&#xff08;exponent&#xff09; E的作用是对浮点数加权&#xff0c;这个权重是2的E次幂尾数&#xff08;significand&#xff09; M是一个二进制小数 二、举例说…

被爬网站用fingerprintjs来对selenium进行反爬,怎么破?

闲暇逛乎的时候&#xff0c;看到了这个问题&#xff1a; Fingerprintjs实际上就是专门用来识别和追踪浏览器的&#xff0c;要应对起来&#xff0c;确实并非易事。那么&#xff0c;我们要如何应对FingerprintJS的唯一标记技术呢&#xff1f; 接下来&#xff0c;我们将一起来探讨…

【自学深度学习梳理2】深度学习基础

一、优化方法 上一篇说到,使用梯度下降进行优化模型参数,可能会卡在局部最小值,或优化方法不合适永远找不到具有最优参数的函数。 1、局部最小值 梯度下降如何工作? 梯度下降是一种优化算法,用于最小化损失函数,即寻找一组模型参数,使得损失函数的值最小(局部最小值…

【Python体验】第五天:目录搜索、数据爬虫(评论区里写作业)

文章目录 目录搜索 os、shutil库数据爬虫 request、re作业&#xff1a;爬取案例的top250电影的关键信息&#xff08;名称、类型、日期&#xff09;&#xff0c;并保存在表格中 目录搜索 os、shutil库 os 模块提供了非常丰富的方法用来处理文件和目录。 os.listdir(path)&#x…

STM32的外部中断实现按键控制led灯亮灭(HAL库)

一&#xff1a;stm32外部中断概述 1&#xff1a;stm32的外部中断线 STM32的每个IO都可以作为外部中断输入。 STM32的中断控制器支持19个外部中断/事件请求&#xff1a; 线0~15&#xff1a;对应外部IO口的输入中断。 线16&#xff1a;连接到PVD输出。 线17&#xff1a;连接到R…

后端采用SpringBoot框架开发的:ADR药物不良反应智能监测系统源码,用于监测和收集药品在使用过程中发生的不良反应的系统

ADR药物不良反应智能监测系统是一套用于监测和收集药品在使用过程中发生的不良反应&#xff08;Adverse Drug Reaction, ADR&#xff09;的系统。该系统基于医院临床数据中心&#xff0c;运用信息技术实现药品不良反应的智能监测、报告管理、知识库查询、统计分析等功能&#x…

【Python学习手册(第四版)】学习笔记11.2-表达式语句(print函数)及打印操作(重定向等)详解

个人总结难免疏漏&#xff0c;请多包涵。更多内容请查看原文。本文以及学习笔记系列仅用于个人学习、研究交流。 主要介绍表达式语句&#xff08;print函数&#xff09;及打印操作&#xff08;重定向等&#xff09;。视需要选择目录阅读。 目录 表达式语句 错误示例&#xf…

实验3-7 统计学生成绩

//实验3-7 统计学生成绩 /* 本题要求编写程序读入N个学生的百分制成绩&#xff0c;统计五分制成绩的分布。 百分制成绩到五分制成绩的转换规则&#xff1a;大于等于90分为A&#xff1b;小于90且大于等于80为B&#xff1b;小于80且大于等于70为C&#xff1b;小于70且大于等于60为…

相机标定(Camera Calibration)

什么是 相机标定&#xff08;Camera Calibration&#xff09;&#xff1f; 相机标定&#xff08;CameraCalibration&#xff09;是确定相机内部参数&#xff08;如焦距、光学中心、畸变系数等&#xff09;和外部参数&#xff08;如相机在世界坐标系中的位置和姿态&#xff09;的…

黑马头条vue2.0项目实战(三)——个人中心功能的实现

1. Tabbar 处理 通过分析页面&#xff0c;可以看到&#xff0c;首页、问答、视频、我的 都使用的是同一个底部标签栏&#xff0c;我们没必要在每个页面中都写一个&#xff0c;所以为了通用方便&#xff0c;我们可以使用 Vue Router 的嵌套路由来处理。 父路由&#xff1a;一个…

激发潜能,Vatee万腾平台驱动企业持续发展

在当今这个日新月异的商业环境中&#xff0c;企业要想保持竞争力并实现持续发展&#xff0c;就必须不断挖掘自身潜能&#xff0c;探索新的增长点。而Vatee万腾平台&#xff0c;正是这样一位能够激发企业潜能、驱动其持续发展的强大伙伴。 一、智能化赋能&#xff0c;解锁企业潜…

了解ISO 22301:业务连续性管理的关键

在当今全球化和复杂化的商业环境中&#xff0c;企业面临着各种潜在的风险和灾难&#xff0c;这些可能对其运营和声誉造成严重影响。为了有效地应对这些挑战并保障持续经营&#xff0c;国际标准化组织&#xff08;ISO&#xff09;引入了ISO 22301标准&#xff0c;这是一项专注于…

智能制造与工业物联网CC2530——定时器查询和中断

一、项目目的&#xff1a; 熟悉 ZigBee 模块相关硬件接口。使用 IAR 开发环境设计程序&#xff0c;学习 CC2530 定时器的使用&#xff0c;利用 CC2530 的定时器 T1 查询方式控制 LED 周期性闪烁。 二、项目原理&#xff1a; LED及按键原理图&#xff0c;如下图所示&#xff…

使用“阿里云人工智能平台 PAI”制作数字人

体验 阿里云人工智能平台 PAI PAI-DSW免费试用 https://free.aliyun.com/?spm5176.14066474.J_5834642020.5.7b34754cmRbYhg&productCodelearn https://help.aliyun.com/document_detail/2261126.html 体验PAI-DSW https://help.aliyun.com/document_detail/2261126.…

一文详解香港机房服务器干什么用的

香港机房服务器干什么用的&#xff1f;香港机房服务器是用于数据存储和备份、网络服务、数据处理与分析、云计算服务、游戏托管服务、其他服务等。香港机房服务器在现代互联网业务中扮演着至关重要的角色&#xff0c;其主要用途可以归纳为以下几个方面&#xff1a; 1、数据存储…

卡拉OK歌唱比赛活动策划方案

一、活动详细策划 &#xff08;一&#xff09;、前期工作准备 1、制定详细的策划方案、比赛流程&#xff0c;通知稿。 2、收集各参赛选手详细资料在选手上台前展示出&#xff0c;让各评委及嘉宾对选手有个初步认识。 3、各工作组准备好相关道具&#xff08;音响、无线话筒、低…

数据大脑智慧工厂数据平台建设方案(可编辑60页PPT)

引言&#xff1a;随着工业4.0时代的到来&#xff0c;智能制造已成为推动产业升级的核心引擎。为了进一步提升生产效率、优化资源配置、实现精准决策与个性化定制&#xff0c;构建一套高效、智能的数据大脑智慧工厂数据平台显得尤为重要。 方案介绍&#xff1a; 在数字化转型的…

05.FreeRTOS任务挂起与恢复

05. FreeRTOS任务挂起与任务恢复 1. FreeRTOS 挂起和恢复任务相关 API 函数 函数描述vTaskSuspend()挂起任务vTaskResume()恢复被挂起的任务xTaskResumeFromISR()在中断中恢复被挂起的任务 函数vTaskSuspend() 此函数用于挂起任务&#xff0c;若使用此函数&#xff0c;需要在…