PLC数据访问
PLC是很多机床设备上都有的控制中心,和PLC通信是很多做工厂管理系统的必经之路。
一年前有个项目需要和PLC(西门子S200)通信,不仅读取里面的数据,还需要写数据需要控制机床的运行,当时不大了解,由于设备比较老,没有以太网模块,还是在设备供应商的提示下用串口rs485联通pc,查资料了解modbus协议,完全手写按照modbus协议和PLC通信,最后总算了磕磕绊绊完成项目,后来还有各种超时异常造成机床运行错误,哎。
现在是第二个阶段,在老前辈的带领下,虽说对PLC下位机程序还是了解甚少,但是对如何与PLC通信方面比以前了解更多。由于市面上PLC的品牌和型号比较多,如果是要求各种PLC都和服务器连接并受控制或集中管理,基本上都会安装以太网扩展卡,然后在服务器上部署opc服务器,opc服务器的种类也比较多,西门子有自己的opc服务器,第三方的opc服务器也很好,能兼容很多种PLC种类和型号,自带的各种驱动,就现在这个项目来说用的是kepserver,用这个管理软件的人很多,只要知道想要的数据在PLC的正确地址,在kepserver做个配置即可。
剩余的事情就是写程序,从kepserver里存取数据,就像访问数据库一样,OPCDAAuto是个不错的选择,现在我用的dotnet,网上down一个OPCDAAuto.dll直接使用,如何使用OPCDAAuto.dll网上也有很多例子。下面是简单例子:
using System;
using System.Windows.Forms;
using log4net;
using OPCAutomation; namespace OpcDaAutoTest
{
public partial class FormReader : Form
{
private ILog _logger = LogManager.GetLogger(typeof(Form1));
private System.Timers.Timer _timer = new System.Timers.Timer(); private OPCGroups _kepGroups = null;
private OPCGroup _groupOmron = null;
private OPCItem _omronQty = null;
private OPCItem _omronStart = null;
private OPCItem _omronWarn = null;
private OPCGroup _groupSiemens = null;
private OPCItem _siemensQty = null;
private OPCItem _siemensStart = null;
private OPCItem _siemensWarn = null; const string open = "正常";
const string close = "关机"; public FormReader()
{
InitializeComponent();
} private void FormReader_Load(object sender, EventArgs e)
{
GetLocalServer();
btnConnLocalServer.Click += btnConnLocalServer_Click;
FormClosing += OnFormClosing;
} private void OnFormClosing(object sender, FormClosingEventArgs formClosingEventArgs)
{
if (_kepServer != null)
{
_kepServer.Disconnect();
_kepServer = null;
}
} private bool ConnectRemoteServer(string remoteServerName)
{
try
{
_kepServer.Connect(remoteServerName); if (_kepServer.ServerState == (int)OPCServerState.OPCRunning)
{
tsslServerState.Text = "已连接到-" + _kepServer.ServerName;
}
else
{
//这里你可以根据返回的状态来自定义显示信息,请查看自动化接口API文档
tsslServerState.Text = "状态:" + _kepServer.ServerState;
}
}
catch (Exception err)
{
MessageBox.Show("连接远程服务器出现错误:" + err.Message, "提示信息", MessageBoxButtons.OK, MessageBoxIcon.Warning);
return false;
}
return true;
}
private void btnConnLocalServer_Click(object sender, EventArgs e)
{
try
{
if (!ConnectRemoteServer(cmbServerName.Text))
{
return;
} _kepGroups = _kepServer.OPCGroups;
_groupOmron = _kepGroups.Add("omron");
_omronQty = _groupOmron.OPCItems.AddItem("Channel_Omron.Device1.Qty", );
_omronStart = _groupOmron.OPCItems.AddItem("Channel_Omron.Device1.Start", );
_omronWarn = _groupOmron.OPCItems.AddItem("Channel_Omron.Device1.Warn", ); _groupSiemens = _kepGroups.Add("siemens");
_siemensQty = _groupSiemens.OPCItems.AddItem("Channel_Siemens.Device1.Qty", );
_siemensStart = _groupSiemens.OPCItems.AddItem("Channel_Siemens.Device1.Start", );
_siemensWarn = _groupSiemens.OPCItems.AddItem("Channel_Siemens.Device1.Warn", ); _timer.Elapsed += (o, args) =>
{
_timer.Enabled = false;
try
{
object value = null;
object quality = null;
object timestamp = null;
_omronQty.Read(, out value, out quality, out timestamp);
_logger.Debug(_omronQty.ItemID + "=" + value);
var yazhu7Qty = value;
_omronStart.Read(, out value, out quality, out timestamp);
_logger.Debug(_omronStart.ItemID + "=" + value);
value = value ?? true;
var yazhu7Start = value.Equals(false) ? open : close;
_omronWarn.Read(, out value, out quality, out timestamp);
_logger.Debug(_omronWarn.ItemID + "=" + value);
SaveData("Y7", yazhu7Start, yazhu7Qty);/*保存压铸7机台数据*/ _siemensQty.Read(, out value, out quality, out timestamp);
_logger.Debug(_siemensQty.ItemID + "=" + value);
var yazhu11Qty = value;
_siemensStart.Read(, out value, out quality, out timestamp);
_logger.Debug(_siemensStart.ItemID + "=" + value);
value = value ?? true;
var yazhu11Start = value.Equals(false) ? open : close;
_siemensWarn.Read(, out value, out quality, out timestamp);
_logger.Debug(_siemensWarn.ItemID + "=" + value);
SaveData("Y11", yazhu11Start, yazhu11Qty);/*保存压铸11机台数据*/
}
catch (Exception exception)
{
_logger.Error(exception);
}
finally
{
_timer.Enabled = true;
}
};
_timer.Enabled = true;
btnConnLocalServer.Enabled = false; }
catch (Exception err)
{
MessageBox.Show("初始化出错:" + err.Message, "提示信息", MessageBoxButtons.OK, MessageBoxIcon.Warning);
}
} private void SaveData(string machineNo, string start, object qty)
{
try
{
using (var db = DbAccess.GetDbContext())
{
if (start.Equals(close))
{
db.Sql("update kbequipment set running=@0 where type=0 and name=@1")
.Parameters(start, machineNo)
.Execute();
}
else
{
db.Sql("update kbequipment set running=@0, status=@1 where type=0 and name=@2")
.Parameters(start, qty, machineNo)
.Execute();
}
}
}
catch (Exception e)
{
_logger.Error(e.Message, e);
}
} private OPCServer _kepServer;
private void GetLocalServer()
{
try
{
_kepServer = new OPCServer();
object serverList = _kepServer.GetOPCServers(Environment.MachineName); foreach (string turn in (Array)serverList)
{
cmbServerName.Items.Add(turn);
} cmbServerName.SelectedIndex = ;
btnConnLocalServer.Enabled = true;
}
catch (Exception err)
{
MessageBox.Show("枚举本地OPC服务器出错:" + err.Message, "提示信息", MessageBoxButtons.OK, MessageBoxIcon.Warning);
} }
}
}
PLC数据访问的更多相关文章
- C#读写三菱PLC和西门子PLC数据 使用TCP/IP 协议
本文将使用一个Github开源的组件库技术来读写三菱PLC和西门子plc数据,使用的是基于以太网的TCP/IP实现,不需要额外的组件,读取操作只要放到后台线程就不会卡死线程,本组件支持超级方便的高性能 ...
- C# 读写西门子PLC数据,包含S7协议和Fetch/Write协议,s7支持200smart,300PLC,1200PLC,1500PLC
本文将使用一个gitHub开源的组件技术来读写西门子plc数据,使用的是基于以太网的TCP/IP实现,不需要额外的组件,读取操作只要放到后台线程就不会卡死线程,本组件支持超级方便的高性能读写操作 官方 ...
- python 读写三菱PLC数据,使用以太网读写Q系列,L系列,Fx系列的PLC数据
本文将使用一个gitHub开源的组件技术来读写三菱的plc数据,使用的是基于以太网的TCP/IP实现,不需要额外的组件,读取操作只要放到后台线程就不会卡死线程,本组件支持超级方便的高性能读写操作 gi ...
- java android 读写西门子PLC数据,包含S7协议和Fetch/Write协议,s7支持200smart,300PLC,1200PLC,1500PLC
本文将使用一个gitHub开源的组件技术来读写西门子plc数据,使用的是基于以太网的TCP/IP实现,不需要额外的组件,读取操作只要放到后台线程就不会卡死线程,本组件支持超级方便的高性能读写操作 gi ...
- C#读写西门子PLC数据
C#读写西门子PLC数据,包含S7协议和Fetch/Write协议,s7支持200smart,300PLC,1200PLC,1500PLC 本文将使用一个gitHub开源的组件技术来读写西门子plc数 ...
- C#读写三菱PLC数据 使用TCP/IP 协议
本文将使用一个Github开源的组件库技术来读写三菱PLC和西门子plc数据,使用的是基于以太网的TCP/IP实现,不需要额外的组件,读取操作只要放到后台线程就不会卡死线程,本组件支持超级方便的高性能 ...
- ADO.NET编程之美----数据访问方式(面向连接与面向无连接)
最近,在学习ADO.NET时,其中提到了数据访问方式:面向连接与面向无连接.于是,百度了一下,发现并没有很好的资料,然而,在学校图书馆中发现一本好书(<ASP.NET MVC5 网站开发之美&g ...
- 高性能Javascript--高效的数据访问
接上一篇,希望能写一个高性能Javascript专题. 第一篇:高性能Javascript--脚本的无阻塞加载策略. 参考摘录<高性能Javascript>. 经典计算机科学的一个问题是, ...
- 解析大型.NET ERP系统数据访问 对象关系映射框架LLBL Gen Pro
LLBL Gen Pro是一个为.NET开发人员设计的的对象关系映射(ORM)框架,与NHibernate,Entity Framework等框架一样,通过实体与数据表的映射,实现关系数据库持久化. ...
随机推荐
- Unity中创建二维码
在网络上发现了一个可以把字符串转换成二维码的dll,但是我们要怎么使用他呢.不废话,直接进入主题. 用到的引用 using UnityEngine;using ZXing;using ZXing.Qr ...
- .net core 学习笔记(4)-ViewComponent
动态菜单,以前用的是Html.Action(url)来获取的,到了 .net core 中忽然发现没有了这个方法,原来在 .net core 中是提供了个 ViewComponent,有点类似以前的用 ...
- 0427 scrum & 读后感
5.Scrum团队成立 5.1 团队名称,团队目标.团队口号.团队照: 5.2 角色分配 6. 团队项目选题 详情见团队博客:http://www.cnblogs.com/alfredzhu/ htt ...
- JS总结 节点
nodeName 获取节点名称 元素节点:返回标记名称 属性节点:返回属性名称 文本节点:返回文本#text nodeTyle 获取节点类型 元素节点:返回1 属性节点:返回2 文本节点:返回3 n ...
- Asp.net attributes collection
<?xml version="1.0" encoding="utf-8"?><root> <ContralNames> ...
- nexus7 一代 手动刷4.4.4
跟上一篇类似,但是中间出了点问题,提示说command write 出错,最后解决方法是电脑上换了个usb口插入....
- PHPSTORM模板变量注释
类似于这种注释,方便使用. 有两种方式一种是生成PHP文件时,自动生成,一种是手动生成. 第一种:自动生成 一图解释所有.这么配置就OK了. 这种方法还有一种就是,在包括里边编写,直接引用,先写PHP ...
- 【Learning Python】【第四章】Python代码结构(一)
这一章的主旨在于介绍python的代码结构 缩进 在很多的编程语言中,一般{}用于控制代码块,比如以下的一段C代码 if(var <= 10) { printf("....." ...
- 如何全面解决ECSHOP的jquery冲突
主要就是Ecshop的AJAX传输类,transport.js中重写了object的对象原型,从而导致了与jq框架的冲突. 解决: 1. 删除transport.js中587行 - 636行中关于ob ...
- IOS 关于NSString类型的属性为什么有时用copy,有时用strong呢?
对于很多初学者,发现在修饰NSString类型的对象时,会有这样的疑惑?怎么有些人用strong修饰,而有些人用copy修饰呢? 这里有个例子,一.首先声明2个属性: @property (nonat ...