Vision has a default project polling rate of 250ms; you can speed this up, but not by enough that any of this other stuff you're doing actually matters.
I think anything you may have been doing to measure different data acquisition methods is faulty because all of them would have been an order of magnitude faster than this.
When I originally wrote this it was a script in the Project Library here's my code for that. I'm not sure why but I put a label on the screen in Vision and it updates instantly, when I see the tag value update in my tag browser it updates at the same speed it does on the screen.
import socket
UDP_PORT = 5175
sock = None
is_running = False
def stopFunction():
global is_running
global sock
is_running = False
if sock:
sock.close()
sock = None
print("UDP listener stopped.")
def startFunction():
global is_running
global sock
print("Starting UDP listener...")
try:
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sock.bind(("0.0.0.0", UDP_PORT))
sock.setblocking(False)
is_running = True
print("Socket successfully bound to UDP port", UDP_PORT)
system.util.invokeAsynchronous(__udpListener)
except Exception as e:
print("Failed to bind UDP socket:", str(e))
sock = None
def __udpListener():
global is_running
global sock
print("UDP listener thread started")
while is_running and sock:
try:
data, addr = sock.recvfrom(1024)
value = float(data.decode('utf-8').strip())
# print("Received from", addr, ":", value)
system.tag.writeBlocking('[IntIgnitionProv]EncoderBoards/SkylightRenishawSawER/encoderBoardValue.value', value)
except socket.error:
pass # No data right now
except Exception as e:
print("Error receiving UDP:", str(e))
print("UDP listener thread exiting")
But when when I moved this to a gateway event like the example I sent earlier it updates much slower on the screen. I think it's about 250ms so it must be because the polling rate. My question is why does the code above update instantly but when it's in the gateway events it doesn't?
You probably executed it on a button or in the Designer script console the first time you tested it. Or some Vision event.
It doesn't matter where you wrote it (script library), it matters where you execute it from (the scope as it's called in Ignition - Gateway (including Perspective), Vision Client, or Designer).
Yes, but that also means it's running directly in that Vision Client process and not on your Gateway. and if you open multiple Clients, they may all start running it, and all be communicating with the device.
Yeah and that's my issue with wanting to move it to the gateway. We actually run our HMI's on the same server and the machines on the floor RDP to the HMI session so I didn't think it would make a difference performance wise
my thought now was to have each individual encoderBoard and HMI talk on a different port but I don't know if this is ideal
If you truly need fast screen updates in Vision then each Vision instance communicating with the device directly might be your only option. You might be able to crank the client poll rate up to 100ms but not sure it's wise to go any faster.
I just had another idea of having another script in the project library that's just a while loop that reads the value from the tag and updates the label on the screen essentially increasing the poll rate but only for one single label.
Do you think this would work or be a good solution?
I'm about to test it out anyways but would love to know what you think about that idea too
Hmm, I don't know. N number of clients calling system.tag.readBlocking in a hard loop might be tough on the Gateway... it might work, but it's not pretty. You'll have to see how it performs.
That's true I'd need to test it out and make sure it doesn't slow down the gateway too much
even though it'd be challenging I feel like my best option right now is to go the Project Library route and have each board and HMI instance communicate on a different port or make sure only one UDP listener is running at a time
You write this as though it matters for how it runs. It does not. The project library is just a library. It doesn't run any code by itself. Code runs from the library when an event calls it, or a thread starts with it. The scope in the library is the scope of the event that kicks it off.
Ignition is event driven. Procedural code will tie up the event system if you aren't very careful, and/or intelligently spawn a new thread.
The Vision button is inside the JVM running in the client machine. The gateway event starts the code running in the gateway's JVM. The gateway JVM delivers tag data to the Vision client at the poll rate. The button code is running directly in the client--no polling involved.
You can turn the poll rate (project property) down to 100ms. I'm not sure if you can go faster than that. (It's rough on the network.) It is hard for humans to detect much faster than 100ms, though.
Ahh this makes more sense I get it now. So it seems like my best option right now is to have each client run a UDP listener on a different port and that would help with the speed.
Is there a way to have the project library script run on startup within the client machine?
Never mind I realized I can do this with Gateway Events startup and call the function from the project library script