Hello everyone
I started working with labjack U3-HV recently and I use the analog inputs to make an acquisition of electrical signals. So I started working with the exemples code provided here:
https://labjack.com/support/software/installers/exodriver
I use the u3Stream.c code, it's an example given by labjack above, where it's explained how to make a streaming acquisition.
If I have understand well the u3 datasheets,
https://labjack.com/support/datasheets/u3/operation/stream-mode
it's specifed that we can make a streaming acquisition with different frequency sampling.
So my question is: How I can to do a streaming acquisition with a frequency that I choise? like 2ksamples/second
Thank you
In the StreamConfig low-level function, you configure the stream scan frequency with the Scan Interval setting in bytes 10 and 11. The StreamConfig_examples in u3Stream.c demonstrates this and the setting is documented here:
https://labjack.com/support/datasheets/u3/low-level-function-reference/s...
The interval between scans (in seconds) is the ScanInterval/ClockFrequency. So in relation to the ScanInterval and ScanFrequency (Hz), you would set the ScanInterval like so:
ScanInterval = ClockFrequency / ScanFrequency
For example, if you are streaming 1 channel at a scan rate of 2kscans/second (2ksamples/second), you could set it with the following scan interval with the 4MHz clock (StreamConfig: bit 3 of byte 9 set to 0):
ScanInterval = 4000000 / 2000 = 2000
Note that SampleRate = NumberOfChannels * ScanRate. Sample rate and scan rate terminology is discussed in the stream mode page you linked to in your post.
Hello,
Thank you for the response, I find the scanInterval in the code u3Stream.c
1 - Can you given me some details about the StreamData_example function? I don't understand why you use two loops numReadsPerDisplay and readSizeMultiplier to read the data?
2 - In case when I need use multiple analog input, I have a segmentation fault if I try use 2 inputs for example. How I can do to resolve this problem?
Best regards
1. At the beginning of the StreamData_example function, where the variables are declared there are comments describing the purpose of the variables. In more detail:
The numReadsPerDisplay variable is for outputting/displaying information to the terminal. Every numReadsPerDisplay number of LJUSB_Stream calls, stream status information is displayed.
The readSizeMultiplier variable indicates how many StreamData responses to read per LJUSB_Stream call. In the loop using this variable, its going through the readSizeMultiplier amount of StreamData responses and parsing out the samples.
In your own code, a numReadsPerDisplay loop would be optional and you could instead just use a loop that performs the LJUSB_Stream calls and a readSizeMultiplier loop to parse through the StreamData responses.
2. First, make sure numChannels is set to 2 or the amount of inputs you want to read so the voltages array size is the correct size. Second, make sure your recBuff and voltages arrays are large enough for the changes you make to the code.
If that doesn't help, attach your code in the next post so I can see your changes. What call in the code is causing the seg. fault?
Hello,
Sorry to give response late.
I attached the following code, the number of channels is 2. In the streaDta_example, I removed the numdisplay loop.
So If I understand well, I kept the numReadsPerDisplay loop which calls the LJUSB_Stream 24 times. In this case, I have an error process retourned 139 (0x8B). But if I use 1 channel, it works well.
<
code
type
=
"c"
>
#include "u3.h"#include <iostream>
#include <fstream>
using namespace std;
int ConfigIO_example(HANDLE hDevice, int *isDAC1Enabled);
int StreamConfig_example(HANDLE hDevice);
int StreamStart(HANDLE hDevice);
int StreamData_example(HANDLE hDevice, u3CalibrationInfo *caliInfo, int isDAC1Enabled);
int StreamStop(HANDLE hDevice);
const uint8 NumChannels = 2; //For this example to work proper,
//SamplesPerPacket needs to be a multiple of
//NumChannels.
const uint8 SamplesPerPacket = 25; //Needs to be 25 to read multiple StreamData
//responses in one large packet, otherwise
//can be any value between 1-25 for 1
//StreamData response per packet.
int main(int argc, char **argv)
{
HANDLE hDevice;
u3CalibrationInfo caliInfo;
int dac1Enabled;
//Opening first found U3 over USB
if( (hDevice = openUSBConnection(-1)) == NULL )
goto done;
//Getting calibration information from U3
if( getCalibrationInfo(hDevice, &caliInfo) < 0 )
goto close;
if( ConfigIO_example(hDevice, &dac1Enabled) != 0 )
goto close;
//Stopping any previous streams
StreamStop(hDevice);
if( StreamConfig_example(hDevice) != 0 )
goto close;
if( StreamStart(hDevice) != 0 )
goto close;
StreamData_example(hDevice, &caliInfo, dac1Enabled);
StreamStop(hDevice);
close:
closeUSBConnection(hDevice);
done:
return 0;
}
....
int StreamStart(HANDLE hDevice)
{
uint8 sendBuff[2], recBuff[4];
int sendChars, recChars;
sendBuff[0] = (uint8)(0xA8); //CheckSum8
sendBuff[1] = (uint8)(0xA8); //command byte
//Sending command to U3
sendChars = LJUSB_Write(hDevice, sendBuff, 2);
if( sendChars < 2 )
{
if( sendChars == 0 )
printf("Error : write failed.\n");
else
printf("Error : did not write all of the buffer.\n");
return -1;
}
//Reading response from U3
recChars = LJUSB_Read(hDevice, recBuff, 4);
if( recChars < 4 )
{
if( recChars == 0 )
printf("Error : read failed.\n");
else
printf("Error : did not read all of the buffer.\n");
return -1;
}
if( normalChecksum8(recBuff, 4) != recBuff[0] )
{
printf("Error : read buffer has bad checksum8 (StreamStart).\n");
return -1;
}
if( recBuff[1] != (uint8)(0xA9) || recBuff[3] != (uint8)(0x00) )
{
printf("Error : read buffer has wrong command bytes \n");
return -1;
}
if( recBuff[2] != 0 )
{
printf("Errorcode # %d from StreamStart read.\n", (unsigned int)recBuff[2]);
return -1;
}
return 0;
}
//Reads the StreamData low-level function response in a loop. All voltages from
//the stream are stored in the voltages 2D array.
int StreamData_example(HANDLE hDevice, u3CalibrationInfo *caliInfo, int isDAC1Enabled)
{
uint16 voltageBytes, checksumTotal;
long startTime, endTime;
double hardwareVersion;
int recBuffSize, recChars, backLog, autoRecoveryOn;
int packetCounter, currChannel, scanNumber;
int i, j, k, m;
int totalPackets; //The total number of StreamData responses read
int numDisplay; //Number of times to display streaming information
int numReadsPerDisplay; //Number of packets to read before displaying
//streaming information
int readSizeMultiplier; //Multiplier for the StreamData receive buffer size
int responseSize; //The number of bytes in a StreamData response
//(differs with SamplesPerPacket)
numDisplay = 1;
numReadsPerDisplay = 24;
readSizeMultiplier = 5;
responseSize = 14 + SamplesPerPacket*2;
/* Each StreamData response contains (SamplesPerPacket / NumChannels) * readSizeMultiplier
* samples for each channel.
* Total number of scans = (SamplesPerPacket / NumChannels) * readSizeMultiplier * numReadsPerDisplay * numDisplay
*/
double voltages[(SamplesPerPacket/NumChannels)*readSizeMultiplier*numReadsPerDisplay*numDisplay][NumChannels];
uint8 recBuff[responseSize*readSizeMultiplier];
packetCounter = 0;
currChannel = 0;
scanNumber = 0;
totalPackets = 0;
recChars = 0;
autoRecoveryOn = 0;
recBuffSize = 14 + SamplesPerPacket*2;
hardwareVersion = caliInfo->hardwareVersion;
printf("Reading Samples...\n");
startTime = getTickCount();
for( j = 0; j < numReadsPerDisplay; j++ )
{
/* For USB StreamData, use Endpoint 3 for reads. You can read the
* multiple StreamData responses of 64 bytes only if
* SamplesPerPacket is 25 to help improve streaming performance. In
* this example this multiple is adjusted by the readSizeMultiplier
* variable.
*/
//Reading stream response from U3
recChars = LJUSB_Stream(hDevice, recBuff, responseSize*readSizeMultiplier);
if( recChars < responseSize*readSizeMultiplier )
{
if( recChars == 0 )
printf("Error : read failed (StreamData).\n");
else
printf("Error : did not read all of the buffer, expected %d bytes but received %d(StreamData).\n", responseSize*readSizeMultiplier, recChars);
return -1;
}
//Checking for errors and getting data out of each StreamData
//response
for( m = 0; m < readSizeMultiplier; m++ )
{
totalPackets++;
checksumTotal = extendedChecksum16(recBuff + m*recBuffSize, recBuffSize);
if( (uint8)((checksumTotal / 256) & 0xFF) != recBuff[m*recBuffSize + 5] )
{
printf("Error : read buffer has bad checksum16(MSB) (StreamData).\n");
return -1;
}
if( (uint8)(checksumTotal & 0xFF) != recBuff[m*recBuffSize + 4] )
{
printf("Error : read buffer has bad checksum16(LBS) (StreamData).\n");
return -1;
}
checksumTotal = extendedChecksum8(recBuff + m*recBuffSize);
if( checksumTotal != recBuff[m*recBuffSize] )
{
printf("Error : read buffer has bad checksum8 (StreamData).\n");
return -1;
}
if( recBuff[m*recBuffSize + 1] != (uint8)(0xF9) ||
recBuff[m*recBuffSize + 2] != 4 + SamplesPerPacket ||
recBuff[m*recBuffSize + 3] != (uint8)(0xC0) )
{
printf("Error : read buffer has wrong command bytes (StreamData).\n");
return -1;
}
if( recBuff[m*recBuffSize + 11] == 59 )
{
if( !autoRecoveryOn )
{
printf("\nU3 data buffer overflow detected in packet %d.\nNow using auto-recovery and reading buffered samples.\n", totalPackets);
autoRecoveryOn = 1;
}
}
else if( recBuff[m*recBuffSize + 11] == 60 )
{
printf("Auto-recovery report in packet %d: %d scans were dropped.\nAuto-recovery is now off.\n", totalPackets, recBuff[m*recBuffSize + 6] + recBuff[m*recBuffSize + 7]*256);
autoRecoveryOn = 0;
}
else if( recBuff[m*recBuffSize + 11] != 0 )
{
printf("Errorcode # %d from StreamData read.\n", (unsigned int)recBuff[11]);
return -1;
}
if( packetCounter != (int)recBuff[m*recBuffSize + 10] )
{
printf("PacketCounter (%d) does not match with with current packet count (%d)(StreamData).\n", recBuff[m*recBuffSize + 10], packetCounter);
return -1;
}
backLog = (int)recBuff[m*48 + 12 + SamplesPerPacket*2];
for( k = 12; k < (12 + SamplesPerPacket*2); k += 2 )
{
voltageBytes = (uint16)recBuff[m*recBuffSize + k] + (uint16)recBuff[m*recBuffSize + k+1]*256;
if( hardwareVersion >= 1.30 )
getAinVoltCalibrated_hw130(caliInfo, currChannel, 31, voltageBytes, &(voltages[scanNumber][currChannel]));
else
getAinVoltCalibrated(caliInfo, isDAC1Enabled, 31, voltageBytes, &(voltages[scanNumber][currChannel]));
currChannel++;
if( currChannel >= NumChannels )
{
currChannel = 0;
scanNumber++;
}
}
if( packetCounter >= 255 )
packetCounter = 0;
else
packetCounter++;
}
}
printf("\nNumber of scans: %d\n", scanNumber);
printf("Total packets read: %d\n", totalPackets);
printf("Current PacketCounter: %d\n", ((packetCounter == 0) ? 255 : packetCounter-1));
printf("Current BackLog: %d\n", backLog);
for( k = 0; k < NumChannels; k++ )
printf(" AI%d: %.4f V\n",k, voltages[scanNumber - 1][k]);//remplacer [scanNumber - 1][1] par[scanNumber - 1][k]
ofstream datalabjack("/home/mahfoud/Bureau/CodeBlocks/labjackU3streaming/data.txt", ios::out | ios::trunc);
ofstream datalabjack2("/home/mahfoud/Bureau/CodeBlocks/labjackU3streaming/data2.txt", ios::out | ios::trunc);
for(int i=0;i<(SamplesPerPacket/NumChannels)*readSizeMultiplier*numReadsPerDisplay*numDisplay; i++){
datalabjack2 << voltages[i][1] << endl;
datalabjack << voltages[i][0] << endl;
}
datalabjack2.close();
datalabjack.close();
endTime = getTickCount();
printf("\nRate of samples: %.0lf samples per second\n", ((scanNumber*NumChannels) / ((endTime-startTime) / 1000.0)));
printf("Rate of scans: %.0lf scans per second\n\n", (scanNumber / ((endTime - startTime) / 1000.0)));
return 0;
}
</
code
>
The voltages array is too small, so you are going out of its bounds eventually causing the segmentation fault. Integer math is being performed to calculate the array size, so "SamplesPerPacket/NumChannels" is getting rounded down and causing the array to be too small.So try something like this instead for your voltages array size:
int voltagesSize = ((double)SamplesPerPacket/(double)NumChannels)*readSizeMultiplier*numReadsPerDisplay*numDisplay;
double voltages[voltagesSize][NumChannels];
Also, note if (SamplesPerPacket % NumChannels != 0), at the end of streaming your last scan may be incomplete since scans are going across multiple packets. So you may want to initialize your voltages values to something like -9999 to see when your samples stop, or read more scans than you actually want and don't use the last scans.
Regarding SamplesPerPacket, if it is under 25 (which makes the StreamData response packet less than 64 bytes) the readSizeMultiplier can only be 1 since you can only read one StreamData packet at a time now. That is why you got the error that your packet size was 62 since that is the size of a StreamData packet with 24 samples, and 310 is the size of 5 StreamData packets with 24 samples which is not possible.