Incorrect Tag Value but showing Good Quality

So we have a client with a Siemens S7-1500 and Ignition 8.1. There is a heartbeat bit that the PLC sets to 1 and Ignition resets to 0 (via a Tag Change Script). The issue they ran into today was the heartbeat in the PLC timed out because the value in the PLC was 1, but ignition wasn’t resetting the value to 0 because the value in Ignition was already 0. Now, when we checked the tag quality, it was listed as ‘Good’ with a time stamp of ~10:25 PM last night (this was at about noon today). Checking the logs from yesterday there are several clock drift entries for both positive and negative time of about an hour, so I think that was the initial cause of the lapse in communication, and the entry “Bad(“Bad_NotConnected: The variable should receive its value from another variable.”)” was logged for the heartbeat.

However once communication was restored (seemed to rectify itself as no one was around at the time) and the connection was at least partially working, the heartbeat still didn’t have the correct value in it even with ‘Good’ quality. We had to disable the Device connection, then re-enable it to get the heartbeat working again. The tag is in the default tag group with a 1000 ms poll rate. Why didn’t the value update (as other tags seemed to be correct) and why didn’t the quality go to ‘Bad’ when the value didn’t update?

Writing to a tag from two directions is inherently racy. Writing is independent of the read subscription so it will always be possible for this scenario to happen. A more reliable heartbeat would be a toggle of the bit on the PLC side, and an echo from Ignition to a separate bit in the PLC.


I recently worked with support for a very similar situation. As Phil describes, it’s a race condition issue, but frankly an easy-to-trigger one that can have rather large consequences. Below is a response from support that gives some workarounds.

I spoke with my colleague on the development team regarding your concerns. Fundamentally speaking, this issue is a race condition and isn’t a bug in how we expect the OPC Server to behave.

  1. You write true to the tag in Ignition, Ignition writes to the tag in the OPC server, OPC server writes to PLC. The write succeeds and the value of the tag in Ignition is now true.
  2. The PLC logic writes it back to false.
  3. The tag is eventually sampled by the OPC server and it sees false, the same as the previous value it reported, so there is no change to report to the client.
  4. The value of the tag in Ignition and the value of the tag in the OPC server and PLC now differ.

While this behavior wouldn’t be classified as a bug, we still would like to provide a solution to this race condition besides using the two mentioned workarounds, which were:
1. to modify their PLC program/logic so multiple systems aren’t writing to the same tag (this would be a best practice)
2. to use a dedicated Tag Group in OPC Polled Mode for any tags that are written to from Ignition and immediately reset by the PLC.

We currently have an internal ticket that is in progress to add an additional setting for timestamp-only changes that will allow you to get the requested value for your tags even if the value sampled by the OPC server sees it as the same value that it previously reported. This setting will be on the tag group, so you would group the tags that you expect to be written to by multiple sources. Once this feature is added, it will resolve the issue caused by the race condition.

Note that in my situation, I was writing a 1 to a boolean that was immediately reset to 0 by the PLC - HMI oneshot button logic, effectively. Slightly different than your case, but same principles. Also note that my issue seemed to be brought on specifically when enabling read after write in the tag group.

As of 2 weeks ago, there was not an estimated release date/version for the feature mentioned - just confirmation that it was in the works.

I always use bits that are set to 1 in the HMI and immediately used and reset in the PLC with no problem, using Siemens PLC.
I think your problem is that you reset the bit using the Tag Change Script. Just use a Gateway Timer script that executes every x seconds that writes 0 to the PLC before the heartbeat times out.

Otherwise, follow pturmel solution. Anyway I suggest to use a Gateway Timer script to write the bit to the PLC. IMHO avoid the Tag Change script for an heartbit, where an immediate response from the HMI is not needed, and, mostly, when you write back to the same tag.

This will eventually bite you in the [expletive]. That it hasn’t yet is just chance.

I just read the Cory.grube explanation more carefully, and now I see the problem. I thought it had to do with the tag change logic and/or the driver not being Siemens (that uses a continuous polling to the device), but I was wrong.

But if now I understood the problem correctly, it should almost always happen if you enable the Read After Write in the tag group. In my case this property is not enabled and probably the issue almost never happens.

Returning to the topic, I think what BCNoyes experienced was due to the combination of device disconnection and the use of the tag change script to write back false to the tag. It had nothing to do with the Read After Write issue.

Finally, the solution I proposed will almost always work. Your solution works always and it is defenitely the way to go.

Thank you for making me think more about the issue…

What do you recommend as an alternative? I always thought this was regarded as best practice (in favor of other solutions like HMI momentary buttons)

Toggle a bit, where each change is a trigger. Or increment a short integer (with rollover), where each change is a trigger.

1 Like

Unfortunately I have no control over the PLC Logic, it is a ‘closed’ system supplied by a 3rd party, and the issue doesn’t occur using their MES software package, which I believe uses Kepware to communicate with the PLC. I will see if they can tell me if the PLC sets the heartbeat immediately or after a timer elapses. I do know the PLC heartbeat timeout is 5 seconds so I can move my script from a tag change to a timer script and set it to 2 seconds (should hopefully give enough delay on the ignition side). I will also setup a tag group just for the heartbeat with a polled OPC mode.