Momentary Pushbutton latching ON

Good day, shibubalaji...

shibubalaji: I some cases, I have seen instances where dialog boxes do not always reveal all options and must be "mouse grabbed" and dragged down to enlarge the box and show all. But in your case, I believe it is a version issue. Please carefully consider Mr. Turmel's excellent replies to you question(s) and act accordingly.

Phil... thank you for your eloquent and thorough replies.

As you were...
Steve

Reviving topic to ask - assuming conditions such that synchronous implementation is reliable (I know this is a dangerous assumption, purely hypothetical) and we don’t need to worry about freezing the HMI, would using system.tag.writeSynchronous() eliminate the race? Thank you in advance

The core problem is not a race condition. It is simply the potential failure to deliver the message that writes to the PLC (resets the bit) when the button is released. That failure to write to the PLC can be caused by any failure in any device or network or piece of software between the user and the PLC. Leaving the signal turned on in the PLC. Some of the mitigation techniques have race conditions that make them unreliable, too. Using system.tag.writeSynchronous() doesn’t change the path the message must follow, nor make it more reliable.

2 Likes

I really appreciate this solution, but I thought of a variant that I was hoping you could provide feedback on, in case I am overlooking something.
Disclaimer: This solution is intended for the assumption the operator is only interacting with one PB at any given time.

-PLC uses a [1x2] array, storing an integer, and a boolean
-Instead of a timer event function, this utilizes a Tag Change - triggered by an Expression Tag (known in this description as x), which stores an integer

  • timer enabled: x = 0 (change triggers script), x = some unique index associated with this PB (change triggers script)
    -when a PB timer is disabled, x = negative unique index (change triggers script)
    Timer event function:
    -when switched to 0, do nothing
    -when switched to positive integer, send [x,1] to PLC
    -when switched to negative integer, send [-1 * x,0] to PLC

PLC:
-timer to check for broken comms
-stores a last received index, defaulted to -1
-new index,value pair received, reset timer
-value = 1, set tag corresponding to index, last received = index
-value = 0, reset tag corresponding to index, set last received = -1
-implement simple error handling regarding unexpected index values
-Note that the indices should be indexed by 1, not 0

I think this will decrease the memory needed, so for large numbers of PBs it should increase speed, and remove the constantly running timer, but will also require more PLC code.
Is there anything in here you think I am overlooking/any reason why this isn’t a viable solution?
Thank you for your help!

It doesn't address any of the failures between the user interface (Vision/Perspective) and Ignition.

I also think it unrealistic to expect only one momentary PB to be pressed at a time across your entire gateway/clients/designers. Unless you have code to enforce it, at which point a general solution starts to make sense.

You are right, if for some reason the ‘OFF’ condition isn’t triggered by the release, the button would continue to run. I think including a check in the enabled script of the timer to the controlValue to make sure it is still held down would fix this. Are there any others I am overlooking?
As for the usage of only one PB, we only use them in one application that is only instanced once - and don’t intend on including them in the future. In general though, I agree that it is a big assumption.

Perhaps you should start over at the top of this topic and review all of the various ways a button-release event can fail. Over the entire path to the PLC. I don’t see how your recommendation covers the cases.

The solutions that appear to cover all of the bases invariably use a quickly changing signal from the client that affirmatively indicates that the button is still pressed, with a short timeout at the PLC. Ensuring that the changing signal originates on the GUI thread (in Vision) is crucial to catching GUI thread crashes. This approach is typically accompanied by some housekeeping logic that ensures that once a timeout expires, the button must affirmatively transition from off to on again before it is allowed.

Thank you for the response, I have gone through the thread and your solution again, and have a few questions.

Am I misunderstanding, or is this not functionally identical to the controlValue check before initiating any action that I mention in my previous comment? If the check fails, cleanup.

The other sources of failure I know of are GUI freeze and gateway-plc comms failure, both of which I think are covered by the PLC timeout, as no new writes will be sent, and window closure while pressed, which I believe should cause the controlValue check to error (along the lines of component does not exist).

Thank you for this, I can imagine safety issues if a queue of pending "move"s were to form. I think saving the response code from system.tag.write and running cleanup and throwing an error window if it is not 1 should account for this. Although there is a chance this could still queue one move (I don't think it would, but can't find affirmative documentation as to what "immediately" constitutes, and whether it is less time than the PB timer), this could be fixed PLC side by requiring 2 consecutive 1 writes in the same index in order to move. Could easily use last_received for this, and the delay should be almost imperceptible to the operator, being at most 1/20 of a second.
Thank you again.

No, an expression tag doesn't guard any traffic from the GUI.

How will your expression tag know the GUI is frozen or comms are lost to the client?

How will the PLC know you've written the same value twice to the same location? If you reset it in the PLC in between, you are setting yourself up for races--see my notes about only writing a given regster from one direction.

default state of PLC: all associated PB tags = 0
last_received = -1
signal (i,1) received
if tag[i] == 0 && last_received == i { tag[i] =1}
else if last_received != i { last_received=i}

So the first time it will just set last_received, saying "there is a precedent for this message", and the second one will actually turn it on. Any PLC timeouts or other signals will reset this count, although that logic isn't included in this comment, just for simplicity.

This is incorporated into:

I was under the impression that if the GUI froze, the script associated with the timer would not run, but I am new to Ignition so you would certainly know better than I. For my reference - could you direct me to which aspect of your solution protects against a frozen GUI, as well as "guard[ing] against traffic from the GUI".
Thank you

Expression tags run in the gateway. If you aren't scripting in the gateway, then maybe your solution satisfies this part. Like mine:

The actionPerformed event runs on the GUI thread, so if the GUI chokes, the message won't be sent. If the messages aren't sent on a steady pace, or comms go down, the gateway side will see that signal's stale timestamp and kill it.

Thank you, I didn’t explicitly mention it in my original write up, but the timer I reference is bound to a PB in the same configuration. I believe the only difference is what is done in the actionPerformed method. Does this mean I can assume that frozen GUI => actionPerformed won’t run => no Expression Tag change => Tag Change script doesn’t run => No write sent ?

Yes, that looks correct.

1 Like

Thank you for your help