Jump to content

As of July 17, 2015, the LabJack forums here at forums.labjack.com are shut down. New registrations, topics, and replies are disabled. All forums are in a read-only state for archive purposes.

Please visit our current forums at labjack.com/forums to view and make new posts. To post on the current forums, use your labjack.com login account. Your old LabJack forums login credentials have been retired. There are no longer separate logins for labjack.com and LabJack forums.


Photo

Errors in Stream Mode w/ LabjackPython


  • Please log in to reply
5 replies to this topic

#1 aganders3

aganders3
  • Members
  • 3 posts

Posted 06 May 2015 - 09:11 AM

I just got a LabJack U3-LV for monitoring some temperature probes. The device is great - simple to set up and the Python interface is intuitive and well maintained. I'm also quite impressed with the support I see provided.

 

My logging/monitoring program is working, but I am having trouble achieving the sampling rates outlined in the User Guide. It should be obvious from my code sample that I am basing my program on the streamTest.py example.

 

Basically I configure the U3 like so, where I set the ScanFrequency to MaxStream [Samples/s] / num_channels. I am getting the maximum sample rate from the user guide.

self.input_channels = [0,1,2,3,4,5]
self.num_channels = len(self.input_channels)
# try to open the U3
self.daq = u3.U3()
self.daq.getCalibrationData()
self.daq.configIO(FIOAnalog=0x3F) # AIN 0-5
self.daq.streamConfig(NumChannels = self.num_channels,
                      PChannels = self.input_channels,
                      NChannels = [32]*self.num_channels,
                      Resolution = 1,
                      ScanFrequency = 10000 // self.num_channels)

Then I sample like so, processing the data as it comes in and updating a plot in separate Timer threads:

if not recover:
    with self.sample_lock:
        self.dataCount = 0
        self.V_samples = np.zeros((self.num_channels,))
        
# continuously sample data using the U3 streaming mode
try:
    if not self.daq.streamStarted:
        self.daq.streamStart()

    # continuously running loop
    for r in self.daq.streamData():
        if r is not None:
            if r['errors'] != 0:
                print("STREAM ERROR : {}".format(r['errors']))

            if r['numPackets'] != self.daq.packetsPerRequest:
                print("---- UNDERFLOW : {}".format(r['numPackets']))
                    
            if r['missed'] != 0:
                print("++++ MISSED : {}".format(r['missed']))

            # average samples 
            with self.sample_lock:
                self.V_samples += [sum(r['AIN{}'.format(ch)]) / len(r['AIN{}'.format(ch)]) for ch in self.input_channels]
                self.dataCount += 1
        else:
            # no data from read
            print("No data")
except LabJackException as e:
    print(e)
    self.daq.streamStop()
    print "Restarting stream..."
    self.start_collecting(recover=True)
finally:
    self.daq.streamStop()

 

This seems to mostly work, but using the ideal rates I get many missed samples and stream errors #40 (SHT1x_COMM_TIME_OUT). If I lower the sampling rate, there are fewer missed samples, but I still get many stream errors #32 (SMBUS_INQ_OVERFLOW) and #8 (??). So now I am sampling at only 2000 // num_channels = 333 Hz to avoid such errors and it seems to have eliminated these errors.

 

Obviously these sampling rates are quite fast for temperature readings, but the readings are coming from an MRI scanner and become very noisy due to rapidly changing EM fields during imaging. Therefore I would like to collect a grip of samples to average out the noise. Any thoughts? I've just noticed (while writing this post) the streamTest-threading.py example, and will look for clues in there as well. Thanks!

 



#2 LabJack Support

LabJack Support
  • Admin
  • 8677 posts

Posted 06 May 2015 - 10:50 AM

If your stream Resolution is 1, the max. stream rate is 10K samples per second. You should be able to set the ScanFrequency to 1666 when streaming 6 channels (9996 samples/sec.).

 

If you are trying for 50K samples per second (the max. for the U3), the stream Resolution needs to be set to 3 and the ScanFrequency to 8333 for 6 channels (49998 samples/sec.).

 

In the code you provided, you are streaming at a sample rate of 60K (ScanFrequency*num_channels) with Resolution set to 1 which would lead to errors. I'm not sure about the errors you provided as stream errors are 48 to 63.

 

In regards to code, make sure your plot and lock code is not causing significant delays in your stream read loop. Not reading stream data from the U3 at a fast enough rate can lead to stream buffer overflows on the U3.

 

If you are trying for a 50K sample rate, you may want to try a USB high-high configuration as mentioned in the stream mode section of the User's Guide which can help USB performance. To test general speeds on your computer you can use the u3allio.py example and compare speeds to the table in the command/response section of the User's Guide. This will let you know if you already have the USB high-high performance. USB high-high performance can speed up your streamData call/loop and help prevent stream buffer overflows.



#3 aganders3

aganders3
  • Members
  • 3 posts

Posted 06 May 2015 - 11:11 AM

Thanks for the quick reply and the helpful suggestions.

 

In the code you provided, you are streaming at a sample rate of 60K (ScanFrequency*num_channels) with Resolution set to 1 which would lead to errors. I'm not sure about the errors you provided as stream errors are 48 to 63.

 

In Python the // operator performs integer division, so with six channels I should be scanning at 10000 Hz // 6 channels = 1666 Hz, for a total sample frequency of 9996 Hz. Maybe I am getting something backwards here? I was confused by the error numbers before, but now I am extra-confused there. Printing them as I am above (print("STREAM ERROR : {}".format(r['errors']))) should give decimal values, and I can repeatably get 40, 32, and 8.

 

I will look at the USB configuration and test the speeds using u3allio.py. I've measured the performance of the plotting code and it should be plenty fast, but I will do some further profiling to see if it can be optimized.



#4 LabJack Support

LabJack Support
  • Admin
  • 8677 posts

Posted 06 May 2015 - 11:37 AM

I was reading the // as a comment. I must have C/C++ on my mind.

 

Also, make sure you are running the latest U3 firmware just in case. The latest is v1.46 and beta v1.49:

 

http://labjack.com/support/firmware

http://labjack.com/support/firmware/u3

 

After checking performance and optimizing if necessary, let us know if the issue is still occurring as a scan frequency of 1666 Hz for your settings should be doable.



#5 LabJack Support

LabJack Support
  • Admin
  • 8677 posts

Posted 06 May 2015 - 11:59 AM

Regarding errors that streamData returns, that is actually a count of the number of errors detected in the StreamData packet responses and not the error codes. Sorry I didn't catch that in my first response. I talk about that in a comment here on our site which also provides code on getting the error codes which will hopefully give a better understanding of what is going on:

 

The errors key's value is a count of the errors detected in the StreamData response packet byte 11. Byte 11 in each packet is an errorcode. You could do something like this to print out what the StreamData packets error codes are when streaming to give a better idea on what is happening:

            cnt = 0
            #StreamData packets are 64 bytes and the 11th byte is the error code.
            #Iterating through error code bytes and displaying the error code
            #when detected.
            for err in r['result'][11::64]:
                errNum = ord(err)
                if errNum != 0:
                    #Error detected in this packet
                    print "Packet", cnt, "error:", errNum
                cnt+=1

Error codes can be found here:

 

http://labjack.com/s...users-guide/5.3

 

With the STREAM_AUTORECOVER_ACTIVE error you will be getting the valid data that was buffered on the U3 before the overflow occurred.



#6 aganders3

aganders3
  • Members
  • 3 posts

Posted 06 May 2015 - 12:25 PM

Ahh, thanks. That makes sense and will give me a lot more to look at.




0 user(s) are reading this topic

0 members, 0 guests, 0 anonymous users