赞
踩
1、导入S7.net通信文件:打开工具->NuGet包管理器->管理解决方案得NuGet程序包,入下图搜索S7,安装S7netplus。
在程序中引用S7.Net文件
建立西门子PLC类
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; using S7.Net; namespace 相机打开 { class SiemensPLC { //构造函数 public SiemensPLC() { _plc = new Plc((CpuType)_plcType, _ipAddress, _crack, _slot); //_plc = new Plc(CpuType.S71500, _ipAddress, _crack, _slot); } /// <summary> /// PLC类型:S7200=0;Logo0BA8=1;S7200Smart=2;S7300=10,S7400=20;S71200=30;S71500=40; /// </summary> public int PLCType { get => _plcType; set => _plcType = value; } /// <summary> /// IP地址 /// </summary> public string IpAdress { get => _ipAddress; set => IpAdress = value; } /// <summary> /// 机架 /// </summary> public short Crack { get => _crack; set => _crack = value; } /// <summary> /// 槽 /// </summary> public short Slot { get => _slot; set => _slot = value; } int _plcType=40; string _ipAddress="192.168.1.12"; short _crack = 0; short _slot = 1; Plc _plc; /// <summary> /// PLC连接状态 /// </summary> /// <returns></returns> public bool ConnectState { get => _plc.IsConnected; } /// <summary> /// PLC连接 /// </summary> public void Connect() { try { _plc.Open(); } catch(Exception ex) { MessageBox.Show("PLC连接失败:"+ex.Message.ToString()); } } /// <summary> /// 连接 /// </summary> public void Disconnect() { try { _plc.Close(); } catch (Exception ex) { MessageBox.Show("PLC断开失败:" + ex.Message.ToString()); } } /// <summary> /// 读取 /// </summary> /// <param name="varName"></param> /// <returns></returns> public object Read(string varName,string varType) { try { switch(varType) { case "布尔": case "整数": return _plc.Read(varName); case "实数": return ((uint)_plc.Read(varName)).ConvertToFloat(); case "字符": int dblength = varName.IndexOf(':') - 2;//DB号的长度 int db = Convert.ToInt32(varName.Substring(2, dblength));//DB号 int adrlength = varName.Length - varName.IndexOf(':') - 1;//startByteAdr的长度 int startByteAddress = Convert.ToInt32(varName.Substring(varName.IndexOf(':') + 1, adrlength));//startByteAdr var count = (byte)_plc.Read(DataType.DataBlock, db, startByteAddress, VarType.Byte, 1); return (string)_plc.Read(DataType.DataBlock, db, startByteAddress, VarType.S7String, count); default: return null; } } catch(Exception ex) { MessageBox.Show("读取失败:" + ex.Message.ToString()); return null; } } /// <summary> /// 写入 /// </summary> /// <param name="varName"></param> /// <param name="varValue"></param> /// <param name="type"></param>位、字节、单字、双字和字符 public void Write(string varName,string varValue,string type) { try { switch(type) { case "位": _plc.Write(varName, (varValue == "1") ? true : false); break; case "字节": _plc.Write(varName, Convert.ToByte(varValue)); break; case "单字": _plc.Write(varName, Convert.ToInt16(varValue)); break; case "双字": _plc.Write(varName, Convert.ToInt32(varValue)); break; case "实数": _plc.Write(varName, Convert.ToSingle(varValue)); break; case "字符": int dblength = varName.IndexOf(':') - 2;//DB号的长度 int db = Convert.ToInt32(varName.Substring(2,dblength));//DB号 int adrlength = varName.Length - varName.IndexOf(':')-1;//startByteAdr的长度 int startByteAddress = Convert.ToInt32(varName.Substring(varName.IndexOf(':')+1, adrlength));//startByteAdr //var temp = System.Text.Encoding.ASCII.GetBytes(varValue);//编码 var temp = System.Text.Encoding.Unicode.GetBytes(varValue);//编码 var bytes = S7.Net.Types.S7String.ToByteArray(varValue, temp.Length);//字节数组 _plc.WriteBytes(DataType.DataBlock, db, startByteAddress, bytes); break; default: break; } } catch(Exception ex) { MessageBox.Show("写入失败:" + ex.Message.ToString()); } } } }
参考教程:https://www.cnblogs.com/xhubobo/p/14573092.html
https://www.cnblogs.com/minily/p/13324120.html
建立winform程序
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; using System.Threading; using S7.Net; using HalconDotNet; using System.Diagnostics; namespace 相机打开 { public partial class Form1 : Form { bool isMThread = false;//是否位多线程模式 bool isStart = false;//线程模式启动 Task collectTask;//识别子线程 // Local iconic variables HObject ho_Image = null, ho_GrayImage = null; // Local control variables HTuple hv_AcqHandle = null;//相机窗口句柄 HTuple hv_WindowHandle = null;//窗口句柄 HTuple hv_Width = new HTuple(), hv_Height = new HTuple(); //PLC变量 SiemensPLC PLC = new SiemensPLC(); bool connectState = false; //线程变量 Thread monitorThread; public Form1() { InitializeComponent(); // Default settings used in HDevelop HOperatorSet.SetSystem("width", 512); HOperatorSet.SetSystem("height", 512); if (HalconAPI.isWindows) HOperatorSet.SetSystem("use_window_thread", "true"); action(); } /// <summary> /// 视觉窗口初始化 /// </summary> private void action() { // Initialize local and output iconic variables HOperatorSet.GenEmptyObj(out ho_Image); HOperatorSet.GenEmptyObj(out ho_GrayImage); //Image Acquisition 01: Code generated by Image Acquisition 01 //判断窗口是否打开 if(HDevWindowStack.IsOpen()) { HOperatorSet.CloseWindow(HDevWindowStack.Pop()); } HOperatorSet.SetWindowAttr("background_color", "black"); hv_WindowHandle = this.hWindowControl1.HalconID; HOperatorSet.OpenWindow(0, 0, this.hWindowControl1.Width, this.hWindowControl1.Height, this.hWindowControl1.HalconWindow, "visible", "", out hv_WindowHandle); HDevWindowStack.Push(hv_WindowHandle); } /// <summary> /// 采用定时器方式 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void timer1_Tick(object sender, EventArgs e) { if(hv_AcqHandle==null) { return; } CollectImage();//图像采集 } /// <summary> /// 图像采集 /// </summary> private void CollectImage() { ho_Image.Dispose(); if (hv_AcqHandle==null) { return; } HOperatorSet.GrabImageAsync(out ho_Image, hv_AcqHandle, -1); if (HDevWindowStack.IsOpen()) { HOperatorSet.DispObj(ho_Image, HDevWindowStack.GetActive()); } //HOperatorSet.WaitSeconds(0.1); ho_GrayImage.Dispose(); HOperatorSet.Rgb1ToGray(ho_Image, out ho_GrayImage); HOperatorSet.DispObj(ho_GrayImage, HDevWindowStack.GetActive()); HOperatorSet.GetImageSize(ho_GrayImage, out hv_Width, out hv_Height); HOperatorSet.SetPart(HDevWindowStack.GetActive(), 0, 0, hv_Height, hv_Width); //HOperatorSet.WaitSeconds(0.1); } /// <summary> /// 相机打开 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void btn_OpenCamera_Click(object sender, EventArgs e) { //打开相机 HOperatorSet.OpenFramegrabber("DirectShow", 1, 1, 0, 0, 0, 0, "default", 8, "rgb", -1, "false", "default", "[0] Integrated Camera", 0, -1, out hv_AcqHandle); HOperatorSet.GrabImageStart(hv_AcqHandle, -1); } /// <summary> /// 启动停止按钮 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void btn_StartCollect_Click(object sender, EventArgs e) { if(this.rdb_Timer.Checked==true) { if (this.timer1.Enabled == false) { this.timer1.Enabled = true; this.btn_StartCollect.Text = "停止采集"; this.rdb_MThread.Enabled = false; this.rdb_Timer.Enabled = false; } else { this.timer1.Enabled = false; this.btn_StartCollect.Text = "开始采集"; this.rdb_MThread.Enabled = true; this.rdb_Timer.Enabled = true; } } else if(this.rdb_MThread.Checked==true) { if(this.btn_StartCollect.Text=="开始采集") { isStart = true; btn_StartCollect.Text = "停止采集"; this.rdb_MThread.Enabled = false; this.rdb_Timer.Enabled = false; //实例化子线程 collectTask = new Task(() => { while (isStart) { CollectImage(); } }); collectTask.Start(); } else { this.btn_StartCollect.Text = "开始采集"; this.rdb_MThread.Enabled = true; this.rdb_Timer.Enabled = true; isStart = false; } } else { MessageBox.Show("请先选择模式!"); } } /// <summary> /// 关闭窗体 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void Form1_FormClosing(object sender, FormClosingEventArgs e) { Process.GetCurrentProcess().Kill(); } private void btn_PLCConnect_Click(object sender, EventArgs e) { //连接线程 ThreadPool.QueueUserWorkItem(t => PLC.Connect()); } /// <summary> /// 退出按钮 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void btn_Exit_Click(object sender, EventArgs e) { Process.GetCurrentProcess().Kill(); } private void btn_Disconnect_Click(object sender, EventArgs e) { //断开线程 ThreadPool.QueueUserWorkItem(t => PLC.Disconnect()); } private void Form1_Load(object sender, EventArgs e) { //监控线程 monitorThread = new Thread(monitorFunc); monitorThread.Start(); } private void btn_SingleRead_Click(object sender, EventArgs e) { ThreadPool.QueueUserWorkItem(t=>SingleRead()); } /// <summary> /// 关闭相机 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void btn_CloseCamera_Click(object sender, EventArgs e) { if (collectTask.Status == TaskStatus.Running || this.timer1.Enabled == true) { MessageBox.Show("请先停止采集!"); return; } //关闭相机 if (hv_AcqHandle != null) { HOperatorSet.CloseFramegrabber(hv_AcqHandle); } ho_Image.Dispose(); ho_GrayImage.Dispose(); } private void btn_Write_Click(object sender, EventArgs e) { ThreadPool.QueueUserWorkItem(t=>SingleWrite()); } public void monitorFunc() { while(true) { connectState = PLC.ConnectState; this.Invoke((MethodInvoker)delegate { lbl_ConnectState.Text = connectState ? "Connected" : "Disconnected"; btn_PLCConnect.Enabled = connectState ? false : true; btn_Disconnect.Enabled = connectState ? true : false; lbl_ConState.BackColor = connectState ? Color.Lime : Color.Red; }); Thread.Sleep(100); } } public void SingleRead() { connectState = PLC.ConnectState; this.Invoke((MethodInvoker)delegate { var value = PLC.Read(tbx_RSignleName.Text.Trim(), cbx_RTypeSelect.Text.Trim()); tbx_RSingleValue.Text = Convert.ToString(value); }); } public void SingleWrite() { this.Invoke((MethodInvoker)delegate { PLC.Write(tbx_WSignleName.Text.Trim(), tbx_WSingleValue.Text.Trim(), cbx_WTypeSelect.Text.Trim()); }); } } }
里面还包含一部分Halcon程序,最终的目的是实现PLC程序通过Halcon程序控制相机。
建立S71500PLC仿真
采用S7-PLCSIM Advanced 3.0
建立西门子博图项目
提前设置电脑的PG端口
在博图中建立一个DB块
打开西门子仿真软件
这个仿真软件用一段时间后就需要重启,否则博图下载程序时找不到端口,有时候还需要重新启动博图软件才能正常下载程序
首先连接PLC,然后给DB1.DBX0.0赋值1,观察博图的监控画面
写入成功
读取成功
分别尝试字节、单字、双字写入读取都顺利
实数读写
比较麻烦的是字符串的读取和写入
西门子PLC有两种字符串,一种是String,另一种是WString,前者是每一个字符由两个字节构成,大小为256个字节;后者是每一个字符由四个字节构成,大小为512个字节。
所以英文字符采用String,中文字符采用WString,虽然WString在博图中无法查看具体字符串,只能看到编码,但是不影响正常的写入和读取。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。