在虚拟机中使用NetToPLCSim和PLC相连.

1,虚拟机...系统Win10...里面安装了VS.

2,本机...系统Win10...里面安装了博图15.

3,转换软件:NetToPLCSIM.

4,本机和虚拟机连接同一个路由器.注意:

image

5,设置虚拟机为桥接模式,并且选择连接了路由器的网卡.

6,网卡设置自动获取IP地址,并且禁止,启用,让网卡获取IP地址.

本机IP:image

虚拟机IP:image

正常情况,两台机器能够互相ping 成功!,则基本准备,网络配置完毕.否则,检查防火墙.我没遇到,就没弄.

然后打开博图,必须要进行get/put打勾!

  1,设置PLC ip image

2,GET/PUT 打勾

                  image

3,模拟的时候,先点击模拟,但是不要下载PLC.


4,打开Nettoplcsim软件:(其中有 stop server start server 默认即可),注意,一定要先打开这个软件.

image

5,打开添加对接画面:点击PLCSIM IP.注意,如果先模拟再添加就不会显示.

image没有PLC

6,打开PLC模拟器,并下载PLC 点击 PLCSIM IP:这个很关键,必须它自己跳出来的.选择PLC.

image

7,选择 NET IP ADDR:

image

8,ok注意 rack和slot选择

image

image

9,在虚拟机的VS里面测试通讯

 internal static void TestS7()
        {


            Plc plc = new Plc(CpuType.S71200, "192.168.3.62", 0, 1);
            try
            {
                log("begin open plc");
                plc.Open();//一个PLC异步函数,注意,异步函数的异常只能通过
                log("plc is open!");
            }
            catch(Exception e)
            {
                log(e.Message);
            }
        }

结果:

image

10,尝试读取写入byte[]数组:

  RecipePLC 数据类型具有:(配方)

    一个字符串: string[20] 占用了22个字节.Index0是其大小,应该是22,index1 是实际字符长度.应该是0.现在

   一个step数组:step是一个plc数据类型. 其为30个step元素.

每个step含有:

image

OK,我们先来完成如何读取写入这个结构:

10.1首先在vs中架构一个PLCSTRING类,因为 string这个类不好投射.


 public class PlcString:IPlcParse
    {
        private readonly byte[] bytes;
        public PlcString() : this(256) { }
        public PlcString(int len )
        {
            bytes = new byte[len];
            bytes[0] = len <= 0xfe ? (byte)len : (byte)0xfe;



        }
        public void SetString(string str)
        {
            int len = bytes.Length;
            if (str != string.Empty)
            {
                byte[] str_bytes = ASCIIEncoding.ASCII.GetBytes(str);
                bytes[1] = (byte)str_bytes.Length;
                str_bytes.CopyTo(bytes, 2);
            }
            else
            {
                bytes[1] = 0;

            }
        }
        public string GetString()
        {
            if (bytes[1] != 0)
            {
                byte[] strs = new byte[(int)bytes[1]];
                Buffer.BlockCopy(bytes, 2, strs, 0, (int)bytes[1]);
                return ASCIIEncoding.ASCII.GetString(strs);
            }
            else
            {
                return string.Empty;
            }


        }

        public static explicit operator String(PlcString obj)
        {
            return obj.GetString();
        }

        public  object FromBytes(byte[] bytes, ref double numBytes)
        {
            numBytes = Math.Ceiling(numBytes);
            if ((numBytes / 2 - Math.Floor(numBytes / 2.0)) > 0)
                numBytes++;
            Buffer.BlockCopy(bytes, (int)numBytes, this.bytes, 0, this.bytes.Length);
            numBytes += this.bytes.Length;
            return this;
        }

        public int GetSize()
        {
            return bytes.Length;
        }

        public void ToBytes(byte[] bytes, ref double numBytes)
        {
            numBytes = Math.Ceiling(numBytes);
            if ((numBytes / 2 - Math.Floor(numBytes / 2.0)) > 0)
                numBytes++;
            Buffer.BlockCopy(this.bytes, 0,bytes, (int)numBytes, this.bytes.Length);
            numBytes += this.bytes.Length;
        }
        public void Display()
        {
            foreach (var x in bytes)
                Console.Write(" {0:X2}", x);
            Console.WriteLine();
        }
    }

