记录|.NET上位机开发和PLC通信的实现

本文记录源自:B站视频

实验结果:跟视频做下来是没有问题的。能运行。

自己补充做了视频中未实现的读取和写入数据部分【欢迎小伙伴指正不对的地方】

目录


前言

在练习完基本的C#和.NET使用后,做下了记录|C#连接PLC通讯

现在打算跟B站视频做一个简单的C#项目。这篇文章做这个记录。


一、项目

Step1. 创建项目

  • 是个Windows窗口(.NET framework)

Step2. 创建动态图片展示

  • 首先,在自己项目的Debug文件位置处,去建立个images文件,用于存放图片【其中,Debug文件是指自己调试的程序;Release文件是指上线使用的程序】
  • 动图需要准备一张.png和一张.gif
  • 在使用PictureBox组件,将图片添加进去,将组件的属性中的SizeMode改为Zoom

Step3. 创建图片型按钮

  • 目的:实现一个具有图片的按钮【本质是button控件】
  • 先对button中FlatSytle属性改为Flat,之后才能使用Image属性。

    据此创建出两个图片按钮:
  • 连接PLC按钮
  • 启动设备按钮

Step4. 创建下拉框

  • ComboBox组件
    在里面提前设定好两个值:S71200和S71500

Step1~4的效果展示


Step5. 编程

实体类

  • 创建Models文件夹,存放实体类EquipState。
  • 实体类类名:EquipState
  • 只存放方法名,等待实现

EquipState类:

csharp 复制代码
namespace thinger.ProjectDemo
{
    /// <summary>
    /// 生产设备状态实体类
    /// </summary>
    internal class EquipState
    {
        public bool Start { get; set; }//设备启动

        public bool Stop { get; set; }//停止

        public bool Task1 { get; set; }//任务1

        public bool Task2 { get; set; }
        public bool Task3 { get; set; }
        public bool RunState { get; set; }//运行状态:1,正常   0 报警
        public ushort RunModel { get; set; }//运行模式:1,普通 2,加速    3,满载
        public float SiteData1 { get; set; }//位置数据1
        public float SiteData2 { get; set; }//位置数据2
        public float SiteData3 { get; set; }//位置数据3
        public float SpeedData1 { get; set; }//速度数据1
        public float SpeedData2 { get; set; }//速度数据2
    }
}

操作类

  • 创建个Manager文件,该文件夹下面创建EquipControlManager类
  • 类中的基本3个方法:ConnectPLC、ClosePLC、WriteDataToPLC
  • ConnectPLC,实现对PLC的连接并返回提示。因此,返回类型位string。

EquipControlMananger类:

csharp 复制代码
namespace thinger.ProjectDemo.Manager
{
    /// <summary>
    /// 设备操作类
    /// </summary>
    internal class EquipControlManager
    {
        //先对Plc对象进行声明
        private Plc s7NetPlc = null;

        /// <summary>
        /// 连接PLC
        /// </summary>
        /// <param name="ipAddress"></param>
        /// <param name="cpuType"></param>
        /// <returns></returns>
        public string ConnectPLC(string ipAddress, string cpuType)
        {
            try
            {
                //CpuType是个enum,枚举类型,因此,需要对string类型进行转换
                CpuType currentCpuType = (CpuType)Enum.Parse(typeof(CpuType), cpuType, true);

                s7NetPlc = new Plc(currentCpuType, ipAddress, 0, 0);
                s7NetPlc.Open();
                return "PLC连接成功";
            }
            catch (Exception ex)
            {
                return $"PLC连接失败,{ex.Message}";
            }

        }

        /// <summary>
        /// 关闭PLC
        /// </summary>
        public void ClosePLC()
        {
            s7NetPlc.Close();
        }

        /// <summary>
        /// 按照指定地址,写入数据【位、字节、字、双字】
        /// </summary>
        /// <param name="varAddress"></param>
        /// <param name="varValue"></param>
        /// <returns></returns>
        public string WriteDataToPLC(string varAddress, object varValue)
        {
            lock (this)
            {
                try
                {
                    this.s7NetPlc.Write(varAddress, varValue);
                    return "写入数据成功";
                }
                catch (Exception ex)
                {
                    return $"写入数据失败,{ex.Message}";
                }

            }
        }
    }
}

Main函数

csharp 复制代码
namespace thinger.ProjectDemo
{
    public partial class FrmMain : Form
    {
        private EquipControlManager controlManger=new EquipControlManager();
        public FrmMain()
        {
            InitializeComponent();
        }
        
        /// <summary>
        /// 打开和关闭PLC
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnPLCConnect_Click(object sender, EventArgs e)
        {
            //Tag记录的是之前的开关状态,只有off和on
            //如果之前off,那么改为on
            if (this.btnPLCConnect.Tag.ToString().Equals("off"))
            {
                string connectManager = controlManger.ConnectPLC("192.168.0.10", this.cbbPLCType.Text);
                this.btnPLCConnect.Tag = "on";
                this.btnPLCConnect.Image = Image.FromFile("images/plcOpen.png");
                MessageBox.Show(connectManager);
            }
            else
            {
                controlManger.ClosePLC();
                this.btnPLCConnect.Tag="off";
                this.btnPLCConnect.Image = Image.FromFile("images/plcClose.png");
            }
        }
    }
}

