//--------------------------------------------------------------------------- // // simplestream.c // // 2-channel stream on the U3. // // support@labjack.com // Jul 21, 2008 //---------------------------------------------------------------------- // // adapted to use timers instead of analogue inputs #include #include #include //#include "c:\program files\labjack\drivers\LabJackUD.h" #include "C:\Program Files (x86)\LabJack\Drivers\LabJackUD.h" //The project must also know where to find labjackud.lib. Here we do //that by putting the lib file in the file view to the left. The relative //path stored by Visual Studio might not be the same on your machine, so //you will probably have to delete the lib in the file view and right-click //to re-add it from the install location ...\labjack\drivers\labjackud.lib. //Another option, besides using the .lib, is dynamic linking. Some //compilers might not be able to link the .lib, and dynamic linking //is usually the solution in those cases. //This is our simple error handling function that is called after every UD //function call. This function displays the errorcode and string description //of the error. It also has a line number input that can be used with the //macro __LINE__ to display the line number in source code that called the //error handler. It also has an iteration input is useful when processing //results in a loop (getfirst/getnext). void ErrorHandler (LJ_ERROR lngErrorcode, long lngLineNumber, long lngIteration) { char err[255]; if (lngErrorcode != LJE_NOERROR) { ErrorToString(lngErrorcode,err); printf("Error number = %d\n",lngErrorcode); printf("Error string = %s\n",err); printf("Source line number = %d\n",lngLineNumber); printf("Iteration = %d\n\n",lngIteration); if(lngErrorcode > LJE_MIN_GROUP_ERROR) { //Quit if this is a group error. getchar(); exit(0); } } } main() { LJ_ERROR lngErrorcode; LJ_HANDLE lngHandle=0; long lngGetNextIteration; long i=0,k=0; long pulseCount=0, p=0; long lngIOType=0, lngChannel=0; double dblValue=0, dblCommBacklog=0; double scanRate = 1000; long delayms = 1000; long numberOfPulses = 4; double numScans = 2000; //2x the expected # of scans (2*scanRate*delayms/1000) double numScansRequested; double adblData[4000] = {0}; //Max buffer size (#channels*numScansRequested) //Make a long parameter which holds the address of the data array. We do this //so the compiler does not generate a warning in the eGet call that retrieves //stream data. Note that the x1 parameter in eGet (and AddRequest) is fairly //generic, in that sometimes it could just be a write parameter, and sometimes //it has the address of an array. Since x1 is not declared as a pointer, the //compiler will complain if you just pass the array pointer without casting //it to a long as follows. long padblData = (long)&adblData[0]; //Read and display the UD version. dblValue = GetDriverVersion(); printf("UD Driver Version = %.3f\n\n",dblValue); //Open the first found LabJack U3. lngErrorcode = OpenLabJack (LJ_dtU3, LJ_ctUSB, "1", 1, &lngHandle); ErrorHandler(lngErrorcode, __LINE__, 0); //Read and display the hardware version of this U3. lngErrorcode = eGet (lngHandle, LJ_ioGET_CONFIG, LJ_chHARDWARE_VERSION, &dblValue, 0); printf("U3 Hardware Version = %.3f\n\n",dblValue); ErrorHandler(lngErrorcode, __LINE__, 0); //Read and display the firmware version of this U3. lngErrorcode = eGet (lngHandle, LJ_ioGET_CONFIG, LJ_chFIRMWARE_VERSION, &dblValue, 0); printf("U3 Firmware Version = %.3f\n\n",dblValue); ErrorHandler(lngErrorcode, __LINE__, 0); //Start by using the pin_configuration_reset IOType so that all //pin assignments are in the factory default condition. lngErrorcode = ePut (lngHandle, LJ_ioPIN_CONFIGURATION_RESET, 0, 0, 0); ErrorHandler(lngErrorcode, __LINE__, 0); // new timer config //Set the timer/counter pin offset to 4, which will put the first //timer/counter on FIO4. lngErrorcode = AddRequest (lngHandle, LJ_ioPUT_CONFIG, LJ_chTIMER_COUNTER_PIN_OFFSET, 4, 0, 0); ErrorHandler(lngErrorcode, __LINE__, 0); //Use the 48 MHz timer clock base with divider. Since we are using clock with divisor //support, Counter0 is not available. lngErrorcode = AddRequest(lngHandle, LJ_ioPUT_CONFIG, LJ_chTIMER_CLOCK_BASE, LJ_tc48MHZ_DIV, 0, 0); //lngErrorcode = AddRequest(lngHandle, LJ_ioPUT_CONFIG, LJ_chTIMER_CLOCK_BASE, LJ_tc24MHZ_DIV, 0, 0); //Use this line instead for hardware rev 1.20. ErrorHandler(lngErrorcode, __LINE__, 0); //Set the divisor to 48 so the actual timer clock is 1 MHz. lngErrorcode = AddRequest(lngHandle, LJ_ioPUT_CONFIG, LJ_chTIMER_CLOCK_DIVISOR, 48, 0, 0); //lngErrorcode = AddRequest(lngHandle, LJ_ioPUT_CONFIG, LJ_chTIMER_CLOCK_DIVISOR, 24, 0, 0); //Use this line instead for hardware rev 1.20. ErrorHandler(lngErrorcode, __LINE__, 0); //Enable 1 timer. It will use FIO4. lngErrorcode = AddRequest(lngHandle, LJ_ioPUT_CONFIG, LJ_chNUMBER_TIMERS_ENABLED, 1, 0, 0); ErrorHandler(lngErrorcode, __LINE__, 0); // Enable timer 32-bit rising to rising edge measurement LJ_tmRISINGEDGES32 lngErrorcode = AddRequest(lngHandle, LJ_ioPUT_TIMER_MODE, 0, LJ_tmRISINGEDGES32, 0, 0); ErrorHandler(lngErrorcode, __LINE__, 0); //Configure FIO0 and FIO1 as analog, all else as digital. That means we //will start from channel 0 and update all 16 flexible bits. We will //pass a value of b0000000000000011 or d3. //lngErrorcode = ePut (lngHandle, LJ_ioPUT_ANALOG_ENABLE_PORT, 0, 3, 16); //ErrorHandler(lngErrorcode, __LINE__, 0); //Configure the stream: //Set the scan rate. lngErrorcode = AddRequest(lngHandle, LJ_ioPUT_CONFIG, LJ_chSTREAM_SCAN_FREQUENCY, scanRate, 0, 0); ErrorHandler(lngErrorcode, __LINE__, 0); //Give the driver a 5 second buffer (scanRate * 2 channels * 5 seconds). lngErrorcode = AddRequest(lngHandle, LJ_ioPUT_CONFIG, LJ_chSTREAM_BUFFER_SIZE, scanRate*2*5, 0, 0); ErrorHandler(lngErrorcode, __LINE__, 0); //Configure reads to retrieve whatever data is available without waiting (wait mode LJ_swNONE). //See comments below to change this program to use LJ_swSLEEP mode. lngErrorcode = AddRequest(lngHandle, LJ_ioPUT_CONFIG, LJ_chSTREAM_WAIT_MODE, LJ_swNONE, 0, 0); ErrorHandler(lngErrorcode, __LINE__, 0); //Define the scan list as AIN0 then AIN1. lngErrorcode = AddRequest(lngHandle, LJ_ioCLEAR_STREAM_CHANNELS, 0, 0, 0, 0); //ErrorHandler(lngErrorcode, __LINE__, 0); //lngErrorcode = AddRequest(lngHandle, LJ_ioADD_STREAM_CHANNEL, 0, 0, 0, 0); // first method for single ended reading - AIN0 //ErrorHandler(lngErrorcode, __LINE__, 0); //lngErrorcode = AddRequest(lngHandle, LJ_ioADD_STREAM_CHANNEL_DIFF, 1, 0, 32, 0); // second method for single ended reading - AIN1 //ErrorHandler(lngErrorcode, __LINE__, 0); ErrorHandler(lngErrorcode, __LINE__, 0); lngErrorcode = AddRequest(lngHandle, LJ_ioADD_STREAM_CHANNEL, 230, 0, 0, 0); ErrorHandler(lngErrorcode, __LINE__, 0); lngErrorcode = AddRequest(lngHandle, LJ_ioADD_STREAM_CHANNEL, 224, 0, 0, 0); ErrorHandler(lngErrorcode, __LINE__, 0); //Execute the list of requests. lngErrorcode = GoOne(lngHandle); ErrorHandler(lngErrorcode, __LINE__, 0); //Get all the results just to check for errors. lngErrorcode = GetFirstResult(lngHandle, &lngIOType, &lngChannel, &dblValue, 0, 0); ErrorHandler(lngErrorcode, __LINE__, 0); lngGetNextIteration=0; //Used by the error handling function. while(lngErrorcode < LJE_MIN_GROUP_ERROR) { lngErrorcode = GetNextResult(lngHandle, &lngIOType, &lngChannel, &dblValue, 0, 0); if(lngErrorcode != LJE_NO_MORE_DATA_AVAILABLE) { ErrorHandler(lngErrorcode, __LINE__, lngGetNextIteration); } lngGetNextIteration++; } //Start the stream. lngErrorcode = eGet(lngHandle, LJ_ioSTART_STREAM, 0, &dblValue, 0); ErrorHandler(lngErrorcode, __LINE__, 0); //The actual scan rate is dependent on how the desired scan rate divides into //the LabJack clock. The actual scan rate is returned in the value parameter //from the start stream command. printf("Actual Scan Rate = %.3f\n",dblValue); printf("Actual Sample Rate = %.3f\n",2*dblValue); lngErrorcode = ePut(lngHandle, LJ_ioPUT_DIGITAL_BIT, 5, 0, 0); ErrorHandler(lngErrorcode, __LINE__, 0); //Read data while(!kbhit()) //Loop will run until any key is hit { //Since we are using wait mode LJ_swNONE, we will wait a little, then //read however much data is available. Thus this delay will control how //fast the program loops and how much data is read each loop. An //alternative common method is to use wait mode LJ_swSLEEP where the //stream read waits for a certain number of scans. In such a case //you would not have a delay here, since the stream read will actually //control how fast the program loops. // //To change this program to use sleep mode, // -change numScans to the actual number of scans desired per read, // -change wait mode addrequest value to LJ_swSLEEP, // -comment out the following Sleep command. for (p = 0; p < numberOfPulses; p++) { Sleep(delayms/numberOfPulses); //Remove if using LJ_swSLEEP. lngErrorcode = ePut(lngHandle, LJ_ioPUT_DIGITAL_BIT, 5, 1, 0); Sleep(2); lngErrorcode = ePut(lngHandle, LJ_ioPUT_DIGITAL_BIT, 5, 0, 0); pulseCount++; } //numberOfPulses = numberOfPulses * 2; //init array so we can easily tell if it has changed for(k=0;k 0) { printf("First scan = %.3f, %.3f\n",adblData[k],adblData[k+1]); } //adblData[k] = 99999.0; } ErrorHandler(lngErrorcode, __LINE__, 0); //Retrieve the current backlog. The UD driver retrieves stream data from //the U3 in the background, but if the computer is too slow for some reason //the driver might not be able to read the data as fast as the U3 is //acquiring it, and thus there will be data left over in the U3 buffer. lngErrorcode = eGet(lngHandle, LJ_ioGET_CONFIG, LJ_chSTREAM_BACKLOG_COMM, &dblCommBacklog, 0); printf("Comm Backlog = %.0f\n",dblCommBacklog); i++; } //Stop the stream lngErrorcode = eGet(lngHandle, LJ_ioSTOP_STREAM, 0, 0, 0); ErrorHandler(lngErrorcode, __LINE__, 0); printf("\nDone"); getchar(); return 0; }