Copying values from one PLC to another

We have a system today where we are copying values from one PLC to another PLC (different brands). An example of this is a temperature from one PLC that is copied to other PLC’s where it is used for calculation.

What is the most efficient / best way to accomplish this using FactorySQL?
Say I want to copy a double from one PLC to 5 others?

To copy data from one device to multiple other devices, follow these steps (I’m assuming here that you can access all the devices using OPC and can browse them from within FactorySQL):

  1. Add a new Standard Group.
  2. Drag your input OPC item to the group item pane.
  3. Double-click on your input, set the Mode to ‘OPC to DB’ and tick the Read-Only box.
  4. Drag your output point(s) to the group item pane.
  5. Double-click on each output, set the Mode to ‘DB to OPC’ and tick the Read-Only box.
  6. For the first output, add an Action Item. Give it a name and make sure the Item Mode is set to ‘Expression’.
  7. Add your input point into the Command box by clicking in the box and pressing , select ‘Items…’, then choose it from the list.
  8. Tick the ‘Store result to DB field or OPC item’ box and enter the name of the first output into the box, again by clicking in the box and pressing , then choose it from the list. Click OK to save the Action Item.
  9. Repeat from step 6 for each output point.
  10. In the right hand pane, set the Update Rate as required - the database settings are not important as the database is not being used to store data.
  11. Set the trigger to ‘Only evaluate this group when a change has occurred’.
  12. Start the group.

You should now be able to set your input and see the outputs change to match it.

Having said all that, you will have to think carefully before making a PC an integral part of any control system, as their reliability cannot match that of PLCs. You may also want to consider implementing a communications heartbeat so that you know in each PLC when comms have failed.


Great, that works like a charm! Thanks!

To avoid setting wrong values when copying from one PLC to another, is it necessary to check the quality of the item that is read, before writing it to another PLS or is this handled automatically in FactorySQL?

I mean, if you do not use a trigger, but run the action-items every 10 seconds. Do I have to check if the data quality (in expression) on the OPC-item is good before writing it to the other PLS’es or does FactorySQL automatically have any logic that can stop this operation if the quality is not good?

I do not want to write to other PLC’s if the value I read is <> 192.

I carried out some testing using the KEPWare simulator. I set up the input value on device 1 and the 2 output values on device 2.

When I disabled device 1, an E_FAIL error was shown in the group item list against the input, but no errors were reported on the Status tab. The outputs froze at the last good value.

When I disabled device 2, E_FAIL errors were shown in the group item list against the outputs, but again no errors were reported on the Status tab.

As FactorySQL is not detecting the errors, you are going to have to do your own error detection. You will have to check for 2 problems: a failure between the input and FactorySQL; and a failure between FactorySQL and each output.

To check for a failure between the input and FactorySQL, I would create a new point in the group item list which was similar to the input, except that it reads the input OPC quality rather than its value. You could then change the action item to check the quality of the point - if it is in error, it would set the output to a known error value e.g.:If({Test1_quality}=192,{Test1},9999)Your PLC code would have to react appropriately to this value.

To check for a failure between FactorySQL and each output, you could use the built-in trigger handshake to provide a heartbeat. With each normal write, the handshake would set a point in the PLC which the PLC would reset before it used the output value. If communications failed, the PLC would time out looking for the handshake and would know that communications had failed.



If it’s ok to track it on the device level, you could just have one item in the group that represented the quality (some data point watching the quality property, or the comm status tag in kepware) and then just set the group’s trigger to “active=192, inactive!=192” (if using the quality- if using the status tag you’ll probably use the “trigger on zero” setting), so that the group will only run while value is good.

You could get a little more complicated by picking multiple points (or a point from each device) and then creating an action item that is set to “run always/ignore trigger settings”, and checks them all to get a 0 or 1 that can then be used as the group’s trigger.

BONUS TIP OF THE DAY! In an expression, when referring to a tag, you can add “.DataIntegrity” to the path in order to get the quality instead of the value. That way, you don’t have to add lots of extra items if you wanted to check multiple qualities. For example, you could do something like the following in your action item:

({Item1.DataIntegrity} & {Item2.DataIntegrity})=192

That’s the “tricky” way to do it in less code- the DataIntegrity by itself will show up as a string in the display, like “GOOD”. However, it’s really an integer. So, you can actually “bitwise and” them together, which will result in an integer result. The following would be equivalent:

ToInt({Item1.DataIntegrity} )=192 && ToInt({Item2.DataIntegrity})=192

Hope this helps,