I am trying to implement a oneshot command where I send a true signal to an OPC tag, maintain it for 2 seconds, then set the signal to false. I've tried many different approaches, including time.sleep(), which I've read is not recommended. How would I go about doing this?
The only reliable way to do this is to use a gateway timer event that repeated examines current conditions (state) to decide what that signal state should be, and write it if not already that state. Typically, you would use a datetime memory tag to hold the desired turn-off timestamp. The code that would normally set that boolean would instead set the timestamp to two seconds in the future. Then the timer script would see that it is supposed to be on, and write that, and then notice when it should turn off, and write that.
If you don't care as much about reliability, you can use timer.
def runAction(self, event):
from threading import Timer
def runLater():
system.tag.writeBlocking([self.view.params.tagPath], [self.view.params.buttonOffValue])
system.tag.writeBlocking([self.view.params.tagPath], [self.view.params.buttonOnValue])
t = Timer(self.view.params.holdTime, runLater)
t.start()
Thank you for the suggesion. This does work, but reliability is important. Any reason why this would not be reliable?
Yes, so currently I have a gateway timer event that sets the tag to 0 every 3 seconds. It works, but is not very elegant, because the duration of the pulse varies based on when you set it to 1 within the timer duration. If I set it to 1 near the end of the 3 second timer, the pulse lasts very short, whereas if I set it to 1 near the beginning, the pulse lasts longer. I kind of understand your explanation, but not quite. Ideally, the timer would be enabled when the pulse rises from 0 to 1
It all depends why you need the timing and what happens if the connection to the device gets interrupted before it resets the tag.
In the scenario I recommend, you'd run the timer event all the time, probably ~100ms interval. Just like a PLC would do with a periodic task.
(If you have many of these, use just one fast timer event for everything.)