1、概述
前面通过坚强的努力,实现了多种数据类型的读写,发现还是灰常棒的,但也显示了它的不灵活性,伙伴们肯定有很多疑问,比如如何做到一个简单的命令实现读写,而不是自己拼接那些非常复杂的报文,这对开发者是很困难的,是的,这个都会解决,那就是自己动手搞通讯库开发,实现高大上的目标,但在自己动手开发通讯库之前,我们先来了解使用别人已经写好的工具,也就是通讯库S7.NET,后面开始我们来搞自己的通讯库开发,实现顶峰冲刺。
2、S7.NET通讯库介绍
S7.NET是一个广泛应用于.NET平台的西门子PLC通信库,在使用西门子PLC进行工业自动化控制的过程中,经常利用这个工具实现与PLC进行数据交换。它为开发者提供了一系列的API函数,以便在C#、VB.NET等.NET语言中轻松实现与西门子PLC的数据交互。不过要注意的是,他仅支持以太网连接,这就表示你的设备PLC必须profinet cpu或profine外部卡,这个库采用C#编写,是基于.NET Framework或.NET Core的通信库,它通过一系列的COM组件或直接引用Native DLL文件,提供了与西门子S7系列PLC进行数据交换的接口,因此可以轻松进行调用。s7.net支持以下PLC:s7-200,s7-300,s7-400,s7-1200,s7-1500。
3、一起来
1、确保PLC硬件工作正常
这点要注意,很多人在执行程序时候,发现 代码完全没有问题,就是总异常,PLC连接失败,因此要保证前期搭建的西门子博途环境都是正常的
2、创建VS项目
这里为了展示方便,采用winform而不是控制台程序来实现应用
3、UI布局
布局方面没有精致设计,时间精力有限,要美化效果,出颜值的话需要使用另外的WINFORM控件框架,这里核心是通信操作,目前这样子,也不算差,基本效果有了,可以交差。
4、引入通讯库
5、连接与断开
6、产品号读取(字符串)
7、状态读取(bool)
8、水量读取(short)
9、液位读取(float)
全部代码
using S7.Net;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using static System.Windows.Forms.VisualStyles.VisualStyleElement.TrackBar;
namespace west.s7siemenstest
{
public partial class Form1 : Form
{
//1 ip地址 端口号 机架号 0 插槽 1
int port;
short rack = 0;
short slot = 1;
string ip = "";
//2.plc实例
Plc plc = null;
//CPU型号
CpuType cpuType = CpuType.S71500;
public Form1()
{
InitializeComponent();
}
/// <summary>
/// 连接PLC
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void btnConne_Click(object sender, EventArgs e)
{
ip = txtip.Text.Trim();
port = Convert.ToInt32(txtport.Text.Trim());
//创建plc实例
plc = new Plc(cpuType, ip, port, rack, slot);
if (plc != null )
{
plc.Open();//打开连接
if (plc.IsConnected)
{
this.btnConne.Enabled = false;
textBox1.Text = "连接PLC成功";
MessageBox.Show("连接PLC成功.");
}
}
}
/// <summary>
/// 断开
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void btnClose_Click(object sender, EventArgs e)
{
if (plc == null)
{
MessageBox.Show("PLC没有连接.");
return;
}
if (plc.IsConnected)
{
plc.Close();//关闭
textBox1.Text = "已断开PLC";
MessageBox.Show("已断开PLC");
this.btnConne.Enabled = true;
}
}
/// <summary>
/// 读取字符串
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void button9_Click(object sender, EventArgs e)
{
if (plc == null)
{
MessageBox.Show("请先连接PLC");
return;
}
if (plc.IsConnected)
{
var totalcount = plc.Read(DataType.DataBlock, 1, 22, VarType.Byte, 1);
var lengthcount = plc.Read(DataType.DataBlock, 1, 23, VarType.Byte, 1);
int length = Convert.ToInt32(lengthcount);
string textname = plc.Read(DataType.DataBlock, 1, 24, VarType.String, length).ToString();
textBox1.Text = textname;
MessageBox.Show(textname,"产品号:");
}
}
/// <summary>
/// bool读取
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void button1_Click(object sender, EventArgs e)
{
if (plc == null)
{
MessageBox.Show("请先连接PLC");
return;
}
if (plc.IsConnected)
{
var varaddr = "DB1.DBX0.0";
var obj = plc.Read(varaddr);
textBox1.Text = obj.ToString();
MessageBox.Show(obj.ToString());
}
}
private void button2_Click(object sender, EventArgs e)
{
if (plc == null)
{
MessageBox.Show("请先连接PLC");
return;
}
if (plc.IsConnected)
{
var varaddr = "DB1.DBX0.1";
var obj = plc.Read(varaddr);
textBox1.Text = obj.ToString();
MessageBox.Show(obj.ToString());
}
}
/// <summary>
/// short读取水量
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void button3_Click(object sender, EventArgs e)
{
Button mybtn = (Button)sender;
string tag = mybtn.Tag.ToString();
string varaddr = "";
switch (tag)
{
case "pum1water":
varaddr = "DB1.DBW2";
string str = plc.Read(varaddr).ToString() ;
int cc = Convert.ToInt32(str);
byte[] objbyte = BitConverter.GetBytes(cc);//转成字节数组
short te = BitConverter.ToInt16(objbyte, 0);//将字节数组转成short
textBox1.Text = te.ToString();
MessageBox.Show(te.ToString());
break;
case "pum2water":
varaddr = "DB1.DBW4";
var obja = plc.Read(varaddr);
textBox1.Text = obja.ToString();
MessageBox.Show(obja.ToString());
break;
default:
break;
}
}
/// <summary>
/// float读取
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void button5_Click(object sender, EventArgs e)
{
Button mybtn = (Button)sender;
string tag = mybtn.Tag.ToString();
string varaddr = "";
switch (tag)
{
case "pat1":
varaddr = "DB1.DBD6";
break;
case "pat2":
varaddr = "DB1.DBD10";
break;
case "pbt1":
varaddr = "DB1.DBD14";
break;
case "pbt2":
varaddr = "DB1.DBD18";
break;
default:
break;
}
var obj = plc.Read(varaddr);//返回的是uint
byte[] objbyte = BitConverter.GetBytes((uint)obj);
float objfloat = BitConverter.ToSingle(objbyte, 0);
textBox1.Text = objfloat.ToString();
MessageBox.Show(objfloat.ToString());
}
}
}
4、小结
掌握西门子S7.NET通信库的使用,可以帮助开发者更高效地进行工业自动化控制系统的开发和维护。通过本文的学习,希望读者能够掌握S7.NET通信库的基本使用方法,并在实际的开发工作中灵活运用, 在实际应用中,开发者需要根据PLC的具体型号和配置,以及数据块的结构,来正确地选择数据块和读取数据。在使用S7.NET通信库时,需要注意的是,读操作的性能和效率非常重要,尤其是在工业现场,可能会涉及到大量的数据读写。因此,合理地设计程序结构,优化数据读取方式,对于保证系统的稳定性和实时性至关重要。此外,当进行PLC编程和通信时,安全性和可靠性也是不可忽视的因素。确保通信过程中的数据完整性和正确性,以及对PLC编程的规范性,都是保证控制系统安全可靠运行的关键。
这个通讯库还是蛮厉害的,真的香啊,下节来搞自己的通讯库,开发自己的通讯库,冲击奥运金牌,坐宝马开飞机。
原创不易,打字截图不易,走过路过,不要错过,欢迎点赞,收藏,转载,复制,抄袭,留言,动动你的金手指,早日实现财务自由