当前位置:   article > 正文

西门子PLC与C#程序的S7.net通信

s7.net

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());
            }
 
        }

    }
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • 158
  • 159
  • 160
  • 161
  • 162
  • 163
  • 164
  • 165
  • 166
  • 167
  • 168
  • 169

参考教程: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());
            });
           
        }
    }
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • 158
  • 159
  • 160
  • 161
  • 162
  • 163
  • 164
  • 165
  • 166
  • 167
  • 168
  • 169
  • 170
  • 171
  • 172
  • 173
  • 174
  • 175
  • 176
  • 177
  • 178
  • 179
  • 180
  • 181
  • 182
  • 183
  • 184
  • 185
  • 186
  • 187
  • 188
  • 189
  • 190
  • 191
  • 192
  • 193
  • 194
  • 195
  • 196
  • 197
  • 198
  • 199
  • 200
  • 201
  • 202
  • 203
  • 204
  • 205
  • 206
  • 207
  • 208
  • 209
  • 210
  • 211
  • 212
  • 213
  • 214
  • 215
  • 216
  • 217
  • 218
  • 219
  • 220
  • 221
  • 222
  • 223
  • 224
  • 225
  • 226
  • 227
  • 228
  • 229
  • 230
  • 231
  • 232
  • 233
  • 234
  • 235
  • 236
  • 237
  • 238
  • 239
  • 240
  • 241
  • 242
  • 243
  • 244
  • 245
  • 246
  • 247
  • 248
  • 249
  • 250
  • 251
  • 252
  • 253
  • 254
  • 255
  • 256
  • 257
  • 258
  • 259
  • 260
  • 261
  • 262
  • 263
  • 264
  • 265
  • 266
  • 267
  • 268
  • 269
  • 270
  • 271
  • 272
  • 273
  • 274
  • 275
  • 276
  • 277
  • 278
  • 279
  • 280
  • 281
  • 282
  • 283
  • 284
  • 285
  • 286
  • 287
  • 288
  • 289
  • 290
  • 291
  • 292
  • 293
  • 294
  • 295
  • 296
  • 297

里面还包含一部分Halcon程序,最终的目的是实现PLC程序通过Halcon程序控制相机。

建立S71500PLC仿真
采用S7-PLCSIM Advanced 3.0
建立西门子博图项目
在这里插入图片描述
在这里插入图片描述
提前设置电脑的PG端口
在这里插入图片描述
在博图中建立一个DB块
在这里插入图片描述
打开西门子仿真软件
在这里插入图片描述
这个仿真软件用一段时间后就需要重启,否则博图下载程序时找不到端口,有时候还需要重新启动博图软件才能正常下载程序
在这里插入图片描述
首先连接PLC,然后给DB1.DBX0.0赋值1,观察博图的监控画面
在这里插入图片描述
在这里插入图片描述
写入成功
在这里插入图片描述
读取成功
分别尝试字节、单字、双字写入读取都顺利

实数读写
在这里插入图片描述

比较麻烦的是字符串的读取和写入
西门子PLC有两种字符串,一种是String,另一种是WString,前者是每一个字符由两个字节构成,大小为256个字节;后者是每一个字符由四个字节构成,大小为512个字节。
在这里插入图片描述

所以英文字符采用String,中文字符采用WString,虽然WString在博图中无法查看具体字符串,只能看到编码,但是不影响正常的写入和读取。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/花生_TL007/article/detail/290053
推荐阅读
相关标签
  

闽ICP备14008679号