libplctag / libplctag.NET

A .NET wrapper for libplctag.
https://libplctag.github.io/
Mozilla Public License 2.0
194 stars 50 forks source link

Tag write timing #374

Closed bwcurless closed 3 weeks ago

bwcurless commented 1 month ago

Hi, I don't think this is an actual issue in the library, but I have a question about the timing of writing different tags in succession. I am using a CompactLogix PLC and am attempting to write two tags in a specific order (or atleast simultaneously), but I sometimes seem to end up with my ladder routine seeing the two tags get written out of order. I'm awaiting two async calls to WriteAsync() like so:

  1. await Tag1.WriteAsync();
  2. await Tag2.WriteAsync();

During execution of a program on the PLC I expect these two scenarios:

However, I believe this is occurring:

Is there any reason that I should expect this behavior? What does the task that WriteAsync() returns completing signify? My understanding is that when we write a tag with 0 timeout (in libplctag) that means it's an async write. When does the callback come from libplctag signifying that the write has completed? Does the task complete when the PLC confirms that it received the CIP message to update the tag, and does that mean that the tag is already updated in the PLC (ie the variable will have the new value on the next scan)?

I have a few workarounds that I can implement like delaying between writes, reading back the value of a tag that I am writing, or restructuring my communication scheme but I wanted to get a better understanding before choosing path. Of course maybe I'm mistaken and there is no way this could happen and I am having a different problem.

Things have been working great for us in general using this library so I wanted to say thanks again.

timyhac commented 1 month ago

We usually expect that IO is somehow synchronized with the scan - i.e. For each scan

  1. Input values are copied from Input modules into CPU memory
  2. all the PLC rungs are executed
  3. the output tags are copied to output modules.

But this is not necessarily the case - the updates to tag memory can happen mid-scan. So what you are describing could definitely happen with the typical/correct/expected behaviour. My understanding is that many PLC systems do this IO buffering by default - especially for local IO.

What could be happening in your case is that both tags are written in Scan 1, but the scan execution has already passed the point where you check Tag 1, and you only discover the new value on the next scan.

We could have a bug however - you can confirm that this problem has nothing to do with the Task/async by using the synchronous versions of the write commands. Debug logs, code repros, screenshots, wireshark logs will all help .

kyle-github commented 1 month ago

We've definitely seen larger tags show partial updates during a scan. For instance if you have an array of DINT of length 100, you could see the first 30 entries updated on one scan and the rest on the next. That particular problem is purely the PLC.

I think Tim's explanation is another example of the same problem.

timyhac commented 3 weeks ago

Hi @bwcurless - I trust that this explains what is going on with your system but would be happy to be wrong.

Please raise a new issue if you do find some evidence that there is something else going on and please include the fault-finding work you've done.

bwcurless commented 2 weeks ago

Sounds good. These explanations were very helpful for me and prompted me to dig a bit further beyond what I was being told. My issue ended up being related not to tags being written out of order, but a first write failing, and the second write succeeding, making it seem like they happened out of order. If I find an actual issue I'll figure out a way to reproduce it in the future. Thank you both.