467 lines
15 KiB
C
467 lines
15 KiB
C
//Author: LabJack
|
|
//April 17, 2012
|
|
//This example program reads analog inputs AI0-AI3 using stream mode.
|
|
|
|
#include "ue9.h"
|
|
#include <math.h>
|
|
#include <stdio.h>
|
|
|
|
int StreamConfig_example(HANDLE hDevice);
|
|
int StreamStart(HANDLE hDevice);
|
|
int StreamData_example(HANDLE hDevice, ue9CalibrationInfo *caliInfo);
|
|
int StreamStop(HANDLE hDevice);
|
|
int flushStream(HANDLE hDevice);
|
|
int doFlush(HANDLE hDevice);
|
|
|
|
const int AIN_RESOLUTION = 12;
|
|
const uint8 NUM_CHANNELS = 4; //Set this to a value between 1-16. Readings
|
|
//are performed on AIN channels 0-(NUM_CHANNELS-1).
|
|
|
|
int main(int argc, char **argv)
|
|
{
|
|
HANDLE hDevice;
|
|
ue9CalibrationInfo caliInfo;
|
|
|
|
//Opening first found UE9 over USB
|
|
if( (hDevice = openUSBConnection(-1)) == NULL )
|
|
goto done;
|
|
|
|
doFlush(hDevice);
|
|
|
|
//Getting calibration information from UE9
|
|
if( getCalibrationInfo(hDevice, &caliInfo) < 0 )
|
|
goto close;
|
|
|
|
if( StreamConfig_example(hDevice) != 0 )
|
|
goto close;
|
|
|
|
if( StreamStart(hDevice) != 0 )
|
|
goto close;
|
|
|
|
StreamData_example(hDevice, &caliInfo);
|
|
StreamStop(hDevice);
|
|
|
|
close:
|
|
closeUSBConnection(hDevice);
|
|
done:
|
|
return 0;
|
|
}
|
|
|
|
//Sends a StreamConfig low-level command to configure the stream to read only 4
|
|
//analog inputs (AI0 - AI3).
|
|
int StreamConfig_example(HANDLE hDevice)
|
|
{
|
|
int sendBuffSize;
|
|
sendBuffSize = 12 + 2*NUM_CHANNELS;
|
|
uint8 sendBuff[sendBuffSize], recBuff[8];
|
|
uint16 checksumTotal, scanInterval;
|
|
int sendChars, recChars, i;
|
|
|
|
sendBuff[1] = (uint8)(0xF8); //Command byte
|
|
sendBuff[2] = NUM_CHANNELS + 3; //Number of data words : NUM_CHANNELS + 3
|
|
sendBuff[3] = (uint8)(0x11); //Extended command number
|
|
sendBuff[6] = (uint8)NUM_CHANNELS; //NumChannels
|
|
sendBuff[7] = AIN_RESOLUTION; //Resolution
|
|
sendBuff[8] = 0; //SettlingTime = 0
|
|
sendBuff[9] = 0; //ScanConfig: scan pulse and external scan
|
|
//trigger disabled stream clock
|
|
//frequency = 4 MHz
|
|
|
|
scanInterval = 4000;
|
|
sendBuff[10] = (uint8)(scanInterval&0x00FF); //Scan interval (low byte)
|
|
sendBuff[11] = (uint8)(scanInterval/256); //Scan interval (high byte)
|
|
|
|
for( i = 0; i < NUM_CHANNELS; i++ )
|
|
{
|
|
sendBuff[12 + i*2] = i; //channel # = i
|
|
sendBuff[13 + i*2] = 0; //BipGain (Bip = unipolar, Gain = 1)
|
|
}
|
|
|
|
extendedChecksum(sendBuff, sendBuffSize);
|
|
|
|
//Sending command to UE9
|
|
sendChars = LJUSB_Write(hDevice, sendBuff, sendBuffSize);
|
|
if( sendChars < sendBuffSize )
|
|
{
|
|
if( sendChars == 0 )
|
|
printf("Error : write failed (StreamConfig).\n");
|
|
else
|
|
printf("Error : did not write all of the buffer (StreamConfig).\n");
|
|
return -1;
|
|
}
|
|
|
|
//Reading response from UE9
|
|
recChars = LJUSB_Read(hDevice, recBuff, 8);
|
|
if( recChars < 8 )
|
|
{
|
|
if( recChars == 0 )
|
|
printf("Error : read failed (StreamConfig).\n");
|
|
else
|
|
printf("Error : did not read all of the buffer (StreamConfig).\n");
|
|
return -1;
|
|
}
|
|
|
|
checksumTotal = extendedChecksum16(recBuff, 8);
|
|
if( (uint8)((checksumTotal / 256) & 0xff) != recBuff[5] )
|
|
{
|
|
printf("Error : read buffer has bad checksum16(MSB) (StreamConfig).\n");
|
|
return -1;
|
|
}
|
|
|
|
if( (uint8)(checksumTotal & 0xff) != recBuff[4] )
|
|
{
|
|
printf("Error : read buffer has bad checksum16(LSB) (StreamConfig).\n");
|
|
return -1;
|
|
}
|
|
|
|
if( extendedChecksum8(recBuff) != recBuff[0] )
|
|
{
|
|
printf("Error : read buffer has bad checksum8 (StreamConfig).\n");
|
|
return -1;
|
|
}
|
|
|
|
if( recBuff[1] != (uint8)(0xF8) || recBuff[2] != (uint8)(0x01) || recBuff[3] != (uint8)(0x11) )
|
|
{
|
|
printf("Error : read buffer has wrong command bytes (StreamConfig).\n");
|
|
return -1;
|
|
}
|
|
|
|
if( recBuff[6] != 0 )
|
|
{
|
|
printf("Errorcode # %d from StreamConfig read.\n", (unsigned int)recBuff[6]);
|
|
return -1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
//Sends a StreamStart low-level command to start streaming.
|
|
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 UE9
|
|
sendChars = LJUSB_Write(hDevice, sendBuff, 2);
|
|
if( sendChars < 2 )
|
|
{
|
|
if( sendChars == 0 )
|
|
printf("Error : write failed (StreamStart).\n");
|
|
else
|
|
printf("Error : did not write all of the buffer (StreamStart).\n");
|
|
return -1;
|
|
}
|
|
|
|
//Reading response from UE9
|
|
recChars = LJUSB_Read(hDevice, recBuff, 4);
|
|
if( recChars < 4 )
|
|
{
|
|
if( recChars == 0 )
|
|
printf("Error : read failed (StreamStart).\n");
|
|
else
|
|
printf("Error : did not read all of the buffer (StreamStart).\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) )
|
|
{
|
|
printf("Error : read buffer has wrong command byte (StreamStart).\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, ue9CalibrationInfo *caliInfo)
|
|
{
|
|
uint16 voltageBytes, checksumTotal;
|
|
int recChars, backLog, overflow;
|
|
int i, j, k, m, packetCounter, currChannel, scanNumber;
|
|
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 totalScans; //Total scans that will be read Meant for calculating the
|
|
//size of the voltages array.
|
|
long startTime, endTime;
|
|
|
|
packetCounter = 0;
|
|
currChannel = 0;
|
|
scanNumber = 0;
|
|
totalPackets = 0;
|
|
recChars = 0;
|
|
numDisplay = 6;
|
|
numReadsPerDisplay = 3;
|
|
readSizeMultiplier = 10;
|
|
|
|
/* Each StreamData response contains (16/NUM_CHANNELS) * readSizeMultiplier
|
|
* samples for each channel.
|
|
* Total number of scans = (16 / NUM_CHANNELS) * 4 * readSizeMultiplier * numReadsPerDisplay * numDisplay
|
|
*/
|
|
totalScans = ceil((16.0/NUM_CHANNELS)*4.0*readSizeMultiplier*numReadsPerDisplay*numDisplay);
|
|
double voltages[totalScans][NUM_CHANNELS];
|
|
uint8 recBuff[192*readSizeMultiplier];
|
|
|
|
printf("Reading Samples...\n");
|
|
|
|
startTime = getTickCount();
|
|
|
|
for( i = 0; i < numDisplay; i++ )
|
|
{
|
|
for( j = 0; j < numReadsPerDisplay; j++ )
|
|
{
|
|
/* For USB StreamData, use Endpoint 2 for reads and 192 byte
|
|
* packets instead of the 46. The 192 byte response is 4
|
|
* StreamData packet responses of 48 bytes.
|
|
* You can read the multiple StreamData responses of 192 bytes to
|
|
* help improve streaming performance. In this example this
|
|
* multiple is adjusted by the readSizeMultiplier variable.
|
|
*/
|
|
|
|
//Reading response from UE9
|
|
recChars = LJUSB_Stream(hDevice, recBuff, 192*readSizeMultiplier);
|
|
if( recChars < 192*readSizeMultiplier )
|
|
{
|
|
if( recChars == 0 )
|
|
printf("Error : read failed (StreamData).\n");
|
|
else
|
|
printf("Error : did not read all of the buffer %d (StreamData).\n", recChars);
|
|
return -1;
|
|
}
|
|
|
|
overflow = 0;
|
|
|
|
//Checking for errors and getting data out of each StreamData response
|
|
for( m = 0; m < 4*readSizeMultiplier; m++ )
|
|
{
|
|
totalPackets++;
|
|
checksumTotal = extendedChecksum16(recBuff + m*48, 46);
|
|
if( (uint8)((checksumTotal >> 8) & 0xff) != recBuff[m*48 + 5] )
|
|
{
|
|
printf("Error : read buffer has bad checksum16(MSB) (StreamData).\n");
|
|
return -1;
|
|
}
|
|
|
|
if( (uint8)(checksumTotal & 0xff) != recBuff[m*48 + 4] )
|
|
{
|
|
printf("Error : read buffer has bad checksum16(LSB) (StreamData).\n");
|
|
return -1;
|
|
}
|
|
|
|
checksumTotal = extendedChecksum8(recBuff + m*48);
|
|
if( checksumTotal != recBuff[m*48] )
|
|
{
|
|
printf("Error : read buffer has bad checksum8 (StreamData).\n");
|
|
return -1;
|
|
}
|
|
|
|
if( recBuff[m*48 + 1] != (uint8)(0xF9) || recBuff[m*48 + 2] != (uint8)(0x14) || recBuff[m*48 + 3] != (uint8)(0xC0) )
|
|
{
|
|
printf("Error : read buffer has wrong command bytes (StreamData).\n");
|
|
return -1;
|
|
}
|
|
|
|
if( recBuff[m*48 + 11] != 0 )
|
|
{
|
|
printf("Errorcode # %d from StreamData read.\n", (unsigned int)recBuff[11]);
|
|
return -1;
|
|
}
|
|
|
|
if( packetCounter != (int) recBuff[m*48 + 10] )
|
|
{
|
|
printf("PacketCounter does not match with with current packet count (StreamData).\n");
|
|
return -1;
|
|
}
|
|
|
|
backLog = recBuff[m*48 + 45]&0x7F;
|
|
|
|
//Checking MSB for Comm buffer overflow
|
|
if( (recBuff[m*48 + 45] & 128) == 128 )
|
|
{
|
|
printf("\nComm buffer overflow detected in packet %d\n", totalPackets);
|
|
printf("Current Comm backlog: %d\n", recBuff[m*48 + 45]&0x7F);
|
|
overflow = 1;
|
|
}
|
|
|
|
for( k = 12; k < 43; k += 2 )
|
|
{
|
|
voltageBytes = (uint16)recBuff[m*48 + k] + (uint16)recBuff[m*48 + k+1]*256;
|
|
getAinVoltCalibrated(caliInfo, (uint8)(0x00), AIN_RESOLUTION, voltageBytes, &(voltages[scanNumber][currChannel]));
|
|
currChannel++;
|
|
if( currChannel >= NUM_CHANNELS )
|
|
{
|
|
currChannel = 0;
|
|
scanNumber++;
|
|
}
|
|
}
|
|
|
|
if( packetCounter >= 255 )
|
|
packetCounter = 0;
|
|
else
|
|
packetCounter++;
|
|
|
|
//Handle Comm buffer overflow by stopping, flushing and restarting stream
|
|
if( overflow == 1 )
|
|
{
|
|
printf("\nRestarting stream...\n");
|
|
doFlush(hDevice);
|
|
if( StreamConfig_example(hDevice) != 0 )
|
|
{
|
|
printf("Error restarting StreamConfig.\n");
|
|
return -1;
|
|
}
|
|
|
|
if( StreamStart(hDevice) != 0 )
|
|
{
|
|
printf("Error restarting StreamStart.\n");
|
|
return -1;
|
|
}
|
|
packetCounter = 0;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
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 Comm backlog: %d\n", backLog);
|
|
|
|
for( k = 0; k < NUM_CHANNELS; k++ )
|
|
printf(" AIN%d: %.4f V\n", k, voltages[scanNumber - 1][k]);
|
|
}
|
|
|
|
endTime = getTickCount();
|
|
printf("\nRate of samples: %.0lf samples per second\n", (scanNumber*NUM_CHANNELS)/((endTime - startTime)/1000.0));
|
|
printf("Rate of scans: %.0lf scans per second\n\n", scanNumber/((endTime - startTime)/1000.0));
|
|
|
|
return 0;
|
|
}
|
|
|
|
//Sends a StreamStop low-level command to stop streaming.
|
|
int StreamStop(HANDLE hDevice)
|
|
{
|
|
uint8 sendBuff[2], recBuff[4];
|
|
int sendChars, recChars;
|
|
|
|
sendBuff[0] = (uint8)(0xB0); //CheckSum8
|
|
sendBuff[1] = (uint8)(0xB0); //Command byte
|
|
|
|
//Sending command to UE9
|
|
sendChars = LJUSB_Write(hDevice, sendBuff, 2);
|
|
if( sendChars < 2 )
|
|
{
|
|
if( sendChars == 0 )
|
|
printf("Error : write failed (StreamStop).\n");
|
|
else
|
|
printf("Error : did not write all of the buffer (StreamStop).\n");
|
|
return -1;
|
|
}
|
|
|
|
//Reading response from UE9
|
|
recChars = LJUSB_Read(hDevice, recBuff, 4);
|
|
if( recChars < 4 )
|
|
{
|
|
if( recChars == 0 )
|
|
printf("Error : read failed (StreamStop).\n");
|
|
else
|
|
printf("Error : did not read all of the buffer (StreamStop).\n");
|
|
return -1;
|
|
}
|
|
|
|
if( normalChecksum8(recBuff, 4) != recBuff[0] )
|
|
{
|
|
printf("Error : read buffer has bad checksum8 (StreamStop).\n");
|
|
return -1;
|
|
}
|
|
|
|
if( recBuff[1] != (uint8)(0xB1) )
|
|
{
|
|
printf("Error : read buffer has wrong command byte (StreamStop).\n");
|
|
return -1;
|
|
}
|
|
|
|
if( recBuff[2] != 0 )
|
|
{
|
|
printf("Errorcode # %d from StreamStop read.\n", (unsigned int)recBuff[2]);
|
|
return -1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
//Sends a FlushBuffer low-level command to clear the stream buffer.
|
|
int flushStream(HANDLE hDevice)
|
|
{
|
|
uint8 sendBuff[2], recBuff[2];
|
|
int sendChars, recChars;
|
|
|
|
sendBuff[0] = (uint8)(0x08); //CheckSum8
|
|
sendBuff[1] = (uint8)(0x08); //Command byte
|
|
|
|
//Sending command to UE9
|
|
sendChars = LJUSB_Write(hDevice, sendBuff, 2);
|
|
if( sendChars < 2 )
|
|
{
|
|
if( sendChars == 0 )
|
|
printf("Error : write failed (flushStream).\n");
|
|
else
|
|
printf("Error : did not write all of the buffer (flushStream).\n");
|
|
return -1;
|
|
}
|
|
|
|
//Reading response from UE9
|
|
recChars = LJUSB_Read(hDevice, recBuff, 2);
|
|
if( recChars < 2 )
|
|
{
|
|
if( recChars == 0 )
|
|
printf("Error : read failed (flushStream).\n");
|
|
else
|
|
printf("Error : did not read all of the buffer (flushStream).\n");
|
|
return -1;
|
|
}
|
|
|
|
if( recBuff[0] != (uint8)(0x08) || recBuff[1] != (uint8)(0x08) )
|
|
{
|
|
printf("Error : read buffer has wrong command byte (flushStream).\n");
|
|
return -1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
//Runs StreamStop and flushStream low-level functions to flush out the
|
|
//streaming buffer. Also reads 128 bytes from streaming endpoint to clear any
|
|
//left over data. If there is nothing to read from the streaming endpoint,
|
|
//then there will be a timeout delay. This function is useful for stopping
|
|
//streaming and clearing it after a Comm buffer overflow.
|
|
int doFlush(HANDLE hDevice)
|
|
{
|
|
uint8 recBuff[192];
|
|
|
|
printf("Flushing stream and reading left over data.\n");
|
|
StreamStop(hDevice);
|
|
flushStream(hDevice);
|
|
LJUSB_Stream(hDevice, recBuff, 192);
|
|
|
|
return 0;
|
|
}
|