Menu

Polling multiple data blocks at a time with Snap7

bouba
2014-07-28
2014-11-05
  • bouba

    bouba - 2014-07-28

    Hello everybody,

    I use snap7 to poll 4 data blocks of my Siemens S7 1200 PLC. It's works(with help of David) at the beginning. I declare 4 S7 Client and I store buffer into 4 arrays of bytes. After I parse buffer and store each variable. I use Thread to do this job with 20ms of delay.
    However, one of S7 Client disconnects after few minutes and I don't have true values.

    I want to know why one of client disconnects after approximately 30 minutes.

    Thanks
    Best regards
    B.M

     
  • bouba

    bouba - 2014-08-01

    OK.How can I use snap7 for pooling 4 DB at same moment? Are there function or methods for do this?
    Thanks

     
  • Davide Nardella

    Davide Nardella - 2014-08-01

    How much is the total size that you need to transfer ?

     
  • bouba

    bouba - 2014-08-01

    for DB1 ---> 4 bytes
    DB2 ---> 4 bytes
    DB3 ----> 140 bytes
    DB4 -----> 40 bytes

    At total 188 bytes

     
  • Davide Nardella

    Davide Nardella - 2014-08-01

    In this case you can use Cli_ReadMultiVars() that can transfer up to 20 vars in the same telegram.
    The drawback (it's a S7 protocol limit) is that the whole size must fit in a single PDU including the header.

     
  • bouba

    bouba - 2014-08-10

    OK
    What do you mean about 20 vars (how many bytes?).What is the max PDU size for Siemens S71200 CPU 1214 PLC.Therefore i must use ReadMultiVars if i want to poll 4 DB simultaneously?

    THX

     
  • Davide Nardella

    Davide Nardella - 2014-08-11

    A var is a Tag, i.e. a block of byte/word/dword, the same that you transfer via Cli_ReadArea() function.

    The maximum payload is:

    ReadMultiVars:
    MaxPayloadSize=PDULength-(14+4*NumItems)

    WriteMultiVars:
    MaxPayloadSize=PDULength-(12+16*NumItems)

    Where PDULength is the size negotiated during the connection, you can obtain it via Cli_GetPduLength() (ref man pag.163) and NumItems is the number of blocks read/wrote.

    You can read up to 20 different DB at the same time if the total size is less or equal to the above value.

     
  • bouba

    bouba - 2014-08-29

    hello

    I use ReadMultiVars function like this in C#:

                byte[] DataDB305= new byte[4];
                byte[] DataDB306=new byte[4];
                byte[] DataDB300=new byte[40];
                byte[] DataDB405=new byte[140];
    
                S7Client.S7DataItem[] items = new S7Client.S7DataItem[3];
                items[0].Area = S7Client.S7AreaDB;
                items[0].WordLen = S7Client.S7WLByte;
                items[0].DBNumber = 305;
                items[0].Start = 0;
                items[0].Amount = 4;
                items[0].pData = &DataDB305 ;      //error
    

    I have an error with items[0].pData, I pass address but I have an error

    THX

     
  • bouba

    bouba - 2014-08-29

    I use GCHandle for passing byte array address but I have another problem with myclient.ReadMultiVars(items, 4).It only take reference as argument.

                items[0].Area = S7Client.S7AreaDB;
                items[0].WordLen = S7Client.S7WLByte;
                items[0].DBNumber = 305;
                items[0].Start = 0;
                items[0].Amount = 4;
                GCHandle myGcHandle1 = GCHandle.Alloc(DataDB305, GCHandleType.Pinned);
                IntPtr DataDB305Ptr = myGcHandle1.AddrOfPinnedObject(); 
                items[0].pData = DataDB305Ptr;
                myGcHandle1.Free();
                myclient.ReadMultiVars(items, 4);         //error
    
     
  • LanceL

    LanceL - 2014-09-26

    I had to modify ReadMultiVars in snap7.net.cs to to get it to work.
    Instead of taking a ref to S7DataItem it takes an IntPtr to the first element of an array (that has been marshalled into unmanaged memory).

    [DllImport(S7Consts.Snap7LibName)]
    protected static extern int Cli_ReadMultiVars(IntPtr Client, IntPtr Item, int ItemsCount);
    public int ReadMultiVars(IntPtr Item, int ItemsCount)
    {
        return Cli_ReadMultiVars(Client, Item, ItemsCount);
    }
    

    I also added this method to marshal the array back and forth.

    public int ReadMultiVars(ref S7DataItem[] Items)
    {
        int iCount = Items.Length;
        int iSize = Marshal.SizeOf(typeof(Snap7.S7Client.S7DataItem));
    
        IntPtr pItems = Marshal.AllocHGlobal(iSize * iCount);
    
        for (int i = 0; i < iCount; i++)
        {
            var pItem_i = new IntPtr(pItems.ToInt64() + (i * iSize));
            Marshal.StructureToPtr(Items[i], pItem_i, false);
        }
    
        var result = this.ReadMultiVars(pItems, iCount);
    
        for (int i = 0; i < iCount; i++)
        {
            var pItem_i = new IntPtr(pItems.ToInt64() + (i * iSize));
            Items[i] = (S7DataItem)(Marshal.PtrToStructure(pItems, typeof(S7DataItem)));
    
        }
    
        Marshal.FreeHGlobal(pItems);
    
        return result;
    }
    

    This is the first time I have ever done any work with unmanaged code so please review these changes for yourself before using them.

    With this code I can read one int and two reals at a rate of 190 to 200 times per second from S7-319 CPU. This is reading from a Data Block.

     
  • Davide Nardella

    Davide Nardella - 2014-09-30

    Hi LanceL,
    thanks for the contribute ;)
    please, could you show a little example of calling this ?
    Dave

     
  • compactview

    compactview - 2014-10-31

    1) Modify ReadMultiVars and WriteMultiVars in snap7.net.cs:

        [DllImport(S7Consts.Snap7LibName)]
        protected static extern int Cli_ReadMultiVars(IntPtr Client, S7DataItem[] Items, int ItemsCount);
        public int ReadMultiVars(S7DataItem[] Items, int ItemsCount)
        {
            return Cli_ReadMultiVars(Client, Items, ItemsCount);
        }
    
        [DllImport(S7Consts.Snap7LibName)]
        protected static extern int Cli_WriteMultiVars(IntPtr Client, S7DataItem[] Items, int ItemsCount);
        public int WriteMultiVars(S7DataItem[] Items, int ItemsCount)
        {
            return Cli_WriteMultiVars(Client, Items, ItemsCount);
        }
    

    2) Modify S7DataItem in snap7.net.cs:

        [StructLayout(LayoutKind.Sequential, Pack = 1)]
        public struct S7DataItem
        {
            public Int32 Area;
            public Int32 WordLen;
            public Int32 Result;
            public Int32 DBNumber;
            public Int32 Start;
            public Int32 Amount;
            public IntPtr pData;
    
            public void Set<T>(Int32 Area, Int32 WordLen, Int32 DBNumber, Int32 Start, Int32 Amount, ref T[] Buffer)
            {
                Set(Area, WordLen, DBNumber, Start, Amount, ref Buffer, 0);
            }
    
            public void Set<T>(Int32 Area, Int32 WordLen, Int32 DBNumber, Int32 Start, Int32 Amount, ref T[] Buffer, Int32 Offset)
            {
                this.Area = Area;
                this.WordLen = WordLen;
                this.Result = 0;
                this.DBNumber = DBNumber;
                this.Start = Start;
                this.Amount = Amount;
                GCHandle handle = GCHandle.Alloc(Buffer, GCHandleType.Pinned);
                this.pData = handle.AddrOfPinnedObject() + Offset * Marshal.SizeOf(typeof(T));
                handle.Free();
            }
        }
    

    3) Calling example:

            using Snap7;
    
            S7Client client = new S7Client();
            int error = client.ConnectTo("192.168.0.10", 0, 2);
            if (client.Connected())
            {
                byte[] E = new byte[200];
                S7Client.S7DataItem[] items = new S7Client.S7DataItem[2];
                items[0].Set(S7Client.S7AreaPE, S7Client.S7WLByte, 0, 0, 1, ref E);
                items[1].Set(S7Client.S7AreaPE, S7Client.S7WLByte, 0, 20, 1, ref E, 20);
    
                client.ReadMultiVars(items, 2);
                client.Disconnect();
    
                MessageBox.Show("EB0: " + E[0].ToString() + ", EB20: " + E[20].ToString());
            }
    
     

    Last edit: compactview 2014-11-02
  • Davide Nardella

    Davide Nardella - 2014-11-05

    Thank you very much ;)
    I will update the library asap.

     

Log in to post a comment.