Register access blocking while streaming | LabJack
 

Register access blocking while streaming

5 posts / 0 new
Last post
Andrew Jones
arjones6's picture
Register access blocking while streaming

Hi,

I'm trying to use a labjack to stream input data at a certain rate, while writing data to the output registers and reading the dios by direct register access.  In my code I have a loop where I read inputs using eStreamRead, then write to DAC0 and DAC1 with eWriteName, then read DIO_STATE with eReadName.  I've set the STEAM_SCANS_RETURN function to STEAM_SCANS_RETURN_ALL_OR_NONE, so the eStreamRead doesn't block if there isn't input available.  However, the eWriteName and eReadName calls will block until the next sample time.  In the example code I'm attaching I set the stream rate to 2 samples per second.  Then each eWriteName and eReadName call blocks for half a second before returning.  Is there something I can do to keep those calls from blocking when streaming inputs?

Thanks,

Andrew

LabJack Support
labjack support's picture
The cause of the issue is in

The cause of the issue is in LJM. I will update this thread when a fix is available. A workaround is as follows.

To account for possible clock drift between the host computer and the LabJack, the LJM stream data collection thread waits less than the full amount of time expected for new stream data to be made available. After that partial wait, the stream data collection thread locks the device and waits for bytes from the device. This wait is most likely causing the delay you're seeing. To cause LJM to wait the full expected time or more, update the LJM_STREAM_SLEEP_FACTOR config before starting stream. During my quick test, the following worked to remove long waits during eWriteName:

ljm.writeLibraryConfigS('LJM_STREAM_SLEEP_FACTOR', 1.3)

Note that this causes eStreamRead to throw LJME_NO_SCANS_RETURNED fairly often. 

Andrew Jones
arjones6's picture
Thanks for your prompt reply.

Thanks for your prompt reply.  That doesn't seem to have fixed the issue for me.  When I set SLEEP_FACTOR to 1.3 with a rate of 2, the first 10 points or os I still see a half second delay.  After that the delay starts getting less and less until it goes away entirely after 20 points or so.  After the register access delay goes away though the time between when a point is read by the labjack and when I read it in my code starts getting larger and larger. 

I'm attaching my modified script and its output.  In the output, it writes a line whenever a delay is detected, and also whenever a point is read.  In the input lines, the first number is the delay between when a point is collected and when it is read using the eStreamRead function according to the clock values returned. 

Let me know if I should be doing something differently.  Thanks,

Andrew

LabJack Support
labjack support's picture
I've made a test version of

I've made a test version of LJM that doesn't block when reading from stream (so regular reads and writes can happen in parallel). It's broken for macOS/Linux via USB, but seems to work for all OSes via Ethernet. What OS are you using? I can send you an installer.

LabJack Support
labjack support's picture
I talked to my manager and

I talked to my manager and unfortunately it looks to be too expensive for us to fix for macOS/Linux USB right now. Because of that, if you need to collect data at 2Hz while reading/writing to device, here are two workarounds:

 

1. Stream faster and discard all the data points you don't need.

If LJM is streaming faster, that means it's getting more packets per second, so the wait time per packet will be lower. You'll want to set the NumScans to something small, like 1, so that LJM reads once scan from the device at a time, and you can use a ScanRate like 1000 to ensure that LJM will never wait much longer than 1 ms per read from device. This is essentially low-latency stream.

 

2. Use a Lua script to replace stream

Using this method, you'll have a Lua script use an interval timer to collect data at 2Hz. Then, your program reads from device (USER_RAM) using e.g. eReadName(s). This loop can run as fast as you want. Then, you can read/write whatever other registers as needed, either from a separate thread/loop or from the same loop.