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等框架一样,通过实体与数据表的映射,实现关系数据库持久化. ...
随机推荐
- php 画图片3
<?php // 中文验证码 // 1. 创建画布 $im = imagecreatetruecolor(200, 200); // 2. 创建背景色 // 2.1得到背景颜色 $bg_colo ...
- MP3播放器团队项目
一.设计思路 程序要求能播放MP3文件,因此需调用库中的播放方法:右键工具箱选择项,添加com组件,选择window media player后工具箱就会多一个控件,然后拖到窗体中就OK了.另在窗体中 ...
- Google play(Android market)账户申请
从09年到现在,Google play账户在国内申请一直都是个问题,根本的原因是国内不支持Google wallet(原Google Checkout) 在国内要获取一个Google play账户,常 ...
- win7 32 bit VS2012 OpenCV3.0配置
今天看CPP基础,想起来之前在vs2012配置opencv3未成功,就忍不住再次配置一... 环境:win7 32bit vs2012 opencv3.0 主要参考这几篇博文:1,2,3 上面的博文已 ...
- zynq中uboot的qspi启动报错及解决办法
问题描述: 用u-boot-xlnx-v2016.3版本编译的uboot通过qspi flash启动出现如下错误: 尝试在uboot命令行输入"sf probe 0 0 0"挂载q ...
- 判断是否存在哈密顿路--HDU 5424
题意:给一张无向图,判断是否是哈密顿图. 哈密顿路:经过每个点有且仅有一次的一条通路. 方法:每次找度数最小的点作为起点,然后dfs整个图,看能遍历到的点的数目能否达到n. #include<i ...
- php组合
为了提高代码的复用性,降低代码的耦合(组合实现的两种方式) 模式一: <?php //组合模式一 class Person{ public function eat(){ echo " ...
- TeeChart常用编程语句汇总(C#)
我用的是C# 从网上看到资料拷贝过来备忘,共同学习下: 设置chart标题:axTChart1.Header.Text.Add("标题"); 修改标题:axTChart1.Hea ...
- 调用DiscuzNT webApi 注册 登录 发帖
注册.登录Discuz论坛比较简单,网上很多教程. 3.发帖出现的问题 1.iis8.0版本 asp.net 4.0 不能发帖 将discuz 的web.config文件里的 此代码 <htt ...
- The Swift Programming Language 英文原版官方文档下载
The Swift Programming Language 英文原版官方文档下载 今天Apple公司发布了新的编程语言Swift(雨燕)将逐步代替Objective-C语言,大家肯定想学习这个语言, ...