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等框架一样,通过实体与数据表的映射,实现关系数据库持久化. ...
随机推荐
- 2016 - 1 - 25 第三方网络框架 AFN的简单使用
AFNetworking 底层是对NSURlSession 和对 NSURLConnect 的包装 1.具体使用方法可以参照github上的主页面,在这里只是举一个文件上传的简单列子 - (void) ...
- MFC程序执行顺序 .
1.创建Application object对象theApp 程序一开始生产一个(且只有一个)Application object对象theApp,也即一个CWinApp对象,这个全局对象一产生,便执 ...
- 关于w3school的html5部分output 元素实例代码(点亲自试一试进去)的问题纠正
修复: 将原来的 = 号修改成 <input type="button" onclick="resCalc()" value ="=" ...
- Varnish介绍
“Varnish是一款高性能的开源HTTP加速器,挪威最大的在线报纸 Verdens Gang (http://www.vg.no) 使用3台Varnish代替了原来的12台squid,性能居然比以前 ...
- 修改HTTPD.CONF中的DocumentRoot,出现 You don't have permission to access /??? on this server.
apache 2.4 修改/conf/extra/httpd-vhosts.conf <VirtualHost _default_:80> DocumentRoot '${SRVROOT} ...
- pointer to function
指针.函数.数字.结构体.指针函数.函数指针 初学不好区分,做点儿实验来有效区分一下,以下代码采用dev-C++平台测试 //pointer to fucntion 函数功能是 基地址加偏移量得到偏移 ...
- 关于jQuery外部框架
(function(window, undefined) { var jQuery = ... ... window.jQuery = wind ...
- [GodLove]Wine93 Tarining Round #9
比赛链接: http://vjudge.net/contest/view.action?cid=48069#overview 题目来源: lrj训练指南---二维几何计算 ID Title Pro ...
- [转帖]零投入用panabit享受万元流控设备——搭建篇
原帖地址:http://net.it168.com/a2009/0505/274/000000274918.shtml 你想合理高效的管理内网流量吗?你想针对各个非法网络应用与服务进行合理限制吗?你是 ...
- Ubuntu Filezilla FTP Client 安装
/************************************************************************************* * Ubuntu File ...