# Momentary Pushbutton latching ON

**URL:** <https://forum.inductiveautomation.com/t/momentary-pushbutton-latching-on/5373>\
**Category:** Ignition\
**Created:** [November 2, 2012, 10:23pm UTC](https://forum.inductiveautomation.com/t/momentary-pushbutton-latching-on/5373 "2012-11-02T22:23:15Z")\
**Posts on this page:** 14\
**Page:** 4

<div class="post-metadata">

**Author:** ![sbrannen](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/sbrannen/32/3459_2.png) [@sbrannen](https://forum.inductiveautomation.com/u/sbrannen)\
**Post date:** [December 17, 2018, 1:57pm UTC](https://forum.inductiveautomation.com/t/momentary-pushbutton-latching-on/5373/62 "2018-12-17T13:57:00Z")

</div>

Good day, shibubalaji...

> [@shibubalaji](#):
>
> _As you mentioned, I was trying to select the 'OPC Read after write for the scan class that are associated with this momentary button. But I don't see this option under my scan class editor._

**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

---

<div class="post-metadata">

**Author:** ![alexfediw](https://avatars.discourse-cdn.com/v4/letter/a/e95f7d/32.png) [@alexfediw](https://forum.inductiveautomation.com/u/alexfediw)\
**Post date:** [January 27, 2021, 9:10pm UTC](https://forum.inductiveautomation.com/t/momentary-pushbutton-latching-on/5373/63 "2021-01-27T21:10:49Z")

</div>

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

---

<div class="post-metadata">

**Author:** ![pturmel](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/pturmel/32/3295_2.png) [@pturmel](https://forum.inductiveautomation.com/u/pturmel)\
**Post date:** [January 27, 2021, 9:31pm UTC](https://forum.inductiveautomation.com/t/momentary-pushbutton-latching-on/5373/64 "2021-01-27T21:31:49Z")

</div>

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.

---

<div class="post-metadata">

**Author:** ![alexfediw](https://avatars.discourse-cdn.com/v4/letter/a/e95f7d/32.png) [@alexfediw](https://forum.inductiveautomation.com/u/alexfediw)\
**Post date:** [February 3, 2021, 3:59pm UTC](https://forum.inductiveautomation.com/t/momentary-pushbutton-latching-on/5373/65 "2021-02-03T15:59:52Z")

</div>

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!

---

<div class="post-metadata">

**Author:** ![pturmel](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/pturmel/32/3295_2.png) [@pturmel](https://forum.inductiveautomation.com/u/pturmel)\
**Post date:** [February 3, 2021, 4:04pm UTC](https://forum.inductiveautomation.com/t/momentary-pushbutton-latching-on/5373/66 "2021-02-03T16:04:43Z")

</div>

> [@alexfediw](#):
>
> any reason why this isn’t a viable solution?

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.

---

<div class="post-metadata">

**Author:** ![alexfediw](https://avatars.discourse-cdn.com/v4/letter/a/e95f7d/32.png) [@alexfediw](https://forum.inductiveautomation.com/u/alexfediw)\
**Post date:** [February 3, 2021, 4:09pm UTC](https://forum.inductiveautomation.com/t/momentary-pushbutton-latching-on/5373/67 "2021-02-03T16:09:44Z")

</div>

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.

---

<div class="post-metadata">

**Author:** ![pturmel](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/pturmel/32/3295_2.png) [@pturmel](https://forum.inductiveautomation.com/u/pturmel)\
**Post date:** [February 3, 2021, 6:02pm UTC](https://forum.inductiveautomation.com/t/momentary-pushbutton-latching-on/5373/68 "2021-02-03T18:02:39Z")

</div>

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.

---

<div class="post-metadata">

**Author:** ![alexfediw](https://avatars.discourse-cdn.com/v4/letter/a/e95f7d/32.png) [@alexfediw](https://forum.inductiveautomation.com/u/alexfediw)\
**Post date:** [February 3, 2021, 7:04pm UTC](https://forum.inductiveautomation.com/t/momentary-pushbutton-latching-on/5373/69 "2021-02-03T19:04:23Z")

</div>

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

> [@pturmel](#):
>
> use a quickly changing signal from the client that affirmatively indicates that the button is still pressed

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.

> [@pturmel](#):
>
> all of the various ways a button-release event can fail

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).

> [@pturmel](#):
>
> the button must affirmatively transition from off to on again before it is allowed.

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.

---

<div class="post-metadata">

**Author:** ![pturmel](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/pturmel/32/3295_2.png) [@pturmel](https://forum.inductiveautomation.com/u/pturmel)\
**Post date:** [February 4, 2021, 1:28pm UTC](https://forum.inductiveautomation.com/t/momentary-pushbutton-latching-on/5373/70 "2021-02-04T13:28:07Z")

</div>

> [@alexfediw](#):
>
> controlValue check before initiating any action that I mention in my previous comment?

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

> [@alexfediw](#):
>
> covered by the PLC timeout, as no new writes will be sent

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

> [@alexfediw](#):
>
> requiring 2 consecutive 1 writes in the same index in order to move

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.

---

<div class="post-metadata">

**Author:** ![alexfediw](https://avatars.discourse-cdn.com/v4/letter/a/e95f7d/32.png) [@alexfediw](https://forum.inductiveautomation.com/u/alexfediw)\
**Post date:** [February 4, 2021, 2:00pm UTC](https://forum.inductiveautomation.com/t/momentary-pushbutton-latching-on/5373/71 "2021-02-04T14:00:19Z")

</div>

> [@pturmel](#):
>
> How will the PLC know you’ve written the same value twice to the same location?

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.

> [@pturmel](#):
>
> comms are lost to the client

This is incorporated into:

> [@alexfediw](#):
>
> saving the response code from system.tag.write and running cleanup and throwing an error window if it is not 1

> [@pturmel](#):
>
> How will your expression tag know the GUI is frozen

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

---

<div class="post-metadata">

**Author:** ![pturmel](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/pturmel/32/3295_2.png) [@pturmel](https://forum.inductiveautomation.com/u/pturmel)\
**Post date:** [February 4, 2021, 2:17pm UTC](https://forum.inductiveautomation.com/t/momentary-pushbutton-latching-on/5373/72 "2021-02-04T14:17:26Z")

</div>

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

> [@pturmel](#):
>
> - In a client window, create a timer component with a 100ms period. In its actionPerformed method, use system.util.sendMessage() with a specific bit number.
> - In the same client window, create a momentary button for that bit and bind its value to the timer component’s enabled property. Do not bind it to any tag.

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.

---

<div class="post-metadata">

**Author:** ![alexfediw](https://avatars.discourse-cdn.com/v4/letter/a/e95f7d/32.png) [@alexfediw](https://forum.inductiveautomation.com/u/alexfediw)\
**Post date:** [February 4, 2021, 2:30pm UTC](https://forum.inductiveautomation.com/t/momentary-pushbutton-latching-on/5373/73 "2021-02-04T14:30:00Z")

</div>

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 ?

---

<div class="post-metadata">

**Author:** ![pturmel](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/pturmel/32/3295_2.png) [@pturmel](https://forum.inductiveautomation.com/u/pturmel)\
**Post date:** [February 4, 2021, 3:03pm UTC](https://forum.inductiveautomation.com/t/momentary-pushbutton-latching-on/5373/74 "2021-02-04T15:03:22Z")

</div>

> [@alexfediw](#):
>
> that frozen GUI =\> actionPerformed won’t run =\> no Expression Tag change =\> Tag Change script doesn’t run =\> No write sent ?

Yes, that looks correct.

---

<div class="post-metadata">

**Author:** ![alexfediw](https://avatars.discourse-cdn.com/v4/letter/a/e95f7d/32.png) [@alexfediw](https://forum.inductiveautomation.com/u/alexfediw)\
**Post date:** [February 4, 2021, 3:04pm UTC](https://forum.inductiveautomation.com/t/momentary-pushbutton-latching-on/5373/75 "2021-02-04T15:04:29Z")

</div>

Thank you for your help

[Previous page](https://forum.inductiveautomation.com/t/momentary-pushbutton-latching-on/5373.md?page=3)
