Expressions on all properties of base tags

Hi!

I just improved the support for expressions in the properties of PascalSCADA tags. At first moment, this feature was only available for the TPLCBlockElement.Index and TPLCStructItem.Index tags/properties. From today, is possible to use expressions on the following tag classes:

  • TPLCTagNumber
  • TPLCStruct
  • TPLCBlock
  • TPLCString

On these tags, is possible use and include in the expression the following properties:

  • PLCRack
  • PLCSlot
  • PLCStation
  • MemFile_DB
  • MemAddress
  • MemSubElement
  • MemReadFunction
  • MemWriteFunction
  • Tag (you can only use this property on expressions in the properties mentioned above)

Below is a video that helps you understand the new feature:

Suggestions for improvements are always welcome!

30 thoughts on “Expressions on all properties of base tags

    • Fabio Luis Girardi Post authorReply

      Not yet. I started the implementation some time ago, but I stopped to put the efforts on others parts of the project.

    • Fabio Luis Girardi Post authorReply

      If you assign a scale processor in TPLCTagNumber.ScaleProcessor, the property TPLCTagNumber.Value will show the scaled value (engineering value) instead TPLCTagNumber.ValueRaw still showing the original value, read from your device.

    • Fabio Luis Girardi Post authorReply

      Insert a TLinearScaleProcessor on your application

      Configure it

      On your tags that will use the same scale, set the property ScalProcessor of your tags to the TLinearScaleProcessor created on the first step

      Note that a single Scale processor component (TLinearScaleProcessor, TUserScale) can be shared across multiples tags.

  1. Slamet Reply

    Hi Fabio,

    What are different for any write method on:
    TPLCTagnumber, TPLCBlock, TPLCBloctElement since of all them use same parameters….
    procedure Write(Values:TArrayOfDouble; Count, Offset:Cardinal); override;
    Should we write from TPLCBlock or from Element ?

    Thank you

  2. Fabio Luis Girardi Post authorReply

    Depends of what you want to do. But in summary, all synchronous writes will be redirected to the

    procedure Write(Values:TArrayOfDouble; Count, Offset:Cardinal); override;

    And the parameters will depend of your tag class and size (and offset or index, if you are doing that from a TPLCStructElement or a TPLCBlockElement).

    This way allows you to map only the first element of a big block using a TPLCTagNumber, to use it to write a big data block using the procedure write mentioned above.

    But as I wrote, depends of what you want to do…

    • Slamet Reply

      Hi Fabio,

      Thank you for your explanation.
      From your explanation, we able to write block of memories address just using TPLCTagNumber.Write, but also using TPLCBlock.Write with same parameters.

      For Offset parameter, please kindly explain clearly since we have already TArrayOfDouble and count.

      Thank you

  3. Slamet Reply

    Hi Fabio,

    We have block of memories in Arduino (15 location, 4 byte: addr from 0 – 14), Slave ID of Arduino is 1.
    if we want write 1 location addr 2 only, should we configure:
    PLCStation : 1
    MemAddress : 2
    Size : 1
    TPLCTagNumber.Write(Value,1,offset);
    Is it correct except “offset – still not clear” ?

    Thank you

    • Slamet Reply

      Hi Fabio,

      We continue with block of memories in Arduino (15 location, 4 byte: addr from 0 – 14), Slave ID of Arduino is 1.
      if we want write 3 location addr from 10 – 12, should we configure:
      PLCStation : 1
      MemAddress : 10
      Size : 3
      We should use TPLCBlock.Write(Value-array,3,offset), instead of TPLCTagNumber…….
      Is it correct except “offset – still not clear” ?

      For moment time we have able to read and write from Autoread/AutoWrite set to true.

      Thank you

  4. Fabio Luis Girardi Post authorReply

    Hi!

    The offset depends of:

    ** Protocol type
    ** Tag Class
    ** Tag.TagType property

    Can you explain more about your configuration?

    • Slamet Reply

      Hi Fabio,

      Our Configuration:
      SerialPortDriverMB: TSerialPortDriver;
      BaudRate : br9600
      COMPort: COM5
      DataBits:db8
      Noparity
      Stopbits:sb2

      ModBusRTUDriverArdu: TModBusRTUDriver;
      CommunicationPort:SerialPortDriverMB

      ArduRlBlockOpr: TPLCBlock;
      ProtocolDriver:ModBusRTUDriverArdu
      PLCStation:1 (same as Arduino)
      MemAddress:2
      Size:2
      MemReadFuntion:3
      MemWriteFuntion:16

      In the Arduino side:
      Slave Addr:1
      Block of memories in Arduino (15 location, 4 byte: addr from 0 – 14)

      And we used following code that doesn’t work:

      procedure TfrmDiag.BtnSendModbusClick(Sender: TObject);
      var
      val: TArrayOfDouble;
      begin
      SetLength(val, 2);
      val[1] := dataToArdu.STATE;
      val[2] := dataToArdu.RESET;
      bankTag.ArduRlBlockOpr.Write(val,2,0);
      BtnSendModbus.Enabled:=false;
      end;

      But working as well if we configure AutoRead/AutoWrite to true

      Thank you

  5. Slamet Reply

    Hi Fabio,

    We continue with our own experiment with “Write” method.
    The following code look doesn’t work.

    procedure TfrmDiag.BtnSendModbusClick(Sender: TObject);
    var
    val: TArrayOfDouble;
    begin
    SetLength(val, 2);
    val[1] := dataToArdu.STATE;
    val[2] := dataToArdu.RESET;
    bankTag.ArduRlBlockOpr.Write(val,2,0);
    BtnSendModbus.Enabled:=false;
    end;

    Any Idea for it ?

    Thank you

  6. Fabio Luis Girardi Post authorReply

    Thanks by your feedback.

    Now that I know your config, is more easy to you explain how offset works.

    On Modbus (RTU/TCP) the TagType pttDefault have 16 bits of length on functions 3 and 16, and no type conversion are made when receiving or sending values.

    So, if the MemAddress of your tag (with TagType=pttDefault or tagType=pttSmallInt or TagType=pttWord, using modbus) is equal to 0, the offset=2 will simple start the write on modbus register 2 instead of 0, with Count registers of lenght.

    But assuming that you are using 32 bits of length tags (TagType=pttLongInt, TagType=pttDWord or TagType=pttFloat) the offset will calculated:

    RealMemAddress:=(SizeOfTag/SizeOfTargetArea)*Offset;

    Writing on modbus holding registers (MemWriteFunction=16):

    pttLongInt size = 32 bits;
    MemWriteFunction=16 on Modbus Size: 16 bits
    Offset = 2
    RealMemAddress := (32 / 16) * 2;

    So, the write of one LongInt tag will start at holding register 4;

    The size of datablock that will be written is:
    RealSize :=(SizeOfTag/SizeOfTargetArea)*Count;

    Writing the same example above, with Count=5, will result:
    RealSize :=(32/16)*5;

    So doing:
    MyTagLongInt.Write(ArrayWith5LongIntValues,5,2);

    Will write 10 words, at the holding register MyTagLongInt.MemAddress + 4.

    To help you, enable the log of the data exchanged between PascalSCADA and your Arduino by doing:

    SerialPortDriverMB.LogFile := ‘c:\some path\some log file name.txt’
    SerialPortDriverMB.LogIOActions := true;

    Ahhh, Do you have activated your SerialPort? To activate it do?

    SerialPortDriverMB.Active := true;

    on your Form.OnFormCreate event

  7. Fabio Luis Girardi Post authorReply

    Another thing:

    You should use a TPLCBlock instead of TPLCTagNumber, because the Write of TPLCTagNumber, the count and offset are hardcoded to 1 and 0, respectively.

  8. Slamet Reply

    Hi Fabio,

    How do we resolve “Error reading SerialPortDriver” when application (PasccalScada) if Modbus-RTU devices are not connected to Host (Master) ?

    Thank You.

    • Fabio Luis Girardi Post authorReply

      Is simple. First of all, leave the property SerialPort.COMPort empty at design time. On your Form Create event put the following code:

      try
      SerialPort.COMPort := ‘COM5’;
      SerialPort.Active := true;
      except
      //show some message telling about the missing serial port…
      end;

  9. Matthias Reply

    Hi Fabio,
    How can I write a 32bit analog register.
    I know I must write two 16bit. But how can I config this in a tag?
    Example please.

    Id 1 address 2 register 2

    Thanks

    • Fabio Luis Girardi Post authorReply

      Hi!

      Assuming that the area being read is 16 bits sized, set the property:

      TagType = pttLongInt (for signed values)
      TagType = pttDWord/pttLongWord (dont remember the property value for unsigned values)

      and use

      SwapBytes, SwapWords and SwapQWords to change de registers positions. You can set it in runtime to see what’s best fits to your needs.

  10. Matthias Reply

    Hi, thanks for answer. On modbus slave I have 32bit analog holding reg.
    What swap type is the right?
    Tagtyp pttlongint?

    • Fabio Luis Girardi Post authorReply

      Hi!

      Is your register?

      a) a 32 bit signed int
      b) a 32 bit unsigned int
      c) a 32 bit floating-point

      Depending on your response, Should you set the following value in TagType:

      a) pttLongInt
      b) pttDword
      c) pttFloat

      With the correct TagType, you should set the properties SwapBytes, SwapWords to match the Endian of your controller. You will have to make trial and error to find out the correct setup of SwapBytes/SwapWords properties. I can’t help you in this with more accurate information. The good is that, with the correct MemAddress and TagType set, you have only four combinations to test:

      +———–+———–+
      | SwapBytes | SwapWords |
      +———–+———–+
      | false | false |
      +———–+———–+
      | true | false |
      +———–+———–+
      | false | true |
      +———–+———–+
      | true | true |
      +———–+———–+

      One of these combinations should let you able to read the correct value from your controller.

      The best regards,

      Fabio

  11. af0815 Reply

    Hi, Fabio !

    I work with PascalSCADA 0.7.5.0 from OPM.

    Access with the TTCP_UDPPort, TISOTCPDriver and TPLCTagNumber works for Flags/MK (german: ‘Merker’) works without a problem. (Memreadfunc, Memwritefunc = 3, MemAdress = FlagAdress, PLCRack = 0, PLCSlot = 2, TagType = pttWord).

    If i want to access DB 200:DBW2 it doesnt work and return and io??? Error ( I have no PLC actual for tests)
    (Memreadfunc, Memwritefunc = 4, MemAdress = 2,Mem_FileDB=200, PLCRack = 0, PLCSlot = 2, TagType = pttWord).

    With the Snap7 demoserver the access works, but not on a real S7-300 device. Have i forgotten/misconfigured something ? Or is PLCTagNumber not ok for DBs ?

    BTW: I have no access to such a device, so i cant test directly.

    • Fabio Luis Girardi Post authorReply

      Hi Andreas!

      Your settings are right. I’ll hint you about symbolic addressing, but isn’t your case, since you are using s7-300. What’s the lastasyncreadstatus?

  12. af0815 Reply

    Hi Fabio,
    it looks we have found the issue. We had a short timeslot for tests.

    1st) We have a missunderstanding between PLC-programmer and us 🙂 The infos about DB-Nr and Byte-Nr were exchanged. So it was an access to an non existing DB.
    2nd) The data in the DB are the last and we have accessed one byte to much. So it was an illegal access.

    Now we can work with it, with DBs too. THX for the help.

    Your PascalSCADA is a brillant and excellent work !!!

Leave a Reply

Your email address will not be published. Required fields are marked *