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

本文记录源自:B站视频
实验结果:跟视频做下来是没有问题的。能运行。
自己补充做了视频中未实现的读取和写入数据部分【欢迎小伙伴指正不对的地方】

目录

  • 前言
  • 一、项目
    • Step1. 创建项目
    • Step2. 创建动态图片展示
    • Step3. 创建图片型按钮
    • Step4. 创建下拉框
    • Step1~4的效果展示
    • Step5. 编程
      • `实体类`
      • `操作类`
      • `Main函数`
    • Step1~5的效果展示
      • `Main函数`
    • 最终效果:
  • 二、补充内容
    • 1. FlatStyle属性
  • 三、读取和写入一个浮点数
    • Step6. 建立图形
    • Step7. 编程
      • `操作类`
      • `Main函数`
    • Step1~7的效果展示
  • 更新时间线


前言

在练习完基本的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类:

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类:

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函数

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函数

  • 添加了修改操作
       /// <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()方法
        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函数

  • 实现两个点击效果
        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:补充了读取和写入一个浮点数。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/800742.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

vue3表格使用拖拽排序

拖拽排序 实现效果实现步骤拖拽排序功能的完整代码 实现效果 实现步骤 先安装sortable.js库使用的vue文件中引入 import Sortablejs from ‘sortablejs’在进入页面后创建sortable实例在提交后端时可获取到排序后的最新table列表数据 sortable.js文档 拖拽排序功能的完整代码 …

SpringBoot中常用的注解及其用法

1. 常用类注解 RestController和Controller是Spring中用于定义控制器的两个类注解. 1.1 RestController RestController是一个组合类注解,是Controller和ResponseBody两个注解的组合,在使 用 RestController 注解标记的类中&#xff0c;每个方法的返回值都会以 JSON 或 XML…

4 C 语言控制流与循环结构的深入解读

目录 1 复杂表达式的计算过程 2 if-else语句 2.1 基本结构及示例 2.2 if-else if 多分支 2.3 嵌套 if-else 2.4 悬空的 else 2.5 注意事项 2.5.1 if 后面不要加分号 2.5.2 省略 else 2.5.3 省略 {} 2.5.4 注意点 3 while 循环 3.1 一般形式 3.2 流程特点 3.3 注…

语音识别概述

语音识别概述 一.什么是语音&#xff1f; 语音是语言的声学表现形式&#xff0c;是人类自然的交流工具。 图片来源&#xff1a;https://www.shenlanxueyuan.com/course/381 二.语音识别的定义 语音识别&#xff08;Automatic Speech Recognition, ASR 或 Speech to Text, ST…

智能厕所系统让厕位状态清晰可见

在当今科技飞速发展的时代&#xff0c;智能化的应用已经渗透到我们生活的方方面面&#xff0c;智能厕所系统就是其中一个令人瞩目的创新。其中&#xff0c;厕位有人无人实时显示这一功能&#xff0c;为人们带来了极大的便利和舒适。 当身处一个繁忙的公共场所&#xff0c;如商场…

嵌入式全栈设计思路:STM32G4+ChibiOS+FreeRTOS+PID控制+PFC算法构建高效智能电源管理系统(附代码示例)

智能电源管理系统是一个基于STM32G4微控制器的高性能数字电源控制解决方案。本项目旨在设计一个功能全面、高效稳定的电源管理系统,可广泛应用于工业控制、新能源、通信设备等领域。 1.1 系统主要特点 高精度数字电源控制&#xff1a;利用STM32G4的高性能ADC和定时器,实现精确…

【NLP实战】基于TextCNN的新闻文本分类

TextCNN文本分类在pytorch中的实现 基于TextCNN和transformers.BertTokenizer的新闻文本分类实现&#xff0c;包括训练、预测、数据加载和准确率评估。 目录 项目代码TextCNN网络结构相关模型仓库准备工作项目调参预测与评估 1.项目代码 https://github.com/NeoTse0622/Te…

C++相关概念和易错语法(22)(final、纯虚函数、继承多态难点)

1.final final在继承和多态中都可以使用&#xff0c;在继承中是指不想将自己被继承&#xff0c;在多态中是指不想该函数被重写&#xff0c;比较简单&#xff0c;下面是一些使用例子。 2.纯虚函数 当我们需要抽象一个类的时候&#xff0c;我们就需要用到纯虚函数。所谓抽象的类…

【微服务】Spring Cloud Config解决的问题和案例

文章目录 强烈推荐引言解决问题1. 配置管理的集中化2. 配置的版本控制3. 环境特定配置4. 配置的动态刷新5. 安全管理敏感数据6. 配置的一致性 组件1. **配置服务器&#xff08;Config Server&#xff09;**2. **配置客户端&#xff08;Config Client&#xff09;** 配置示例配置…

