Menu

ReadMultiVars 'function refused by CPU' error when requesting >= 20 items

2014-11-05
2015-01-31
  • Gareth Webber

    Gareth Webber - 2014-11-05

    Hi,

    I am using an unmodified version of Snap7 1.2.1 and writing my code in C#. My application was working perfectly reading up to 16 different items from the PLC. Values returned matched those seen in my VAT tables.

    I then decided to expand from 16 different items up to 20, and get the following error text returned:
    "CLI : function refused by CPU (Unknown error)"

    Here is the important part of code for creating the PDU:

    dataItems[item].Area = S7Client.S7AreaDB;
    dataItems[item].WordLen = S7Client.S7WLByte;
    dataItems[item].Amount = 1;
    dataItems[item].DBNumber = tag.DB;
    dataItems[item].Start = tag.Byte;
    

    So, when the code fails I am requesting 20 separate (yet identical) bytes from the PLC. This results in a PDU size much smaller than the negotiated size of 240 bytes and shouldn't be causing an issue. Reducing the item count from 20 down to 19 fixes the problem and the code returns the expected values reliably again. The same problem exists for all data types requested.

    //EDIT: Just to clarify, this error only occurs when 20 items are requested. If I request >20 items it fails with an error saying the maximum number of items is 20. Less than 20 items works perfectly.

    Thank you for your help in getting to the bottom of this error. So far I am very impressed with the library.

    Many thanks,
    Gareth

     

    Last edit: Gareth Webber 2014-11-05
  • Davide Nardella

    Davide Nardella - 2014-11-05

    Hi,
    It's a CPU error, I will check.
    It's not a PDU problem since the max payload is:
    PDULength-(14+4*NumItems), for NumItems=20 it is 146.

    Regards

     
  • Davide Nardella

    Davide Nardella - 2014-11-05

    My formula is wrong :(

    The header/params size for MultiRead Function is 12+(12*NumItems).
    So you definitely have a PDU problem if you negotiated 240 bytes.

    The MultiWrite calc is a nightmare :( because every variable except for the last must be even, otherwise a padding byte must be inserted (this is done automatically by Snap7).

    In the next release I will insert a check on the final telegram size in addition to the NumItems Limit.

     
  • Nicolas Schneider

    Using the formula would give a maximum payload of 218 bytes for one item and -12 bytes for 20 items with a 240 bytes PDU. Does this mean, that we can not transfer 20 Variables at once with a 240 bytes PDU?

    While we are at it: What is the maximum payload that can be received with one ReadArea call for one PDU, i.e. what is the exact header size of the returned packet from the S7?
    My tests show it is 18 bytes (resulting in 222 bytes that can be received with a 240 bytes PDU). Is this true for all S7 CPUs?

     

    Last edit: Nicolas Schneider 2015-01-30
  • Davide Nardella

    Davide Nardella - 2015-01-30

    The key concepts are :
    1) Each data transfer must fit in a PDU (Headers+Data)
    2) The PDU size is negotieted during the connection and goes from 240 up to 480 bytes (dependings on the CPU model).
    3) The CPU itself doesn't handle multiple PDU data exchange except for Up/Download, Directory and SZL functions.

    MultiRead/Write var are S7 native functions that allow you to transfer up to 20 vars but their total size (headers+data) must fit in a single PDU (see pt.1).

    Using Read/WriteArea Snap7 functions there is no PDU limit since the library automatically splits the job in subsequent telegrams, the only limit is 64Kb of a S7400 DB.
    This is performed via multiple read/write in subsequent chunks and can be done obviously only for "single var" data exchange.

    So if you want to read severel vars using several requests (ReadArea or DBRead and so on.) you dont need to worry about their dimension, you need only a buffer big enough.

    Regards
    Davide

     

    Last edit: Davide Nardella 2015-01-30
  • Nicolas Schneider

    I am aware of the automatic split feature provided by Snap7 - which is great by the way –, but I need to know how much data can be exchanged using a single PDU, so that there is no splitting involved.
    After looking at the source code, I think a response header of a single PDU exchange with the CPU when reading a single variable is 18 bytes long. Can you confirm this?

    The reason for that is that I am writing an application where the user can specify which variables should be retrieved from the CPU.

    It would be great if I could read the data in the most efficient way. That is, if it fits in one PDU, I just get all of it with a single ReadArea call.
    Things get interesting, if the variables are not next to each other, but spread across the MB or DB. Now, I would have to calculate if it is better to just issue one big ReadArea call or split it manually in a few smaller ones.
    A similar situation arises, if there are multiple variables in the MB and others in a DB.
    It might be better to issue multiple ReadArea calls instead of a few ReadMultiVars, but that is not always the case.

    Example:
    There are 10 variables at the beginning of the MB, 10 at Offset 1kb and 20 words at Offset 3kb.
    Obviously, using a single ReadArea call would result in 3kb + 20*words data, which would result in quite a few requests to the CPU.
    Using ReadMultiVars is not possible, because there are too many variables involved.
    The best strategy would be to issue three ReadArea calls, one at Offset 0, one at Offset 1kb, and one at Offset 3kb.
    Maybe it would also work to use 3 ReadMultiVars call in this example and the performance would be the same.

    Additionally, it would be nice to have a helper function in the wrappers that would determine, if a given (PS7DataItem Item, int ItemsCount) pair would fit into a single PDU.
    This would allow me to write an algorithm that chooses the best (or at least a good one) strategy to query the data from the CPU.

     
  • Davide Nardella

    Davide Nardella - 2015-01-31

    Hi Nicholas,
    currently there's not an official function that says you if you are off the PDU.
    I noted your request ;)

    in the meantime, if you call MultiRead/Write and the size is over, an error is reported by Snap7 without involving PLC communication, i.e. it's immediate just like a "Test" function.

    Stay tuned

     

Log in to post a comment.