C#与PLC变量在数据交互上的一些探索

1. 基于C#的数据交互

A. 用静态变量存储PLC的交互数据

  • UI和PLC变量如下:

  • 新建static类

    internal static class data_yamltest_exchange
    {
        public static byte byte_var;
        public static short word_var;
        public static bool bool_var;
    }
  • 数据交互,这里的数据二次封装过的,基于S7协议封装的,这里不深究
            //task1
            Task.Run(() =>
            {
                while (true)
                {
                    if (my_plc_status)
                    {
                        //read from plc
                        data_yamltest_exchange.bool_var = my_s7.bool_rw_value(132, my_plc_iDB, 4, "r", 0); ;

                        //write to plc 
                        my_s7.write_read_value("word", 132, my_plc_iDB, 2, "w", data_yamltest_exchange.word_var, 0, 1);
                        my_s7.write_read_value("byte", 132, my_plc_iDB, 0, "w", data_yamltest_exchange.byte_var, 0, 1);
                    }
                }
            });
  • UI后端代码,这里用了两个委托来完成radioButton的显示
    public partial class _6Yaml_test : UserControl
    {
        public _6Yaml_test()
        {
            InitializeComponent();
            this.textBox1.Text = "0";
            this.textBox2.Text = "0";
        }
        string val = null;
        bool status = false;
        private void _6Yaml_test_Load(object sender, EventArgs e)
        {
            Task.Run(() =>
            {
                setTextCallBack sV = new setTextCallBack(setValue);
                setRadioCallBack rV = new setRadioCallBack(setStatus);
                while (true)
                {
                    if (data_yamltest_exchange.bool_var == true)
                    {
                        status = true;
                        val = "bool have been enabled";
                        radioButton1.Invoke(sV, val);
                        radioButton1.Invoke(rV, status);
                    }
                    else
                    {
                        status = false;
                        val = "bool have been disabled";
                        radioButton1.Invoke(sV, val);
                        radioButton1.Invoke(rV, status);
                    }
                    try
                    {
                        data_yamltest_exchange.word_var = Convert.ToInt16(textBox2.Text.ToString());
                        data_yamltest_exchange.byte_var = Convert.ToByte(textBox1.Text.ToString());
                    }
                    catch { break; };
                }
            });
        }
        //cross-thread delivery
        //1.delegate type
        public delegate void setTextCallBack(string val);
        public delegate void setRadioCallBack(bool status);
        //2.delegate function
        public void setValue(string val)
        {
            radioButton1.Text=val;
        }
        public void setStatus(bool status)
        { 
        radioButton1.Checked = status;
        }

    }
  • 这个方法里,PLC读出的数据存储在自建的静态类里,要写入PLC变量的值也由自建的静态类给出,C#各个线程都可以访问该静态类,避免了各个线程和类之间传值的复杂和繁琐。

B. 用yaml交互

  • 安装YamlDoNet
  • 引用命名空间
using YamlDotNet.Serialization;
  • 新建文件夹,新建.yaml文件,建立yaml结构

  • 读取yaml文件方法

        //yaml_read
        public T Yaml_read<T>(string file_path)
        { 
        var deserializer = new DeserializerBuilder().Build();
            T my_yamlObject;
            using (var reader = new StreamReader(file_path))
            { 
            my_yamlObject=deserializer.Deserialize<T>(reader);
            }
            return my_yamlObject;
        }
  • 写入yaml文件方法
        //yaml_write
        public void Yaml_write(object obj, string file_path)
        { 
        var serializer = new SerializerBuilder().WithNamingConvention(CamelCaseNamingConvention.Instance).Build();
            var my_yaml = serializer.Serialize(obj);
            File.WriteAllText(file_path, my_yaml);
        }
  • 建立和yaml结构一致的class结构这是重点
    • [YamlMember(Alias)=""]来指定yaml文件中的结构名
    • [YamlIgnore]用于在序列化或者反序列化的时候忽略掉它
    • [YamlMember(Order = 1)]用于指定序列化的顺序
    • {get;set;}用于设置yaml结构的属性,公有属性。yaml文件的结构本身就相当于被保护起来的一个私有字段
    • yaml文件中不要用table键缩进,会报错,缩进一般使用空格,敲两个或者四个空格
    • yaml内容的结构名,和实际程序里面必须一一对应,一字不差
  • 建立yaml文件需要的程序结构样例
    //yaml结构
    public class yaml_data
    {
        public class yaml_test_data1
        {
            [YamlMember(Alias = "Byte_var")]
            public byte Byte_var { get; set; }
            [YamlMember(Alias = "Word_var")]
            public short Word_var { get; set; }
            [YamlMember(Alias = "Bool_var")]
            public bool Bool_var { get; set; }
        }
        public class yaml_test_data2
        {
            [YamlMember(Alias = "Int_var")]
            public int Int_var { get; set; }
            [YamlMember(Alias = "Char_var")]
            public char Char_var { get; set; }
        }

        // Class II
        public class yamal_class_collection
        {
            [YamlMember(Alias = "test_data1")]
            public yaml_test_data1 test_data1 { get; set; }

            [YamlMember(Alias = "test_data2")]
            public yaml_test_data2 test_data2 { get; set; }
        }

        //Class I
        [YamlMember(Alias="data_collection")]
        public yamal_class_collection data_collection { get; set; }
    }
  • 建立yaml文件内容,注意上下对应
data_collection:  #Class I 一级class名称,和程序对应
  test_data1:  #Class II 二级class名称,和程序对应
    Byte_var: 0x10  #各个字段
    Word_var: 32
    Bool_var: false
    
  test_data2:  #Class II 二级class名称,和程序对应
    Int_var: 99
    Char_var: 'a'
  • 找了个以前的截图,只为说明yaml文件的结构如何做,示意如图:

  • 引用yaml,在窗体load事件中读取yaml文件默认配置(读取到初始化的值)

yaml_data my_yaml_data = new yaml_data();
Config_yaml my_yaml= new Config_yaml();
my_yaml_data = my_yaml.Yaml_read<yaml_data>("C:\\Users\\testyaml.yaml");
posted @ 2024-05-08 17:20  不愿透露姓名的小村村  阅读(36)  评论(10编辑  收藏  举报