电脑数据恢复软件哪个好?这六款软件轻松恢复数据

随着电脑使用的日益频繁&#xff0c;数据的丢失也成为了一个不可避免的问题。在生活中&#xff0c;我们常因误删除、误格式化、分区失败、中病毒等而丢失数据。在这种情况下&#xff0c;一个好的数据恢复软件就显得尤为重要。 电脑数据恢复软件哪个好&#xff1f;本文将为大家…

Midjourney 商业实战案例(附AI学习工具教程资料)

前言 Midjourney 商业实战案例 &#xff08;附AI学习工具教程资料&#xff09; 如何把 AI 绘画应用到设计工作中&#xff1f; AI 绘画技术可以应用于设计工作中&#xff0c;帮助设计师更快速、更高效地完成设计工作&#xff0c;以下是一些常见的应用&#xff1a; **1. 快速…

对接企业微信API自建应用配置企业可信IP

前言 为了实现系统调用团队会议功能&#xff0c;组织发起企业微信会议&#xff0c;于是需要和企业微信做API对接。对接过程很难受&#xff0c;文档不清晰、没有SDK、没有技术支持甚至文档报文和实际接口报文都不匹配&#xff0c;只能说企业微信的API是从业以来见过的最难用的AP…

【数据结构与算法 经典例题】判断二叉树是否对称

&#x1f493; 博客主页&#xff1a;倔强的石头的CSDN主页 &#x1f4dd;Gitee主页&#xff1a;倔强的石头的gitee主页 ⏩ 文章专栏&#xff1a;《数据结构与算法 经典例题》C语言 期待您的关注 目录 一、问题描述 二、解题思路 三、C语言实现代码 一、问题描述 给你一个二…

ENSP中NAT的相关实验(两个私网,一个公网)

题目 实验需求 1.按照图示配置IP地址&#xff0c;公网地址100.1.1.1/24 2.私网A通过NAPT&#xff0c;使R1接入到互联网&#xff0c;私网B通过EASY IP&#xff0c;使R3接入到互联网 3.私网A配置NAT SERVER把Telnet的Telnet服务发布到公网&#xff0c;使PC2可以访问 三、实验…

Vue中使用mind-map实现在线思维导图

概述 在前面的文章Vue中实现在线画流程图实现中介绍了流程图的在线绘制&#xff0c;在本文&#xff0c;给大家分享一下基于mind-map实现在线的思维导图&#xff0c;并实现&#xff1a;1. 导图导出为图片&#xff1b;2. 打开xmind文件。 实现效果 实现 1. mind-map简介 simp…

随笔(三):CSS

一、CSS .&#xff08;类选择器&#xff09;和 #&#xff08;ID选择器&#xff09;在CSS中的主要区别在于它们的选择范围和用途&#xff1a; 1. 选择范围 类选择器&#xff08;. 开头&#xff09;&#xff1a; 类选择器用于选择具有指定类名的所有HTML元素。由于一个HTML元素…

spring boot基础知识

spring boot是整合spring 一系列的包的坐标集合 对依赖进行整合 总体介绍 spring boot是用来方便构建项目的工具 spring cloud是用来方便spring boot项目之间进行数据交互通讯和配置的 spring cloud data Flow 是用来进行数据的连接的 Spring 缺点 配置繁琐 虽然Spring的组件代…

超市管理系统 需求分析与设计 UML 方向

一、项目介绍 1.1项目背景 随着经济一体化和电子商务的迅速发展&#xff0c;网络传播信息的速度打破了传统信息传递的模式&#xff0c;互联网的高速发展和计算机应用在各个高校进展迅速&#xff0c;更多信息化产品的突飞猛进&#xff0c;让现代的管理模式也发生了巨大的变化&…

vue数据缓存

data 对象未定义或未正确传递&#xff1a;确保 data 对象在你调用 onMounted 钩子时已经存在且包含 base.columns 属性。 columns 响应式引用未定义&#xff1a;确保 columns 是一个使用 ref 或 reactive 创建的响应式引用。 异步数据问题&#xff1a;如果 data 是通过异步操…

vue 搭建 pinia

文章目录 环境设置存储读取数据【 storeToRefs】借助storeToRefs将store中的数据转为ref对象&#xff0c;方便在模板中使用【getters】当state中的数据&#xff0c;需要经过处理后再使用时&#xff0c;可以使用getters配置【$subscribe】通过 store 的 $subscribe() 方法侦听 s…