PLC数据访问

时间:2023-03-09 19:53:50
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);
} }
}
}