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

What is wrong with my code


  • Please log in to reply
7 replies to this topic

#1 Billo

Billo
  • Members
  • 5 posts

Posted 30 November 2012 - 10:49 PM

I only read all zeros from the LabJack, can you tell me where I am going wrong please. The simplified code is attached. Thanks, Bill

Attached Files



#2 LabJack Support

LabJack Support
  • Admin
  • 8677 posts

Posted 03 December 2012 - 02:10 PM

What channels are you trying to stream, and are you performing a Go/GoOne call after your AddRequest calls to send the requests to your U3? I didn't see those in your attached code.

Also, if you haven't done so take a look at the Stream Mode pseudocode in the User's Guide as it provides more documentation on streaming with the UD driver than the Delphi example:

http://labjack.com/s...ers-guide/4.3.7

#3 Billo

Billo
  • Members
  • 5 posts

Posted 04 December 2012 - 03:12 AM

Thanks for your reply, I will read the User's Guide. Attached is the code leading up to the start of the stream, it is mainly a paste from the example code. The number of channels depend on which test is being done. Selecting a test sets or clears the UseCh1 .. UseCh16. I wonder if I should be attempting to clear the little buffer, perhaps the driver does it. Could I just pass a pointer to my large array and have the UD Driver continually stream to it until the stream is stopped?

Attached Files



#4 LabJack Support

LabJack Support
  • Admin
  • 8677 posts

Posted 04 December 2012 - 02:10 PM

Are there any errors being reported in your program and how are you handling them? After your GoOne call that configures the stream settings are you checking the results for errors like in the example? UD settings wise I do not see a problem, but your ReadArray is too small for most conditions. Your ReadArray needs to be the size numScans*numChannels. Your current ReadArray will have problems if numChannels > 1. As for your stream read loop, you should not always be getting zero (9999) values and if you are I would expect an error from your "eGet(lngHandle, LJ_ioGET_STREAM_DATA, LJ_chALL_CHANNELS, numScansRequested, @ReadArray)" call. The rate you are reading from the UD's stream buffer is fast though, so you may have some stream reads that are empty. The U3 stream buffer on the U3 hardware 512-984 samples, and you are trying to read 1000 scans (1000*numChannels = samples). To check the number of scans read, check numScansRequested after your stream read as this may be different than the value you passed. When you iterate through the ReadArray, do this for loop instead: "for a := 0 to numScansRequested*numChannels do". When you perform a stream read the UD driver returns the requested amount of scans/samples (or what is available), and removes the scans from its buffer. You can pass either your little buffer or your large buffer assuming it is a double array. The buffer just needs to be large enough for the number of scans you request. My Delphi/Pascal is a bit rusty, so I am not sure if you can pass a pointer to specific locations in your large buffer like in C.

#5 Billo

Billo
  • Members
  • 5 posts

Posted 07 December 2012 - 04:26 PM

Thanks for your detailed reply, I really appreciate it. > UD settings wise I do not see a problem, but your ReadArray is too small for most conditions. Your ReadArray needs to be the size numScans*numChannels. Your current ReadArray will have problems if numChannels > 1. It is array[0..1000] of double because thought it contains only one read of the LJ buffer which is only 975 doubles. I then empty it ready for the next read in 10mS time. > The rate you are reading from the UD's stream buffer is fast though, so you may have some stream reads that are empty. To check the number of scans read, check numScansRequested after your stream read Ok, I will only use the first numScansRequested doubles from each read. >You can pass either your little buffer or your large buffer assuming it is a double array. The buffer just needs to be large enough for the number of scans you request. So if I pass my large buffer and do a single request of say 500,000 scans will it stream the whole lot into my large buffer.? I obviously haven't done enough reading of the manual, I thought I could only read 975 doubles at a time. I have done some tests and there are no errors in the initialising of the variables or of the U3. (Last attached file) The first error is - // Start the stream. lngErrorcode := eGet(lngHandle, LJ_ioSTART_STREAM, 0, dblValue, 0); error = 7, XBR_CONFIG_ERROR I can't find reference to XBR_CONFIG_ERROR or even XBR in the manual. dblValue was set to 0 as in the 2 channel streaming example. Since it looks like a stream error I guess that the other 2 errors are a result of the stream not working. The other 2 are - // Put the U3 data into the (temp) ReadArray[0..1000] lngErrorcode := eGet(lngHandle, LJ_ioGET_STREAM_DATA, LJ_chALL_CHANNELS, numScansRequested, @ReadArray); error = 4, ADC0_BUFFER_OVERFLOW //Stop the stream lngErrorcode := eGet(lngHandle, LJ_ioSTOP_STREAM, 0, dblTemp, lngTemp); error = 5, FUNCTION_INVALID

#6 LabJack Support

LabJack Support
  • Admin
  • 8677 posts

Posted 07 December 2012 - 06:52 PM

For referencing UD driver error codes use this list instead of the low-level one:

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

Error 7 is LJE_UNABLE_TO_CONFIG_STREAM, error = 4 is LJE_UNABLE_TO_START_STREAM and error = 5 is LJE_UNABLE_TO_STOP_STREAM. I would expect error 7 for your stream config GoOne or results error checks and error 4 for the "eGet(lngHandle, LJ_ioSTART_STREAM, 0, dblValue, 0)".

