Trigger a Data Read

Having established a link between your tag and a driver tag (previous topic), your Refresh module must issue an AddRead request to the driver to start receiving data. If any of the connection parameters change, this request should be cleared and a fresh AddRead issued.

After the AddRead has been issued to the driver instance, it is then up to the driver code to poll the PLC at the ScanInterval rate and send new values back to the specified destination. Note: The Refresh module is not used to handle new values from the driver. For that, you will need a NewData module, as covered in the following topic.

The following example (taken from the Analog Input tag's Refresh module) shows how the AddRead function should be called. The tag's RawValue parameter is used as the destination for the value read from the driver. You may then write code that scales this before using the result as the tag's value or, if the manual data flag is set, ignores the raw data value in favor of the manual data value. Note that this example is for analog data - digital values are read using the same technique, but would not be scaled.

Refresh [
  If 1;
  [

    {***** Scan Interval *****}
    ScanInterval = PickValid(Cast(ScanInterval, 3), 
                             GetDefaultValue(&ScanInterval));

    {***** The connection parameters were set or changed *****}
    IfThen (PickValid(Parm[#IODevice]      != DeviceTag,    1) ||
            PickValid(Parm[#ScanInterval]  != ScanInterval, 1) ||
            PickValid(Parm[#Address], "")  != PickValid(Address, ""),

      {***** Remove the previous read request (this will do nothing
             if the parameters are invalid) *****}
      Scope(Root, Parm[#IODevice])\Driver\DelRead(Parm[#Address], 
                                       &RawValue, Parm[#ScanInterval]);

      RawValue = Invalid { old value no longer valid };

      {***** Add a new read request *****}
      Scope(Root, DeviceTag)\Driver\AddRead(Address  
                        { Address in the PLC for the data },
                                              1          
                        { Number of data elements to get         },
                                              &RawValue
                        { Destination pointer for data read      },
                                              ScanInterval
                        { Scan Interval                          });
    );
    {******************************************************************}
    { ManualValue                                                      }
    {******************************************************************}
    ManualValue = Cast(ManualValue, 3 { Float });
    IfElse (Valid(ManualValue),
      Value = ManualValue;
    { Else } IfThen (!ExternalValue,
      Value = IsText ? RawValue : Scale(RawValue, UnscaledMin, 
                                        UnscaledMax, ScaledMin, ScaledMax);
    ));