Step1~5的效果展示


Main函数

  • 添加了修改操作
csharp 复制代码
       /// <summary>
       /// 操作设备
       /// </summary>
       /// <param name="sender"></param>
       /// <param name="e"></param>
       private void btnSwitch_Click(object sender, EventArgs e)
       {
           if (this.btnPLCConnect.Tag.ToString().Equals("off"))
           {
               MessageBox.Show("请先连接PLC", "操作提示");
               return;
           }
           //获取Tag中的地址值
           string[] tags = this.btnSwitch.Tag.ToString().Split('-');

           if (tags[0].Equals("off"))
           {
               //打开冷却泵
               this.pictureBox1.Image = Image.FromFile("images/电机.gif");
               this.btnSwitch.Image = Image.FromFile("images/btnOn.png");
               this.btnSwitch.Tag = $"on-{tags[1]}";
               //修改PLC中的值
               controlManger.WriteDataToPLC(tags[1], true);
           }
           else
           {
               this.pictureBox1.Image = Image.FromFile("images/电机.png");
               this.btnSwitch.Image = Image.FromFile("images/btnOff.png");
               this.btnSwitch.Tag = $"off-{tags[1]}";
               //修改PLC中的值
               controlManger.WriteDataToPLC(tags[1], false);
           }

       }

最终效果:


二、补充内容

1. FlatStyle属性

  • 功能:设置Windows Forms控件(如:按钮、标签等)。
  • Flat:产生"平面"效果,将空间的边框移除
  • Standard:默认,三维效果。

三、读取和写入一个浮点数

接着前面的Step5进行的

Step6. 建立图形

  • 两个按钮+两个文本框【如下所示:红色的部分是对组件重新的取名,便于后面的编程

Step7. 编程

操作类

  • 重写了一个WriteDataToPLC()方法【因为我不会用DBX0.0,DBW0,DBD0.0等用法,所以我想到直接按照 PLC.Write()的第二种重写方法,来重写】
  • 一个ReadDataFromPLC()方法
csharp 复制代码
        public string WriteDataToPLC(int db, string varAddress, object varValue)
        {
            int varAd = int.Parse(varAddress);
            float varVal = float.Parse(varValue.ToString());
            lock (this)
            {
                try
                {
                    s7NetPlc.Write(DataType.DataBlock, db, varAd,varVal);
                    return "写入数据成功";
                }catch(Exception ex)
                {
                    return $"写入数据失败,{ex.Message}";
                }
            }
        }

        public string ReadDataFromPLC(int db, string varAddress)
        {
            int varAd = int.Parse(varAddress);
            try
            {
                return s7NetPlc.Read(DataType.DataBlock, db, varAd, VarType.Real, 1).ToString();
            }catch(Exception ex)
            {
                return $"写入数据失败,{ex.Message}";
            }
        }

Main函数

  • 实现两个点击效果
csharp 复制代码
        private void writeDB0_Click(object sender, EventArgs e)
        {
            string writeMessage = controlManger.WriteDataToPLC(1,writeDB0.Tag.ToString(),textBox_writeDB0.Text);
            textBox_writeDB0.Text = "";
            MessageBox.Show(writeMessage);

        }

        private void readDB0_Click(object sender, EventArgs e)
        {
            string readMessage = controlManger.ReadDataFromPLC(1,readDB0.Tag.ToString());
            if (readMessage.Contains("失败"))
            {
                MessageBox.Show(readMessage);
                return;
            }
            textBox_readDB0.Text = readMessage;
        }

Step1~7的效果展示

读取一个浮点:

写入一个浮点数

更新时间线

  • 2024.07.15:创建文章
  • 2024.07.16:补充了读取和写入一个浮点数。
相关推荐
dsywws1 小时前
Linux学习笔记之vim入门
linux·笔记·学习
m0_656974741 小时前
C#中的集合类及其使用
开发语言·c#
晨曦_子画1 小时前
3种最难学习和最容易学习的 3 种编程语言
学习
九鼎科技-Leo1 小时前
了解 .NET 运行时与 .NET 框架:基础概念与相互关系
windows·c#·.net
城南vision2 小时前
Docker学习—Docker核心概念总结
java·学习·docker
ctrey_2 小时前
2024-11-1 学习人工智能的Day20 openCV(2)
人工智能·opencv·学习
十年之少3 小时前
由中文乱码引来的一系列学习——Qt
学习
u0101526583 小时前
STM32F103C8T6学习笔记2--LED流水灯与蜂鸣器
笔记·stm32·学习
九鼎科技-Leo4 小时前
什么是 ASP.NET Core?与 ASP.NET MVC 有什么区别?
windows·后端·c#·asp.net·mvc·.net
.net开发4 小时前
WPF怎么通过RestSharp向后端发请求
前端·c#·.net·wpf