这个类实现了如下的接口:

 public interface IPlcParse
    {
        void ToBytes(byte[] bytes, ref double numBytes);
        object FromBytes(byte[] bytes, ref double numBytes);
        int GetSize();
    }

https://gitee.com/mao_qin_bin/s7netplus

算了,太多了,大家到这个地方下载吧. 注意版权.是我的!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

在原有的S7的基础上更改的实现.(git下来之后,我们再开始下一步)

下面我们来实现VS中的step步:

public class Recipe_Step
    {
        public short element1;
        public short element2;
        public short element3;
        public short element4;
        public short element5;
        public short element6;
        public double element7;
        public double element8;
        public double element9;
        public double element10;
        public double element11;
        public double element12;
        public double element13;
        public bool element14;
        public bool element15;
        public short element16;
    }

image

1,int--投射成short

2,real-投射成double

3,注意大小是64个字节.我们来计算下我们的类的大小.

 public static void demo5()
        {

            PlcClassHelper.DisplayObject(new Recipe_Step());


        }

结果:

 Recipe_Step : ConsoleApp1.PlcClass.Recipe_Step   Size:44

Class of Recipe_Step
   Int16 : 0   Size:2
   Int16 : 0   Size:2
   Int16 : 0   Size:2
   Int16 : 0   Size:2
   Int16 : 0   Size:2
   Int16 : 0   Size:2
   Double : 0   Size:4
   Double : 0   Size:4
   Double : 0   Size:4
   Double : 0   Size:4
   Double : 0   Size:4
   Double : 0   Size:4
   Double : 0   Size:4
   Boolean : False   Size:2
   Boolean : False   Size:2
   Int16 : 0   Size:2

OK.

然后再测试下Recipe1:

 public class Recipe
    {
        public static Recipe StaticInstance=new Recipe();
        public PlcString Recipe_Name = new PlcString(20, "");
        public Recipe_Step[] Recipe_Steps = new Recipe_Step[30];
        private Recipe()
        {
            for(var i = 0; i < Recipe_Steps.Length; i++)
            {
                Recipe_Steps[i] = new Recipe_Step();
            }
        }
    }

这是PLC数据块(非优化)编译好的

image

这是我测试的:

Recipe : ConsoleApp1.PlcClass.Recipe   Size:1342

Class of Recipe
   PlcString :  String =   Bytes = : 14  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0    Size:22

Array of ConsoleApp1.PlcClass.Recipe_Step[] :
     Recipe_Step : ConsoleApp1.PlcClass.Recipe_Step   Size:44

Class of Recipe_Step
       Int16 : 0   Size:2
       Int16 : 0   Size:2
       Int16 : 0   Size:2
       Int16 : 0   Size:2
       Int16 : 0   Size:2
       Int16 : 0   Size:2
       Double : 0   Size:4
       Double : 0   Size:4
       Double : 0   Size:4
       Double : 0   Size:4
       Double : 0   Size:4
       Double : 0   Size:4
       Double : 0   Size:4
       Boolean : False   Size:2
       Boolean : False   Size:2
       Int16 : 0   Size:2
     Recipe_Step : ConsoleApp1.PlcClass.Recipe_Step   Size:44

完全正确.下面设定下一些数据并且从PLC的读取:

10.5 设置PLC数据

image

image

10.6 从PLC读取数据:

image

完全一致:

10.7 将数据写入PLC:

 public static void demo6()
        {

            Recipe curRecipe = Recipe.StaticInstance;//引用配方
            Recipe.Initial();
            short t = 0;
            foreach(var step in curRecipe.Recipe_Steps)
            {
                step.element1 = t++;
                step.element16 = t++;


            }






            Plc plc = new Plc(CpuType.S71200, "192.168.3.62", 0, 1);
            try
            {
                plc.Open();
                plc.WriteBytes(DataType.DataBlock, 1, 0, PlcClass.ToBytes(curRecipe));
                PlcClassHelper.DisplayObject(curRecipe);
            }
            catch (PlcException e)
            {
                Console.WriteLine("Exception'Message is {0},Exception's Errcode is {1}", e.Message, e.ErrorCode.ToString());
            }
            finally
            {
                plc.Close();
            }

        }

上面的Initial是将staticInstance实列给初始化了.

查看结果: PLC

image

查看结果:VS

image

posted @ 2020-02-22 16:50  frogkiller  阅读(7401)  评论(0编辑  收藏  举报