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数据访问的更多相关文章

  1. C#读写三菱PLC和西门子PLC数据 使用TCP/IP 协议

    本文将使用一个Github开源的组件库技术来读写三菱PLC和西门子plc数据,使用的是基于以太网的TCP/IP实现,不需要额外的组件,读取操作只要放到后台线程就不会卡死线程,本组件支持超级方便的高性能 ...

  2. C# 读写西门子PLC数据,包含S7协议和Fetch/Write协议,s7支持200smart,300PLC,1200PLC,1500PLC

    本文将使用一个gitHub开源的组件技术来读写西门子plc数据,使用的是基于以太网的TCP/IP实现,不需要额外的组件,读取操作只要放到后台线程就不会卡死线程,本组件支持超级方便的高性能读写操作 官方 ...

  3. python 读写三菱PLC数据,使用以太网读写Q系列,L系列,Fx系列的PLC数据

    本文将使用一个gitHub开源的组件技术来读写三菱的plc数据,使用的是基于以太网的TCP/IP实现,不需要额外的组件,读取操作只要放到后台线程就不会卡死线程,本组件支持超级方便的高性能读写操作 gi ...

  4. java android 读写西门子PLC数据,包含S7协议和Fetch/Write协议,s7支持200smart,300PLC,1200PLC,1500PLC

    本文将使用一个gitHub开源的组件技术来读写西门子plc数据,使用的是基于以太网的TCP/IP实现,不需要额外的组件,读取操作只要放到后台线程就不会卡死线程,本组件支持超级方便的高性能读写操作 gi ...

  5. C#读写西门子PLC数据

    C#读写西门子PLC数据,包含S7协议和Fetch/Write协议,s7支持200smart,300PLC,1200PLC,1500PLC 本文将使用一个gitHub开源的组件技术来读写西门子plc数 ...

  6. C#读写三菱PLC数据 使用TCP/IP 协议

    本文将使用一个Github开源的组件库技术来读写三菱PLC和西门子plc数据,使用的是基于以太网的TCP/IP实现,不需要额外的组件,读取操作只要放到后台线程就不会卡死线程,本组件支持超级方便的高性能 ...

  7. ADO.NET编程之美----数据访问方式(面向连接与面向无连接)

    最近,在学习ADO.NET时,其中提到了数据访问方式:面向连接与面向无连接.于是,百度了一下,发现并没有很好的资料,然而,在学校图书馆中发现一本好书(<ASP.NET MVC5 网站开发之美&g ...

  8. 高性能Javascript--高效的数据访问

    接上一篇,希望能写一个高性能Javascript专题. 第一篇:高性能Javascript--脚本的无阻塞加载策略. 参考摘录<高性能Javascript>. 经典计算机科学的一个问题是, ...

  9. 解析大型.NET ERP系统数据访问 对象关系映射框架LLBL Gen Pro

    LLBL Gen Pro是一个为.NET开发人员设计的的对象关系映射(ORM)框架,与NHibernate,Entity Framework等框架一样,通过实体与数据表的映射,实现关系数据库持久化. ...

随机推荐

  1. iOS中block的用法 以及和函数用法的区别

    ios中block的用法和函数的用法大致相同 但是block的用法的灵活性更高: 不带参数的block: void ^(MyBlock)() = ^{}; 调用的时候  MyBlock(); 带参数的 ...

  2. Hadoop程序运行中的Error(1)-Error: org.apache.hadoop.hdfs.BlockMissingException

    15/03/18 09:59:21 INFO mapreduce.Job: Task Id : attempt_1426641074924_0002_m_000000_2, Status : FAIL ...

  3. TE9手机微信场景

    HTML <!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8& ...

  4. asp.net中的GridView控件的部分知识点

    <PagerTemplate> <br /> <asp:Label ID="lblPage" runat="server" Tex ...

  5. callee的用法

    callee返回正被执行的 Function 对象,也就是所指定的 Function 对象的正文.[function.]arguments.callee可选项 function 参数是当前正在执行的 ...

  6. LVM逻辑卷基本概念及LVM的工作原理

    这篇随笔将详细讲解Linux磁盘管理机制中的LVM逻辑卷的基本概念以及LVM的工作原理!!! 一.传统的磁盘管理 其实在Linux操作系统中,我们的磁盘管理机制和windows上的差不多,绝大多数都是 ...

  7. 关于IIS服务器证书续订

    输入办证机构+服务器名或IP 办证机构可以通过certsrv.msc来查看 输入完后点完成

  8. Hibernate save, saveOrUpdate, persist, merge, update 区别

    Hibernate Save hibernate save()方法能够保存实体到数据库,正如方法名称save这个单词所表明的意思.我们能够在事务之外调用这个方法,这也是我不喜欢使用这个方法保存数据的原 ...

  9. SpringMVC笔记

    Struts1是采用单例模式的,在并发访问中出来资源混乱,于是出现Struts2被设计为多例的解决并发产生的 数据混乱由于Struts2引入了值栈,拦截器,OGNL等,,,是访问速度下降在原生的JSP ...

  10. <mate>

    1.<meta http-equiv="X-UA-Compatible" content="IE=edge"> 以最高级别的可用模式显示内容 有些因 ...