I looked over your code again and it looks like I missed a problem with your "ePut(lngHandle, LJ_ioPUT_ANALOG_ENABLE_PORT, 0, 65536, 16)" call. I think you meant "ePut(lngHandle, LJ_ioPUT_ANALOG_ENABLE_PORT, 0, 65535, 16)" to set FIO0-15 to analog inputs. A value of 65536 is 10000000000000000 in binary, so you are setting the FIO lines to digital currently. This is probably the cause of your problem of the stream not starting since you are trying to stream FIO lines as analog inputs but they are configured as digital.

As for the size of the UD driver's buffer, it is the size you set it to in your LJ_chSTREAM_BUFFER_SIZE AddRequest. The value you set is the number of samples the UD driver will buffer. It is possible to read more that 975 samples (U3 hardware's stream buffer is 512-984 samples) in one UD stream call since the UD driver is collecting stream data from the U3 in the background and appending it to its software buffer. Section 4.3.7 of the User's Guide (the link in my first post) describes all of this further.

>So if I pass my large buffer and do a single request of say 500,000 scans will it stream the whole lot into my large buffer.?

If you are going to do that many scans it might be better to read smaller scans and add them to your large buffer. You can try to read that many and see how it works out. To help prevent stream buffer overflows make sure your LJ_chSTREAM_BUFFER_SIZE is larger than your stream scan reads and that you read stream scans at a fast enough rate. Also, note that 1 scan is numChannels samples.

Regarding LJ_chSTREAM_WAIT_MODE settings, you currently have it set to LJ_swNONE which will read the amount of scans currently in the UD driver's stream buffer up to the numScansRequested you passed. The Sleep delay lets the stream buffer build up. If you use the LJ_swSLEEP setting, the stream read call will block until all numScansRequested scans are available or will timeout with no scans. You do not need to use the Sleep calls with this setting.

#7 Billo

Billo
  • Members
  • 5 posts

Posted 08 December 2012 - 04:27 AM

Thanks for your persistence especially in finding the 65536 / 65535 typo. I now only get the error 5 LJE_UNABLE_TO_STOP_STREAM. I have been confusing the U3 buffer and the driver buffer, I think I've got it now - The U3 buffer is 984 but I'm not reading from it, the driver is reading it in the background and placing several of the U3 buffers into the buffer declared in LJ_chSTREAM_BUFFER_SIZE. It is this buffer that I am reading and so my ReadBuffer in eGet(lngHandle, LJ_ioGET_STREAM_DATA, LJ_chALL_CHANNELS, numScansRequested, @ReadArray); should not be 1000 but big enough for several lots of 984. I like your suggestion of using LJ_swSLEEP (with no wait) because the number of samples read per loop will be the same every time. I still haven't been able to see the input that is tied high but that will happen tomorrow - I will try again tomorrow with these values - I need to log 50,000 / Sec for usually 2 seconds but there is an option to log for 20 Sec. (Sometimes 2 channels @ 25000/S each, sometimes 15 channels at 3333/S each) So the Large Buffer will be 1..1000000 (50,000 x 20) The LJ_chSTREAM_BUFFER_SIZE is currently 50000*Seconds but only 50,000 will be overkill because that will allow reads from it up to almost a second apart. The ReadArray that I use to empty the driver buffer will be 1..6000 with a numScansRequested of 5,000. Using LJ_swSLEEP mode it will drain the driver buffer about 10 times / Sec. Each 5000 will be appended into the large buffer. Thanks again for your help.

#8 Billo

Billo
  • Members
  • 5 posts

Posted 09 December 2012 - 04:03 AM

Thanks again for you help, I have finally got it working. No error codes and valid data from the U3.


For anyone following this post here is the code using my first guess values.
It will be tidied up later.


DataArray : array[1..1000000] of Double; // 50,000/Sec x 20 Sec.

ReadArray : array[1..20000] of double; // Reads 1,000 Scans from the Driver buffer from up to 16 ch.
// A Scan is a read of all ActiveChannels.


// Give the Driver a large buffer.
lngErrorcode := AddRequest(lngHandle, LJ_ioPUT_CONFIG, LJ_chSTREAM_BUFFER_SIZE, 50000, 0, 0);

// Configure reads to retrieve a fixed amount at a time (LJ_swSLEEP).
lngErrorcode := AddRequest(lngHandle, LJ_ioPUT_CONFIG, LJ_chSTREAM_WAIT_MODE, LJ_swSLEEP, 0, 0);

// I will request 1,000 scans per loop. A Scan is all ActiveChannels.
// 50000/(1000 * ActiveChannels) = Loops per second.
// * Form1.SpinEditLogSeconds.value = Total Loops.
// Ceil = Round Up the number of loops.

n := 1; // The LoggedData index
ii := 0;
while ii < Ceil((50000/(1000 * ActiveChannels)) * Form1.SpinEditLogSeconds.value) do
begin

// Request 1,000 scans. The amount of data = 1,000 x ActiveChannels
numScans := 1000; numScansRequested := numScans;

// Get the 1,000 scans from the Driver Buffer into the ReadArray
lngErrorcode := eGet(lngHandle, LJ_ioGET_STREAM_DATA, LJ_chALL_CHANNELS, numScansRequested, @ReadArray);
// Append the valid part of the ReadArray to the DataArray
for a := 1 to (1000 * ActiveChannels) do
begin
DataArray[n] := ReadArray[a];
n := n +1;
end;
ii := ii +1;

end;


Because the number of loops is rounded up, the data will be logged slightly more than the Form1.SpinEditLogSeconds.value.
That is ok because the 2Sec, 5Sec, ... 20Sec are only nominal periods of logging.


0 user(s) are reading this topic

0 members, 0 guests, 0 anonymous users