Fastest way to retrieve data from OPTO22

I am trying to figure out the fastest way to communicate with my OPTO 22 DAQ.

Right now I’m communicating to it through peer-to-peer using python and rest API calls for groovManage. The response times are anywhere between 0.1ms - 0.15ms with waiting for a response code, and anywhere between 0.02ms - 0.05ms utilizing threading and not waiting for a response code.

Does anyone know a faster way to retrieve and set data that can still interact with python from a separate computer? I don’t have any of the OPTOMMP cards, only ODCSRC-24, IV-24, IVI-12

Thanks I really appreciate it!

Fastest would be to setup OptoMMP UDP streaming where you setup memory areas that get pushed out to another IP port.

3 Likes

REST (as you have discovered) is about the slowest way.
Philip is spot on with the UDP streaming.
@torchard did some Python MMP benchmarking, he might have some thoughts on this.

1 Like

Oh, and all our cards have MMP.

1 Like

This is the area on a PR1 to enable the streaming:

Set index 4 to 1 to enable, 0 to disable the stream.
Index 5 is the interval in milliseconds.
Index 6 is the UDP port to stream to
Index 8 is the IP address of the system you are streaming to, each octet of the IP uses a byte of the value.

Default is to stream every IO channel possible, which is 2,308 bytes on the PR1 - this can be optimized by setting up the custom configuration area for the addresses you need and setting the streaming configuration to use the custom configuration area (check the OptoMMP Protocol Guide).

When streaming all 2,308 bytes and setting the index 5 to 1 for 1 ms, I was averaging a little over 2 ms for each push.

Note for Opto22 Devs: If I have the streaming set to 1 or 2 ms and then set index 4 to 0 to stop streaming, the streaming doesn’t stop - I think there is a bug here. I have to set the interval to 3ms or higher first, then I can write a 0 to index 4 and it stops.

Ugly Python UDP listener code that times the intervals and averages the last 100 and displays the results repeatedly:

import socket
from timeit import default_timer as timer

sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sock.bind(("", 10500))

lstTimes = [0.0]*100
i=0
start = 0
while True:
    data, sender = sock.recvfrom(2500)
    end = timer()
    duration = end-start
    start = timer()
    lstTimes[i]=duration
    i = i + 1
    if i == 100:
        i = 0
    size = len(data)
    avg = sum(lstTimes)/100.0
    print("Received a message of size %d bytes. Time since last packet: %6.4f. Average: %6.4f" % (size, duration, avg), end='\r')
3 Likes

Thanks guys! I got the OPTOMMP protocol working and it is fast enough for my applications (around 0.3ms). I’ll look into UDP streaming if I have faster requirements but for now this is all good information.

Also not sure if this changes between OS’s but importing the optommp library into Python didn’t work natively for me. I had to edit the “init.py” to go from “import O22SIOUT” to “from . import O22SIOUT.” Not sure if you guys have some devs that want to update the github for that.

Was it 0.003ms or 3ms?

My bad, just revisited my code I had a conversion error.
Should be 0.3ms.
I would take also take this measurement with a grain of salt though, since it’s written in Python and I’m not even sure if Python can output that kind of resolution. I’m using the perf_counter_ns() function from the time library to calculate just a single function call (for example: “GetAnalogPointValue()”)

Hey Philip, how were you able to get this page? The closest page I could get to this was under Generic MMP in I/O configuration, but the addresses don’t match so I’m assuming I’m in the wrong area

That is the “Generic MMP” page as you listed. You should be able to change the address and any of the other parameters.

1 Like