0% found this document useful (0 votes)
105 views

LabJack MSVC++ v1.4

This document provides instructions for accessing a LabJack device from a C program using Microsoft Visual C/C++. It describes how to create a new C project, add necessary header files and error handling functions, establish communication with the LabJack, configure I/O channels for digital or analog operation, and includes an example program.

Uploaded by

Nathen Upperman
Copyright
© Attribution Non-Commercial (BY-NC)
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
105 views

LabJack MSVC++ v1.4

This document provides instructions for accessing a LabJack device from a C program using Microsoft Visual C/C++. It describes how to create a new C project, add necessary header files and error handling functions, establish communication with the LabJack, configure I/O channels for digital or analog operation, and includes an example program.

Uploaded by

Nathen Upperman
Copyright
© Attribution Non-Commercial (BY-NC)
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 38

LabJack MS Visual C/C++ Programming Guide Version 1.

4
ECE 103 Engineering Programming Portland State University Phillip Wong

Credits: LabJack Corporation Original source code & technical information

ECE Department Portland State University

Version 1.4

How to Access the LabJack Using MS Visual C/C++


INTRODUCTION
To access a LabJack from a C program (Microsoft Visual C/C++), these steps are necessary: 1. Create a new C project file 2. Add startup code to the C program 3. Establish communications with the LabJack 4. Configure the I/O channels 5. Initiate an I/O command

STEP 1: Create a New C Project


Follow this procedure when creating the project for the first time. 1. Start either Visual Studio 2008 or Visual C++ 2008 Express. 2. The Start Page window will appear. If the Solution Explorer pane is not visible, select View > Solution Explorer from the menu bar. Select File > New > Project from the menu bar.

3. The New Project window will pop-up. In the Project types section under the type Visual C++, select Win32. In the Templates section under Visual Studio installed templates, select Win32 Console Application. In the Name input box, enter a name you would like to use for your application. In the Location input box, enter a directory where you would like to save your application. Click [OK].

4. The Win32 Application Wizard window will pop-up. Click [Next]. On the left-side of the wizard window, select Application Settings. Under Application type, select Console application. Under Additional options: o UNCHECK Precompiled header o CHECK Empty project Click [Finish].

ECE Department Portland State University

Version 1.4

5. The Solution Explorer pane will show your newly created application. There should be three folders visible: Header Files, Resource Files, and Source Files. Right-click the Source Files folder in the solution explorer. A pop-up menu will appear. Select Add > New Item from the pop-up menu.

6. The Add New Item window will pop-up. In the Categories section under Visual C++, select Code. In the Templates section, select C++ File (.cpp). Note: Dont worry that you chose .cpp instead of .c. This is fixed in the next step. In the Name input box, enter a filename with a .c extension (e.g., program.c). Click [Add]

If the file is successfully added, you will see the name of the newly created file inside the Source Files folder. 7. The last step is to add a link to the actual LabJack code library to the project. Right-click the Project name in the solution explorer. A pop-up menu will appear. Select Add > Existing Item from the pop-up menu.

8. The Add Existing Item window will pop-up. Using the pop-up windows browser, navigate to and select the following file:
C:\Program Files\LabJack\Drivers\labjackud.lib

Note: If your Windows profile is configured not to show known filename extensions, then the library file will be displayed as just labjackud in the browser. Click [Add] A message will appear and ask if you want to create a new rule file. Click [No].

If the file is successfully added, you will see its name below (not inside) the Source Files folder.

Once the project and source files have been created, they will exist until you manually delete them. If you want to work on a pre-existing project, just open the project by selecting File > Open > Project/Solution from the menu bar.

ECE Department Portland State University

Version 1.4

STEP 2: Add Startup Code to the C Program


Add these header files at the beginning of each C program or module:
#include <stdio.h> #include <stdlib.h> #include "c:\program files\labjack\drivers\LabJackUD.h"

The files contain the declarations needed to access the LabJack system. Add the following function before any other function definition:
void ErrorHandler (LJ_ERROR lngErrorcode, long lngLineNumber) { char err[255]; if (lngErrorcode != LJE_NOERROR) { ErrorToString(lngErrorcode, err); printf("Error # %d: %s\n", lngErrorcode, err); printf("Source line number = %d\n", lngLineNumber); if(lngErrorcode > LJE_MIN_GROUP_ERROR) { getchar(); exit(0); /* Quit if serious error. */ } } }

After calling a LabJack library function, this function is used to display error information. Note: You could add this function after your other function definitions, as long as you remember to insert a prototype for ErrorHandler at the top of the source file. Add the following variable declarations at the start of the main() function:
LJ_ERROR lngErrorcode; /* LabJack error code */ LJ_HANDLE lngHandle = 0; /* ID# assigned to the opened LabJack */

These variables are used by various LabJack library functions.

ECE Department Portland State University

Version 1.4

STEP 3: Establish Communications with the LabJack


Add the following function calls at the start of the main() function:
/* Open the first found LabJack U3 */

lngErrorcode = OpenLabJack (LJ_dtU3, LJ_ctUSB, "1", 1, &lngHandle); ErrorHandler(lngErrorcode, __LINE__);

The purpose of each line is described here: lngErrorcode = OpenLabJack (LJ_dtU3, LJ_ctUSB, "1", 1, &lngHandle); This searches for a LabJack device that may be attached to the computer. If it finds one, then an attempt is made to establish contact with the LabJack hardware. Arguments: LJ_dtU3, LJ_ctUSB, 1, 1 : These values make the function search for a LabJack U3 that is attached to the computer through a USB cable. lngHandle : The unique ID number assigned to the opened LabJack is passed back Returns: lngErrorcode : A numeric error code. Note: Multiple LabJack devices can be attached to the same PC. Each opened LabJack is assigned its own identification number. lngHandle can be passed as an argument to other LabJack functions such as ePut to indicate the specific LabJack you want to control. ErrorHandler (lngErrorcode, __LINE__); This displays an error message that corresponds to the passed error code. If no error occurred, then no message is displayed. If the error is serious enough, then ErrorHandler will terminate the program. Arguments: lngErrorcode : Numeric error code. __LINE__ : This is a pre-defined macro (two underscores, LINE, two underscores). Returns: nothing

ECE Department Portland State University

Version 1.4

Example (Complete Program):


/* ECE 103 Engineering Programming */ /* Bare minimum setup code for interfacing */ /* a Visual C/C++ program to a LabJack. */ #include <stdio.h> #include <stdlib.h> #include "c:\program files\labjack\drivers\LabJackUD.h" /* ErrorHandler code was written by the LabJack company */ void ErrorHandler (LJ_ERROR lngErrorcode, long lngLineNumber) { char err[255]; if (lngErrorcode != LJE_NOERROR) { ErrorToString(lngErrorcode, err); printf("Error # %d: %s\n", lngErrorcode, err); printf("Source line number = %d\n", lngLineNumber); if(lngErrorcode > LJE_MIN_GROUP_ERROR) { getchar(); exit(0); /* Quit if serious error. */ } } } int main (void) { LJ_ERROR lngErrorcode; /* LabJack error code */ LJ_HANDLE lngHandle = 0; /* ID# assigned to the opened LabJack */ /* Open the first found LabJack U3 */ lngErrorcode = OpenLabJack (LJ_dtU3, LJ_ctUSB, "1", 1, ErrorHandler(lngErrorcode, __LINE__);

&lngHandle);

/* CONFIGURATION OF I/O CHANNELS GOES HERE */ /* AFTER THAT COMES YOUR OWN LABJACK CODE */

return 0; }

Note: In the rest of this tutorial, the following LabJack library functions are used: ePut() : This sends values to the LabJack device. eGet() : This reads values from the LabJack device.

ECE Department Portland State University

Version 1.4

STEP 4: Configure the I/O Channels for Digital or Analog Operation


A LabJack has multiple input and output (I/O) channels. Some channels are flexible and can be configured as either digital I/O or analog input. Other channels are dedicated to a single task.
LabJack Model Flexible Digital I/O or Analog Input Dedicated Digital I/O Dedicated Analog Input Dedicated Analog Output

U3-LV U3-HV
Bit# 0 1 2 3 4 5 6 7

FIO0 FIO7, EIO0 EIO7 FIO4 FIO7, EIO0 EIO7


Channel FIO0 or AIN0 FIO1 or AIN1 FIO2 or AIN2 FIO3 or AIN3 FIO4 FIO5 FIO6 FIO7 Bit# 8 9 10 11 12 13 14 15

CIO0 CIO3 CIO0 CIO3


Channel EIO0 EIO1 EIO2 EIO3 EIO4 EIO5 EIO6 EIO7

none AIN0 AIN3


Bit# 16 17 18 19

DAC0, DAC1 DAC0, DAC1


Channel CIO0 CIO1 CIO2 CIO3

Add the following lines of code to your C program (e.g., in the main() function):
/* Set all pin assignments to the factory default condition */ lngErrorcode = ePut(lngHandle, LJ_ioPIN_CONFIGURATION_RESET, 0, 0, 0); ErrorHandler(lngErrorcode, __LINE__);

The purpose of each line is described here: lngErrorcode = ePut (lngHandle, LJ_ioPIN_CONFIGURATION_RESET, 0, 0, 0); This resets the I/O channels to their factory default configuration. Arguments: The given values will set all available flexible I/O channels for digital operation. Returns: lngErrorcode : Numeric error code. If all you need are digital I/O channels, then I/O configuration is complete. However, if you require analog input channels, then additional procedures may be needed.

ECE Department Portland State University

Version 1.4

To set an individual flexible I/O channel for analog input: lngErrorcode = ePut (lngHandle, LJ_ioPUT_ANALOG_ENABLE_BIT, Bit#, State, 0); If State is true (1), the channel corresponding to Bit# is set to analog input. If State is false (0), the channel is set to digital I/O. No other channels are changed. Example: Set FIO0, FIO5, and FIO6 for analog input.
/* For FIO0, set Bit# to 0. To enable analog input, set State to 1. */ lngErrorcode = ePut(lngHandle, LJ_ioPUT_ANALOG_ENABLE_BIT, 0, 1, 0); ErrorHandler(lngErrorcode, __LINE__); /* For FIO5, set Bit# to 5. To enable analog input, set State to 1. */ lngErrorcode = ePut(lngHandle, LJ_ioPUT_ANALOG_ENABLE_BIT, 5, 1, 0); ErrorHandler(lngErrorcode, __LINE__); /* For FIO6, set Bit# to 6. To enable analog input, set State to 1. */ lngErrorcode = ePut(lngHandle, LJ_ioPUT_ANALOG_ENABLE_BIT, 6, 1, 0); ErrorHandler(lngErrorcode, __LINE__);

Set FIO5 back to digital I/O (i.e., disable analog input).


/* For FIO5, set Bit# to 5. To disable analog input, set State to 0. */ lngErrorcode = ePut(lngHandle, LJ_ioPUT_ANALOG_ENABLE_BIT, 5, 0, 0); ErrorHandler(lngErrorcode, __LINE__);

To set a group of flexible I/O channels for analog input all at once:
lngErrorcode = ePut (lngHandle, LJ_ioPUT_ANALOG_ENABLE_PORT, StartBit, Settings, NumBits);

For typical programs, set StartBit = 0 and NumBits = 16. Next, define a binary number that represents which channels you want to use for analog input. A bit value of 1 is analog, while a bit value of 0 is digital. The Settings argument is the decimal version of the binary number.
EIO7 15 14 EIO0 FIO7 8 7 FIO0 0 Bit

13

12

11

10

MSB

LSB

Example: Set FIO0, FIO5, and FIO6 for analog input. All other available channels are digital.
/* FIO0 is bit 0, FIO5 is bit 5, FIO6 is bit 6 */ /* Settings = 0000000001100001 (binary) = 97 (decimal) */ lngErrorcode = ePut(lngHandle, LJ_ioPUT_ANALOG_ENABLE_PORT, 0, 97, 16); ErrorHandler(lngErrorcode);

ECE Department Portland State University

Version 1.4

STEP 5: Initiate an I/O Command


At this point, the LabJack should be properly configured for analog and/or digital operations. The basic commands for writing and reading data on the LabJack are: Writing to a digital output channel: lngErrorcode = ePut (lngHandle, LJ_ioPUT_DIGITAL_BIT, Bit#, WriteVal, 0); If WriteVal is set to true (1), the channel corresponding to Bit# outputs a logic high (+ V). If WriteVal is set to false (0), the channel outputs a logic low (0 V). Bit# is type long int. WriteVal is type double. Allowed ranges: Bit# = 0 to 19, WriteVal = 0 or 1 Reading from a digital input channel: lngErrorcode = eGet (lngHandle, LJ_ioGET_DIGITAL_BIT, Bit#, &ReadVal, 0); If ReadVal is true (1), the channel corresponding to Bit# is sensing a logic high. If ReadVal is false (0), the channel is sensing a logic low. Bit# is type long int. ReadVal is type double (&ReadVal is the address of ReadVal). Allowed ranges: Bit# = 0 to 19

Writing to an analog output channel (DAC): lngErrorcode = ePut (lngHandle, LJ_ioPUT_DAC, DAC#, WriteVal, 0); The channel corresponding to DAC# outputs a voltage that is an analog representation of the value stored in WriteVal. DAC# is type long int. WriteVal is type double. Allowed ranges: DAC# = 0 or 1, 0 WriteVal 5 (floating point) Reading from an analog input channel (AIN): lngErrorcode = eGet (lngHandle, LJ_ioGET_AIN, AIN#, &ReadVal, 0); The channel corresponding to AIN# is read and the digital representation of the analog input is passed back in ReadVal. AIN# is type long int. ReadVal is type double (&ReadVal is the address of ReadVal). Allowed ranges: AIN# = 0 to 15

ECE Department Portland State University

Version 1.4

Example: Set digital output channel FIO7 to logic high.


/* For FIO7, set Bit# to 7 */ lngErrorcode = ePut(lngHandle, LJ_ioPUT_DIGITAL_BIT, 7, 1, 0); ErrorHandler(lngErrorcode, __LINE__);

Set digital output channel FIO7 to logic low.


/* For FIO7, set Bit# to 7 */ lngErrorcode = ePut(lngHandle, LJ_ioPUT_DIGITAL_BIT, 7, 0, 0); ErrorHandler(lngErrorcode, __LINE__);

Read state of digital input channel EIO2.


/* For EIO2, set Bit# to 10 */ lngErrorcode = eGet(lngHandle, LJ_ioGET_DIGITAL_BIT, 10, &EIO_State, 0); ErrorHandler(lngErrorcode, __LINE__);

Set analog output channel DAC0 to 1.25 V.


/* For DAC0, set DAC# to 0 */ lngErrorcode = ePut(lngHandle, LJ_ioPUT_DAC, 0, 1.25, 0); ErrorHandler(lngErrorcode, __LINE__);

Read analog input channel AIN5 (= FIO5).


/* For AIN5, set AIN# to 5 */ lngErrorcode = eGet(lngHandle, LJ_ioGET_AIN, 5, &AIN_Value, 0); ErrorHandler(lngErrorcode, __LINE__);

ECE Department Portland State University

Version 1.4

Example (Complete Program Digital I/O):


/* --------------------------------------------------------------------This program sets a single digital output channel based on user input and reads a single digital input channel. Connect a wire from FIO4 to FIO5. The program will return the value you set FIO4 to as FIO5. --------------------------------------------------------------------- */ #include <stdio.h> #include <stdlib.h> #include "c:\program files\labjack\drivers\LabJackUD.h" /* ErrorHandler code was written by the LabJack company */ void ErrorHandler (LJ_ERROR lngErrorcode, long lngLineNumber) { char err[255]; if (lngErrorcode != LJE_NOERROR) { ErrorToString(lngErrorcode, err); printf("Error # %d: %s\n", lngErrorcode, err); printf("Source line number = %d\n", lngLineNumber); if(lngErrorcode > LJE_MIN_GROUP_ERROR) { getchar(); exit(0); /* Quit if serious error. */ } } } int main (void) { LJ_ERROR lngErrorcode; LJ_HANDLE lngHandle = 0; double WriteVal, ReadVal;

/* LabJack error code */ /* ID# assigned to the opened LabJack */ /* FIO values */

/* Open the first found LabJack U3 */ lngErrorcode = OpenLabJack(LJ_dtU3, LJ_ctUSB, "1", 1, ErrorHandler(lngErrorcode, __LINE__);

&lngHandle);

/* Set all pin assignments to the factory default condition */ lngErrorcode = ePut(lngHandle, LJ_ioPIN_CONFIGURATION_RESET, 0, 0, 0); ErrorHandler(lngErrorcode, __LINE__); /* Prompt user for FIO4 output value */ printf("Enter desired FIO4 setting ( 1 for high and 0 for low ): "); scanf("%lf", &WriteVal); /* Write FIO4 value */ lngErrorcode = ePut(lngHandle, LJ_ioPUT_DIGITAL_BIT, 4, WriteVal, 0); ErrorHandler(lngErrorcode, __LINE__); /* Read FIO5 value */ lngErrorcode = eGet(lngHandle, LJ_ioGET_DIGITAL_BIT, 5, ErrorHandler(lngErrorcode, __LINE__); printf("FIO5 value = %lf\n", ReadVal); return 0; }

&ReadVal, 0);

10

ECE Department Portland State University

Version 1.4

Example (Complete Program Analog Input):


/* -----------------------------------------------------------------------This program sets the voltage for an analog output channel and reads the voltage from an analog input channel. Connect a wire from DAC0 to FIO2 (aka AIN2). The program will return the value you set DAC0 to as AIN2. ------------------------------------------------------------------------ */ #include <stdio.h> #include <stdlib.h> #include "c:\program files\labjack\drivers\LabJackUD.h" /* ErrorHandler code was written by the LabJack company */ void ErrorHandler (LJ_ERROR lngErrorcode, long lngLineNumber) { char err[255]; if (lngErrorcode != LJE_NOERROR) { ErrorToString(lngErrorcode, err); printf("Error # %d: %s\n", lngErrorcode, err); printf("Source line number = %d\n", lngLineNumber); if(lngErrorcode > LJE_MIN_GROUP_ERROR) { getchar(); exit(0); /* Quit if serious error. */ } } } int main (void) { LJ_ERROR lngErrorcode; LJ_HANDLE lngHandle = 0; double WriteVal, ReadVal;

/* LabJack error code */ /* ID# assigned to the opened LabJack */ /* DAC and AIN state values */

/* Open the first found LabJack U3 */ lngErrorcode = OpenLabJack(LJ_dtU3, LJ_ctUSB, "1", 1, ErrorHandler(lngErrorcode, __LINE__);

&lngHandle);

/* Set all pin assignments to the factory default condition */ lngErrorcode = ePut(lngHandle, LJ_ioPIN_CONFIGURATION_RESET, 0, 0, 0); ErrorHandler(lngErrorcode, __LINE__); /* For FIO2, set Bit# to 2. To enable analog input, set State to 1 */ lngErrorcode = ePut(lngHandle, LJ_ioPUT_ANALOG_ENABLE_BIT, 2, 1, 0); ErrorHandler(lngErrorcode, __LINE__); /* For DAC0, set DAC# to 0. Set the output voltage at 0.75 V */ WriteVal = 0.75; lngErrorcode = ePut(lngHandle, LJ_ioPUT_DAC, 0, WriteVal, 0); ErrorHandler(lngErrorcode, __LINE__); /* Read AIN2 single-ended voltage */ lngErrorcode = eGet(lngHandle, LJ_ioGET_AIN, 2, ErrorHandler(lngErrorcode, __LINE__); printf("AIN2 value = %lf\n", ReadVal); return 0; }

&ReadVal, 0);

11

ECE Department Portland State University

Version 1.4

Passing LabJack Variables to Functions


In the previous examples, most of the LabJack setup and I/O code was placed in the main() function. It is also possible to call LabJack functions from inside other user-written functions, as long as the appropriate variables (e.g., lngHandle) are passed as arguments. Note: Avoid using global variables to share LabJack variables! Use argument passing instead. Example (Complete Program Passing LabJack Variables):
/* ------------------------------------------------------------This program is a revised version of the digital I/O example. It shows how to pass LabJack variables between functions. All of the functions are contained in the same file. ------------------------------------------------------------- */ #include <stdio.h> #include <stdlib.h> #include "c:\program files\labjack\drivers\LabJackUD.h" /* Function prototypes */ void Initialize_LJ (LJ_HANDLE * plngHandle); double Perform_LJ_IO (LJ_HANDLE lngHandle, double WriteVal); void ErrorHandler (LJ_ERROR lngErrorcode, long lngLineNumber);

/* main Used for calling LabJack functions that we wrote Parameters: none Returns : execution status */ int main (void) { LJ_HANDLE lngHandle = 0; /* ID# assigned to the opened LabJack */ double WriteVal, ReadVal; /* FIO values */ /* Open LabJack U3 and set it to default config */ Initialize_LJ(&lngHandle); /* Prompt user for FIO4 output value */ printf("Enter desired FIO4 setting ( 1 for high and 0 for low ): "); scanf("%lf", &WriteVal); /* Call LabJack code to set and read FIOs */ ReadVal = Perform_LJ_IO(lngHandle, WriteVal); printf("FIO5 value = %lf\n", ReadVal); return 0; }

12

ECE Department Portland State University

Version 1.4

/* Initialize_LJ Opens and initializes LabJack hardware Parameters: plngHandle pointer to LabJack ID# variable Returns : none */ void Initialize_LJ (LJ_HANDLE * plngHandle) { LJ_ERROR lngErrorcode; /* LabJack error code */ /* Open the first found LabJack U3 */ /* Note: plngHandle is already a pointer, so no & is needed */ lngErrorcode = OpenLabJack(LJ_dtU3, LJ_ctUSB, "1", 1, plngHandle); ErrorHandler(lngErrorcode, __LINE__); /* Set all pin assignments to the factory default condition */ /* Note: *plngHandle is the ID# stored at plngHandle address */ lngErrorcode = ePut(*plngHandle, LJ_ioPIN_CONFIGURATION_RESET, 0, 0, 0); ErrorHandler(lngErrorcode, __LINE__); }

/* Perform_LJ_IO Sets FIO4 output value and reads FIO5 state Parameters: lngHandle LabJack ID WriteVal - Desired state value for FIO4 Returns : Current state value for FIO5 */ double Perform_LJ_IO (LJ_HANDLE lngHandle, double WriteVal) { LJ_ERROR lngErrorcode; /* LabJack error code */ double ReadVal; /* FIO value */ /* Write FIO4 state */ lngErrorcode = ePut(lngHandle, LJ_ioPUT_DIGITAL_BIT, 4, WriteVal, 0); ErrorHandler(lngErrorcode, __LINE__); /* Read FIO5 state */ lngErrorcode = eGet(lngHandle, LJ_ioGET_DIGITAL_BIT, 5, ErrorHandler(lngErrorcode, __LINE__); return ReadVal; }

&ReadVal, 0);

/* ErrorHandler code was written by the LabJack company */ void ErrorHandler (LJ_ERROR lngErrorcode, long lngLineNumber) { char err[255]; if (lngErrorcode != LJE_NOERROR) { ErrorToString(lngErrorcode, err); printf("Error # %d: %s\n", lngErrorcode, err); printf("Source line number = %d\n", lngLineNumber); if(lngErrorcode > LJE_MIN_GROUP_ERROR) { getchar(); exit(0); /* Quit if serious error. */ } } }

13

ECE Department Portland State University

Version 1.4

Advanced Topic: Counters & Timers


INTRODUCTION - Counters
A counter is a hardware circuit that counts the number of times the falling edge of a digital voltage signal is detected on an external pin. Counters are useful for keeping track of the number of times an event has occurred. The event must generate a High-to-Low logic transition in order to trip the counter. In terms of physical voltage levels, H is 2.0 V to 5 V, and L is 0 V to 0.8 V (~ ground). The counter value limits are o Minimum = 0 o Maximum = 4,294,967,295 The maximum input counter frequency is 8 MHz. Depending on the timer clock base, either one or two counters are available. A counter can be assigned to only certain FIO channels.

H L
Input signal has three H-to-L transitions

Counter (32 bits, LSB on right side)

00000000000000000000000000000011 = 310
Figure 1: Sample input signal being counted

Basic Setup
The first four steps of developing a counter program for the LabJack are: 1. Create a new C project file 2. Add startup code to the C program 3. Establish communications with the LabJack 4. Configure the I/O Channels (reset to factory default) These steps are identical to the procedures discussed previously for digital I/O and analog input programs.

14

ECE Department Portland State University

Version 1.4

Counter Setup
Since there are no dedicated counter channels on the LabJack, a counter needs to be assigned to an available FIO channel. The counter takes over the FIO channel until it is released. Up to two counters can be assigned to channels FIO4 through FIO7 and EIO0 through EIO1. Dual counters are always assigned to consecutive channels. The LabJack utilizes a timer/counter pin offset value (4 to 8) to specify the starting channel for the counters. One Counter Two Counters

Counter Pin Counter0 Counter Pin Counter0 Counter1 Offset Channel Offset Channel Channel

4 5 6 7 8

FIO4 FIO5 FIO6 FIO7 EIO0

4 5 6 7 8

FIO4 FIO5 FIO6 FIO7 EIO0

FIO5 FIO6 FIO7 EIO0 EIO1

Setting the starting channel for counters:


lngErrorcode = ePut(lngHandle, LJ_ioPUT_CONFIG, LJ_chTIMER_COUNTER_PIN_OFFSET, TCPO, 0);

TCPO (timer/counter pin offset) specifies the starting channel for counter assignments. TCPO is type double. Allowed range: TCPO = 4 to 8 Example:
/* Put one counter on FIO4 */ lngErrorcode = ePut(lngHandle,LJ_ioPUT_CONFIG,LJ_chTIMER_COUNTER_PIN_OFFSET,4,0); ErrorHandler(lngErrorcode, __LINE__); /* Put one counter on FIO7 */ lngErrorcode = ePut(lngHandle,LJ_ioPUT_CONFIG,LJ_chTIMER_COUNTER_PIN_OFFSET,7,0); ErrorHandler(lngErrorcode, __LINE__); /* Put two counters on FIO6 and FIO7 */ lngErrorcode = ePut(lngHandle,LJ_ioPUT_CONFIG,LJ_chTIMER_COUNTER_PIN_OFFSET,6,0); ErrorHandler(lngErrorcode, __LINE__);

15

ECE Department Portland State University

Version 1.4

Enabling counters: lngErrorcode = ePut(lngHandle, LJ_ioPUT_COUNTER_ENABLE, Counter#, ENA, 0); If ENA is set to true (1), the counter corresponding to Counter# will be enabled. If ENA is set to false (0), the counter will be disabled. Counter# is type long int. ENA is type double. Allowed ranges: Counter# = 0 or 1; ENA = 0 or 1 Example:
/* Enable Counter0 */ lngErrorcode = ePut(lngHandle, LJ_ioPUT_COUNTER_ENABLE, 0, 1, 0); ErrorHandler(lngErrorcode, __LINE__); /* Enable Counter1 */ lngErrorcode = ePut(lngHandle, LJ_ioPUT_COUNTER_ENABLE, 1, 1, 0); ErrorHandler(lngErrorcode, __LINE__); /* Disable Counter1 */ lngErrorcode = ePut(lngHandle, LJ_ioPUT_COUNTER_ENABLE, 1, 0, 0); ErrorHandler(lngErrorcode, __LINE__);

Resetting counters: lngErrorcode = ePut(lngHandle, LJ_ioPUT_COUNTER_RESET, Counter#, 1, 0); The counter corresponding to Counter# will be reset back to a zero count. Counter# is type long int. Allowed ranges: Counter# = 0 or 1 Example:
/* Reset Counter0 */ lngErrorcode = ePut(lngHandle, LJ_ioPUT_COUNTER_RESET, 0, 1, 0); ErrorHandler(lngErrorcode, __LINE__); /* Reset Counter1 */ lngErrorcode = ePut(lngHandle, LJ_ioPUT_COUNTER_RESET, 1, 1, 0); ErrorHandler(lngErrorcode, __LINE__);

16

ECE Department Portland State University

Version 1.4

Reading from a counter: lngErrorcode = eGet(lngHandle, LJ_ioGET_COUNTER, Counter#, &ReadVal, 0); The counter corresponding to Counter# is read, and the current count is passed back in ReadVal. Counter# is type long int. ReadVal is type double (&ReadVal is the address of ReadVal). Allowed ranges: Counter# = 0 or 1 Example:
/* Read Counter0 */ lngErrorcode = eGet(lngHandle, LJ_ioGET_COUNTER, 0, &cur_count, 0); ErrorHandler(lngErrorcode, __LINE__); /* Read Counter1 */ lngErrorcode = eGet(lngHandle, LJ_ioGET_COUNTER, 1, &Value, 0); ErrorHandler(lngErrorcode, __LINE__);

Example (Complete Program Counters Only):


/* -----------------------------------------------------------------------This program demonstrates how to set up a single counter. Attach one end of a wire to FIO4 (counter input). Touch the other end of the wire to GND. Each touch generates many counts due to contact bounce. GND is used because U3 digital inputs are normally high, so it needs to be pulled low to initiate the H-to-L trigger for the counter. ------------------------------------------------------------------------ */ #include <stdio.h> #include <windows.h> #include "c:\program files\labjack\drivers\LabJackUD.h" /* ErrorHandler code was written by the LabJack company */ void ErrorHandler (LJ_ERROR lngErrorcode, long lngLineNumber) { char err[255]; if (lngErrorcode != LJE_NOERROR) { ErrorToString(lngErrorcode, err); printf("Error # %d: %s\n", lngErrorcode, err); printf("Source line number = %d\n", lngLineNumber); if(lngErrorcode > LJE_MIN_GROUP_ERROR) { getchar(); exit(0); /* Quit if serious error. */ } } }

17

ECE Department Portland State University

Version 1.4

int main (void) { LJ_ERROR lngErrorcode; LJ_HANDLE lngHandle=0; double dblValue=0;

/* LabJack error code */ /* ID# assigned to the opened LabJack */ /* Current count value */

/* Open the first found LabJack U3. */ lngErrorcode = OpenLabJack(LJ_dtU3, LJ_ctUSB, "1", 1, ErrorHandler(lngErrorcode, __LINE__);

&lngHandle);

/* Set all pin assignments to the factory default condition. */ lngErrorcode = ePut(lngHandle, LJ_ioPIN_CONFIGURATION_RESET, 0, 0, 0); ErrorHandler(lngErrorcode, __LINE__); /* Set the timer/counter pin offset to 4. The puts Counter0 on FIO4. */ lngErrorcode = ePut(lngHandle,LJ_ioPUT_CONFIG,LJ_chTIMER_COUNTER_PIN_OFFSET,4,0); ErrorHandler(lngErrorcode, __LINE__); /* Enable Counter0. */ lngErrorcode = ePut(lngHandle, LJ_ioPUT_COUNTER_ENABLE, 0, 1, 0); ErrorHandler(lngErrorcode, __LINE__); /* Read and display counter value until user presses any key to stop */ while (!_kbhit()) /* _kbhit() is in <conio.h> - not ANSI/ISO compliant */ { /* Request a read from the counter. */ lngErrorcode = eGet(lngHandle, LJ_ioGET_COUNTER, 0, &dblValue, 0); ErrorHandler(lngErrorcode, __LINE__); /* Display the current count value. */ printf("Counter = %.1f\n", dblValue); /* Wait 0.01 second. Sleep() is in <windows.h> - not ANSI/ISO compliant */ /* Argument has units of milliseconds. */ Sleep(10); } /* Reset all pin assignments to factory default condition. */ lngErrorcode = ePut(lngHandle, LJ_ioPIN_CONFIGURATION_RESET, 0, 0, 0); ErrorHandler(lngErrorcode, __LINE__); return 0; }

18

ECE Department Portland State University

Version 1.4

INTRODUCTION Timers
A timer is used if an input signal measurement or an output signal generation requires precise, hardware-based timing. Some timer modes include: pulse width modulation output, signal period input, frequency output, and firmware counter input Up to two timers are available. A timer can be assigned to only certain FIO channels.

Basic Setup
The first four steps of developing a timer program for the LabJack are: 1. Create a new C project file 2. Add startup code to C program 3. Establish Communications with the LabJack 4. Configure the I/O Channels (reset to factory default) These steps are identical to the procedures discussed previously for digital I/O and analog input programs.

19

ECE Department Portland State University

Version 1.4

Common Timer Setup


Note: The following section applies to all of the timer modes. Setup information that is modespecific will be presented separately in their own sections. Since there are no dedicated timer channels on the LabJack, a timer needs to be assigned to an available FIO channel. The timer takes over the FIO channel until it is released. Up to two timers can be assigned to channels FIO4 through FIO7 and EIO0 through EIO1. Dual timers are always assigned to consecutive channels. The LabJack utilizes a timer/counter pin offset value (4 to 8) to specify the starting channel for the timers. One Timer Two Timers

Timer Pin Timer0 Timer Pin Timer0 Timer1 Offset Channel Offset Channel Channel

4 5 6 7 8

FIO4 FIO5 FIO6 FIO7 EIO0

4 5 6 7 8

FIO4 FIO5 FIO6 FIO7 EIO0

FIO5 FIO6 FIO7 EIO0 EIO1

Setting the starting channel for timers:


lngErrorcode = ePut(lngHandle, LJ_ioPUT_CONFIG, LJ_chTIMER_COUNTER_PIN_OFFSET, TCPO, 0);

TCPO (timer/counter pin offset) specifies the starting channel for timer assignments. TCPO is type double. Allowed range: TCPO = 4 to 8 Example:
/* Put one timer on FIO4 */ lngErrorcode = ePut(lngHandle,LJ_ioPUT_CONFIG,LJ_chTIMER_COUNTER_PIN_OFFSET,4,0); ErrorHandler(lngErrorcode, __LINE__);

20

ECE Department Portland State University

Version 1.4

Setting the timer clock base:


lngErrorcode = ePut(lngHandle, LJ_ioPUT_CONFIG, LJ_chTIMER_CLOCK_BASE, TCB, 0);

TCB (timer clock base) specifies the base frequency for all timer operations. Note: Changing the default 48 MHz base frequency may increase the DAC output noise. TCB is type double. Allowed range: Predefined macros are available for setting TCB. TCB Macro Name
LJ_tc4MHZ LJ_tc12MHZ LJ_tc48MHZ LJ_tc1MHZ_DIV LJ_tc4MHZ_DIV LJ_tc12MHZ_DIV LJ_tc48MHZ_DIV

Description 4 MHz clock base 12 MHz clock base 48 MHz clock base (default) 1 MHz clock base w/ divisor (no Counter0) 4 MHz clock base w/ divisor (no Counter0) 12 MHz clock base w/ divisor (no Counter0) 48 MHz clock base w/ divisor (no Counter0)

Since the LabJack only offers a limited number of base frequencies (1, 4, 12, and 48 MHz), a divisor can be used to divide the chosen frequency down to a smaller value. The divisor is set using a separate ePut() call. If a divisor is used, then Counter0 is no longer available. Example:
/* Use the 4 MHz timer clock with no divisor */ lngErrorcode= ePut(lngHandle, LJ_ioPUT_CONFIG, LJ_chTIMER_CLOCK_BASE, LJ_tc4MHZ, 0); ErrorHandler(lngErrorcode, __LINE__);

/* Use the 48 MHz timer clock with a divisor */ lngErrorcode = ePut(lngHandle, LJ_ioPUT_CONFIG, LJ_chTIMER_CLOCK_BASE, LJ_tc48MHZ_DIV, 0); ErrorHandler(lngErrorcode, __LINE__);

21

ECE Department Portland State University

Version 1.4

Setting the timer clock divisor:


lngErrorcode = ePut(lngHandle, LJ_ioPUT_CONFIG, LJ_chTIMER_CLOCK_DIVISOR, TCD, 0);

If the chosen timer clock base uses a divisor, then TCD (timer clock divisor) sets the divisor value. The timer frequency is given by fT = timer clock base / timer clock divisor = TCB / TCD. This function should only be used if the timer clock base is LJ_tc1MHz_DIV,
LJ_tc4MHZ_DIV, LJ_tc12MHZ_DIV, or LJ_tc48MHZ_DIV.

TCD is type double. Allowed range: TCD = 0 to 255, where 0 is interpreted as 256. Sample base frequency and divisor combinations TCB Macro Name
LJ_tc1MHz_DIV LJ_tc1MHz_DIV LJ_tc1MHz_DIV LJ_tc1MHz_DIV LJ_tc4MHZ_DIV LJ_tc4MHz_DIV LJ_tc4MHz_DIV LJ_tc4MHz_DIV LJ_tc48MHZ_DIV LJ_tc48MHZ_DIV LJ_tc48MHZ_DIV LJ_tc48MHZ_DIV

TCD 1 4 100 0 (equiv to 256) 1 4 100 0 (equiv to 256) 1 48 128 0 (equiv to 256)

Timer Frequency 1 MHz 250 kHz 10 kHz 3906.25 Hz 4 MHz 1 MHz 40 kHz 15.625 kHz 48 MHz 1 MHz 375 kHz 187.5 kHz

Example:
/* Assume LJ_tc48MHz. Use a divisor of 48 to get a timer frequency of 1 MHz */ lngErrorcode= ePut(lngHandle, LJ_ioPUT_CONFIG, LJ_chTIMER_CLOCK_DIVISOR, 48, 0); ErrorHandler(lngErrorcode, __LINE__);

22

ECE Department Portland State University

Version 1.4

Enabling timers:
lngErrorcode = ePut(lngHandle, LJ_ioPUT_CONFIG, LJ_chNUMBER_TIMERS_ENABLED, #Timers, 0);

#Timers determines the number of timers that should be enabled. Once a timer is enabled (1 or 2), the timer immediately begins operating. Once a timer is disabled (0), the timer immediately stops operating. #Timers is type double. Allowed ranges: #Timers = 0 , 1, or 2 Example:
/* Enable Timer0 only */ lngErrorcode = ePut(lngHandle, LJ_ioPUT_CONFIG, LJ_chNUMBER_TIMERS_ENABLED, 1, 0); ErrorHandler(lngErrorcode, __LINE__); /* Enable both Timer0 and Timer1 */ lngErrorcode = ePut(lngHandle, LJ_ioPUT_CONFIG, LJ_chNUMBER_TIMERS_ENABLED, 2, 0); ErrorHandler(lngErrorcode, __LINE__);

23

ECE Department Portland State University

Version 1.4

Additional Timer Setup for Pulse Width Modulation (PWM) Mode


The LabJack can generate a periodic train of voltage pulses at a frequency f with a specified duty cycle. The pulse period is defined as tp = 1 / f . Within a single pulse period, the pulse is high for a certain amount of time and low for the remainder of the time. The pulse width tw is defined as the time interval over which the pulse is high. The duty cycle (in %) of the pulse train is: Duty = (tw / tp) * 100% PWM can be used for controlling the speed of DC motors.

V
A

Pulse Width = 0.9 ms

Duty = 90%

0 0 1 Pulse Period = 1.0 ms Pulse Freq = 1 kHz 2 3

t (ms)

V
A

Pulse Width = 0.5 ms

Duty = 50%

0 0 1 Pulse Period = 1.0 ms Pulse Freq = 1 kHz 2 3

t (ms)

V
A

Pulse Width = 0.1 ms

Duty = 10%

0 0 1 Pulse Period = 1.0 ms Pulse Freq = 1 kHz 2 3

t (ms)

Figure 2: Sample pulse train with f = 1 kHz and varying duty cycles.

24

ECE Department Portland State University

Version 1.4

Setting the PWM timer mode:


lngErrorcode = ePut(lngHandle, LJ_ioPUT_TIMER_MODE, Timer#, Tmode, 0);

The timer corresponding to Timer# will be set to mode Tmode. The mode affects the final pulse width modulation frequency. Timer# is type long int. Tmode is type double. Allowed range: Timer# = 0 or 1. Predefined macros are available for setting Tmode. Macro Name
LJ_tmPWM16 LJ_tmPWM8

Description 16-bit PWM output (Mode 0) 8-bit PWM output (Mode 1)

The selection of 8-bit or 16-bit PWM output determines the pulse train frequency. The pulse train frequency is fPT = (TCB / TCD) / 2#bits , where #bits = 8 or 16 Timer Clock Base Frequency (TCB) 4 MHz 12 MHz 48 MHz (Default) 1 MHz w/ divisor 4 MHz w/ divisor 12 MHz w/ divisor 48 MHz w/ divisor Example:
/* Set Timer0 to 8-bit pulse width modulation mode */ lngErrorcode = ePut(lngHandle, LJ_ioPUT_TIMER_MODE, 0, LJ_tmPWM8, 0); ErrorHandler(lngErrorcode, __LINE__); /* Set Timer1 to 16-bit pulse width modulation mode */ lngErrorcode = ePut(lngHandle, LJ_ioPUT_TIMER_MODE, 1, LJ_tmPWM16, 0); ErrorHandler(lngErrorcode, __LINE__);

PWM16 Frequency Range (Hz) TCD = 1 TCD = 256

PWM8 Frequency Range (Hz) TCD = 1 TCD = 256

61.035 183.105 732.422 15.259 61.035 183.105 732.422

N/A N/A N/A 0.060 0.238 0.715 2.861

15625.000 46875.000 187500.000 3906.25 15625.000 46875.000 187500.000

N/A N/A N/A 15.259 61.035 183.105 732.422

25

ECE Department Portland State University

Version 1.4

Setting the PWM duty cycle:


lngErrorcode = ePut(lngHandle, LJ_ioPUT_TIMER_VALUE, Timer#, TISL, 0);

The timer corresponding to Timer# will have its pulse train duty cycle set according to TISL. TISL is the total number of increments out of 65536 that the pulse is in a low state within a single pulse period. To calculate TISL, use TISL = (1 Duty) * 65536, where Duty is the fractional duty cycle. Timer# is type long int. TISL is type double Allowed ranges: Timer# = 0 or 1; TISL = 0 to 65535 (16-bit PWM) or 65280 (8-bit PWM) PWM Type 16-bit 8-bit Resolution (increment size) 65536 / 216 = 1 65536 / 28 = 256 Maximum Duty Cycle 100% 100% Minimum Duty Cycle (1 / 65536) * 100% = 0.0015% (256 / 65536) * 100% = 0.39%

Example:
/* Set Timer0 to a 25% duty cycle (is low 49152 out of 65536 */ lngErrorcode = ePut(lngHandle, LJ_ioPUT_TIMER_VALUE, 0, 49152,0); ErrorHandler(lngErrorcode, __LINE__); /* Set Timer0 to a 50% duty cycle (is low 32768 out of 65536 */ lngErrorcode = ePut(lngHandle, LJ_ioPUT_TIMER_VALUE, 0, 32768,0); ErrorHandler(lngErrorcode, __LINE__); /* Set Timer1 to a 75% duty cycle (is low 16384 out of 65536 */ lngErrorcode = ePut(lngHandle, LJ_ioPUT_TIMER_VALUE, 0, 16384,0); ErrorHandler(lngErrorcode, __LINE__);

26

ECE Department Portland State University

Version 1.4

List of LabJack functions typically needed for PWM mode: Opening LabJack for I/O
lngErrorcode = OpenLabJack(LJ_dtU3, LJ_ctUSB, "1", 1, &lngHandle);

Resetting LabJack configuration


lngErrorcode = ePut(lngHandle, LJ_ioPIN_CONFIGURATION_RESET, 0, 0, 0);

Starting channel for timers lngErrorcode = ePut(lngHandle, LJ_ioPUT_CONFIG, LJ_chTIMER_COUNTER_PIN_OFFSET, TCPO, 0); Timer clock base lngErrorcode = ePut(lngHandle, LJ_ioPUT_CONFIG, LJ_chTIMER_CLOCK_BASE, TCB, 0); Timer clock divisor lngErrorcode = ePut(lngHandle, LJ_ioPUT_CONFIG, LJ_chTIMER_CLOCK_DIVISOR, TCD, 0); Enable/disable timers lngErrorcode = ePut(lngHandle, LJ_ioPUT_CONFIG, LJ_chNUMBER_TIMERS_ENABLED, #Timers, 0); PWM timer mode lngErrorcode = ePut(lngHandle, LJ_ioPUT_TIMER_MODE, Timer#, LJ_tmPWM?, 0); PWM duty cycle lngErrorcode = ePut(lngHandle, LJ_ioPUT_TIMER_VALUE, 0, TISL, 0);

27

ECE Department Portland State University

Version 1.4

Example (Complete Program PWM Timer Only):


/* -----------------------------------------------------------------------This program demonstrates pulse width modulation by using a timer. Connect a wire from FIO4 (PWM output) to an LED to see it blink. ------------------------------------------------------------------------ */ #include #include #include #include <stdio.h> <stdlib.h> <conio.h> "c:\program files\labjack\drivers\LabJackUD.h"

/* ErrorHandler code was written by the LabJack company */ void ErrorHandler (LJ_ERROR lngErrorcode, long lngLineNumber) { char err[255]; if (lngErrorcode != LJE_NOERROR) { ErrorToString(lngErrorcode, err); printf("Error # %d: %s\n", lngErrorcode, err); printf("Source line number = %d\n", lngLineNumber); if(lngErrorcode > LJE_MIN_GROUP_ERROR) { getchar(); exit(0); /* Quit if serious error. */ } } }

int main (void) { LJ_ERROR lngErrorcode; LJ_HANDLE lngHandle=0; double Value;

/* LabJack error code */ /* ID# assigned to the opened LabJack */ /* Scratch variable */

/* Open the first found LabJack U3. */ lngErrorcode = OpenLabJack(LJ_dtU3, LJ_ctUSB, "1", 1, ErrorHandler(lngErrorcode, __LINE__);

&lngHandle);

/* Set all pin assignments to the factory default condition. */ lngErrorcode = ePut(lngHandle, LJ_ioPIN_CONFIGURATION_RESET, 0, 0, 0); ErrorHandler(lngErrorcode, __LINE__); /* Set the timer/counter pin offset to 4. This puts Timer0 on FIO4. */ lngErrorcode = ePut(lngHandle,LJ_ioPUT_CONFIG,LJ_chTIMER_COUNTER_PIN_OFFSET,4,0); ErrorHandler(lngErrorcode, __LINE__); /* Use the 48 MHz timer clock base with divisor. */ lngErrorcode = ePut(lngHandle, LJ_ioPUT_CONFIG, LJ_chTIMER_CLOCK_BASE, LJ_tc48MHZ_DIV, 0); ErrorHandler(lngErrorcode, __LINE__); /* Set divisor to 0 (=256) so the actual timer clock is 187.5 kHz MHz. */ lngErrorcode = ePut(lngHandle, LJ_ioPUT_CONFIG, LJ_chTIMER_CLOCK_DIVISOR, 0, 0); ErrorHandler(lngErrorcode, __LINE__); /* Enable 1 timer. */ lngErrorcode = ePut(lngHandle, LJ_ioPUT_CONFIG, LJ_chNUMBER_TIMERS_ENABLED, 1,0); ErrorHandler(lngErrorcode, __LINE__);

28

ECE Department Portland State University

Version 1.4

/* Configure Timer0 as 16-bit PWM. Frequency is (187.5 kHz / 2^16) = 2.861 Hz. */ lngErrorcode = ePut(lngHandle, LJ_ioPUT_TIMER_MODE, 0, LJ_tmPWM16, 0); ErrorHandler(lngErrorcode, __LINE__); /* Set the PWM duty cycle to 50%. */ lngErrorcode = ePut(lngHandle, LJ_ioPUT_TIMER_VALUE, 0, 32768, 0); ErrorHandler(lngErrorcode, __LINE__); printf("Press any key to stop the PWM output and reset the LabJack.\n"); while (!_kbhit()) /* _kbhit() is in <conio.h> - not ANSI/ISO compliant */ ; /* Reset all pin assignments to factory default condition. */ lngErrorcode = ePut(lngHandle, LJ_ioPIN_CONFIGURATION_RESET, 0, 0, 0); ErrorHandler(lngErrorcode, __LINE__); /* The PWM output sets FIO4 to output, so we do a read */ /* here to set it to input. */ lngErrorcode = eGet(lngHandle, LJ_ioGET_DIGITAL_BIT, 4, &Value, 0); ErrorHandler(lngErrorcode, __LINE__); return 0; }

29

ECE Department Portland State University

Version 1.4

Additional Timer Setup for Frequency Output (FREQOUT) Mode


The LabJack can generate a square wave output voltage at a specified frequency f. The period is defined as t = 1 / f . For a square wave, the duty cycle is always 50%. The minimum amplitude of the output voltage is 0 V. The maximum amplitude of the output voltage is approximately +3.5 V.

V
3.5

Pulse Width = 0.5 ms

0 0 1 Pulse Period = 1.0 ms Pulse Freq = 1 kHz 2 3

t (ms)

Figure 3: Sample square wave output at f = 1 kHz.

Setting the timer mode:


lngErrorcode = ePut(lngHandle, LJ_ioPUT_TIMER_MODE, Timer#, Tmode, 0);

The timer corresponding to Timer# will be set to mode Tmode. Timer# is type long int. Tmode is type double. Allowed range: Timer# = 0 or 1; A predefined macro is available for setting Tmode. Macro Name
LJ_tmFREQOUT

Description Frequency output (Mode 7)

Example:
/* Set Timer0 to frequency output mode */ lngErrorcode = ePut(lngHandle, LJ_ioPUT_TIMER_MODE, 0, LJ_tmFREQOUT,0); ErrorHandler(lngErrorcode, __LINE__);

30

ECE Department Portland State University

Version 1.4

Setting the output frequency:


lngErrorcode = ePut(lngHandle, LJ_ioPUT_TIMER_VALUE, Timer#, Tvalue, 0);

The timer corresponding to Timer# will have its output frequency set according to Tvalue. The output frequency is f = (TCB / TCD) / (2 * Tvalue) Timer# is type long int. Tvalue is type double Allowed ranges: Timer# = 0 or 1; Tvalue = 0 to 255, where 0 is interpreted as 256. Timer Clock Base Frequency (TCB) 4 MHz 12 MHz 48 MHz (Default) 1 MHz w/ divisor 4 MHz w/ divisor 12 MHz w/ divisor 48 MHz w/ divisor
Output Frequency Range (Hz) TCD = 1 Tvalue = 1 Tvalue = 256

2000000 6000000 24000000 500000 2000000 6000000 24000000

7812.5 23437.5 93750 7.629 30.518 91.553 366.211

The table shows only a few sample frequencies. The LabJack can generate many thousands of different frequencies, depending on the values of TCB, TCD, and Tvalue.

The LabJack website has a file that lists all the allowed combinations of TCB, TCD, and Tvalue parameters, along with the frequencies to which they correspond. The file is in CSV format (comma separated values) for easy importing into a spreadsheet program. It can also be opened with a standard text editor. The file can be downloaded from:
http://labjack.com/support/u3/frequency-list-u3-timer-mode-7

Example:
/* Set output frequency to 30.518 Hz (assuming TCB=4 MHz w/divisor, TCD=1 */ lngErrorcode = ePut(lngHandle, LJ_ioPUT_TIMER_VALUE, 0, 256, 0); ErrorHandler(lngErrorcode, __LINE__);

31

ECE Department Portland State University

Version 1.4

List of LabJack functions typically needed for FREQOUT mode: Opening LabJack for I/O
lngErrorcode = OpenLabJack(LJ_dtU3, LJ_ctUSB, "1", 1, &lngHandle);

Resetting LabJack configuration


lngErrorcode = ePut(lngHandle, LJ_ioPIN_CONFIGURATION_RESET, 0, 0, 0);

Starting channel for timers lngErrorcode = ePut(lngHandle, LJ_ioPUT_CONFIG, LJ_chTIMER_COUNTER_PIN_OFFSET, TCPO, 0); Enable/disable timers lngErrorcode = ePut(lngHandle, LJ_ioPUT_CONFIG, LJ_chNUMBER_TIMERS_ENABLED, #Timers, 0); FREQOUT timer mode lngErrorcode = ePut(lngHandle, LJ_ioPUT_TIMER_MODE, Timer#, LJ_tmFREQOUT, 0); Timer clock base lngErrorcode = ePut(lngHandle, LJ_ioPUT_CONFIG, LJ_chTIMER_CLOCK_BASE, TCB, 0); Timer clock divisor lngErrorcode = ePut(lngHandle, LJ_ioPUT_CONFIG, LJ_chTIMER_CLOCK_DIVISOR, TCD, 0); PWM duty cycle lngErrorcode = ePut(lngHandle, LJ_ioPUT_TIMER_VALUE, 0, Tvalue, 0);

32

ECE Department Portland State University

Version 1.4

Example (Complete Program FREQOUT Timer Only):


/* -----------------------------------------------------------------------This program demonstrates frequency output (440 Hz square wave) by using a timer. The output on FIO4 can be viewed on an oscilloscope. ------------------------------------------------------------------------ */ #include #include #include #include <stdio.h> <stdlib.h> <conio.h> "c:\program files\labjack\drivers\LabJackUD.h"

/* ErrorHandler code was written by the LabJack company */ void ErrorHandler (LJ_ERROR lngErrorcode, long lngLineNumber) { char err[255]; if (lngErrorcode != LJE_NOERROR) { ErrorToString(lngErrorcode, err); printf("Error # %d: %s\n", lngErrorcode, err); printf("Source line number = %d\n", lngLineNumber); if(lngErrorcode > LJE_MIN_GROUP_ERROR) { getchar(); exit(0); /* Quit if serious error. */ } } }

int main (void) { LJ_ERROR lngErrorcode; LJ_HANDLE lngHandle=0;

/* LabJack error code */ /* ID# assigned to the opened LabJack */

/* Open the first found LabJack U3. */ lngErrorcode = OpenLabJack(LJ_dtU3, LJ_ctUSB, "1", 1, &lngHandle); ErrorHandler(lngErrorcode, __LINE__); /* Set all pin assignments to the factory default condition. */ lngErrorcode = ePut(lngHandle, LJ_ioPIN_CONFIGURATION_RESET, 0, 0, 0); ErrorHandler(lngErrorcode, __LINE__); /* Set the timer/counter pin offset to 4. This puts Timer0 on FIO4. */ lngErrorcode = ePut(lngHandle,LJ_ioPUT_CONFIG,LJ_chTIMER_COUNTER_PIN_OFFSET,4,0); ErrorHandler(lngErrorcode, __LINE__); /* Enable one timer. It will use FIO4 */ lngErrorcode = ePut(lngHandle, LJ_ioPUT_CONFIG, LJ_chNUMBER_TIMERS_ENABLED, 1,0); ErrorHandler(lngErrorcode, __LINE__); /* Configure Timer0 as Frequency Output (square wave) */ lngErrorcode = ePut(lngHandle, LJ_ioPUT_TIMER_MODE, 0, LJ_tmFREQOUT, 0); ErrorHandler(lngErrorcode, __LINE__);

33

ECE Department Portland State University

Version 1.4

/* ----------------------------------------------------------------Desired output frequency = 440 Hz From the LabJack frequency table, the closest matching frequency is 440.044006 Hz, and there are four combinations that will work: Freq (Hz) Clock (Hz) Clock_Divisor 440.044006, 4000000.000000, 45.000000, 440.044006, 4000000.000000, 101.000000, 440.044006, 12000000.000000, 101.000000, 440.044006, 12000000.000000, 135.000000, Timer_Value 101.000000 45.000000 135.000000 101.000000

Choosing the first one, these are the required settings: Clock = 4000000.000000 (i.e., 4 MHz) Clock_Divisor = 45.000000 Timer_Value = 101.000000 -------------------------------------------------------------- */ /* Set the timer clock base to 4 MHz with divisor */ lngErrorcode = ePut(lngHandle, LJ_ioPUT_CONFIG, LJ_chTIMER_CLOCK_BASE, LJ_tc4MHZ_DIV, 0); ErrorHandler(lngErrorcode, __LINE__); /* Set the timer clock divisor to 45 */ lngErrorcode = ePut(lngHandle, LJ_ioPUT_CONFIG, LJ_chTIMER_CLOCK_DIVISOR, 45, 0); ErrorHandler(lngErrorcode, __LINE__); /* Set the timer value to 101 */ lngErrorcode = ePut(lngHandle, LJ_ioPUT_TIMER_VALUE, 0, 101, 0); ErrorHandler(lngErrorcode, __LINE__);

printf("Press any key to stop the square wave output and reset the LabJack.\n"); while (!_kbhit()) /* _kbhit() is in <conio.h> - not ANSI/ISO compliant */ ; /* Disable timer */ lngErrorcode = ePut(lngHandle, LJ_ioPUT_CONFIG, LJ_chNUMBER_TIMERS_ENABLED, 0,0); ErrorHandler(lngErrorcode, __LINE__);

/* Reset all pin assignments to factory default condition. */ lngErrorcode = ePut(lngHandle, LJ_ioPIN_CONFIGURATION_RESET, 0, 0, 0); ErrorHandler(lngErrorcode, __LINE__); return 0; }

34

ECE Department Portland State University

Version 1.4

INTRODUCTION Using Both Counters & Timers


It is possible to use both counters and timers in the same program. However, there are certain restrictions with regards to FIO assignments and counter availability. When timers or counters are enabled, they take over FIO/EIO channels in this sequence: Timer0, Timer1, Counter0, then Counter1. The starting channel is determined by the timer/counter pin offset value. For certain timer clock base frequencies (LJ_tc1MHz_DIV, LJ_tc4MHZ_DIV, LJ_tc12MHZ_DIV, or LJ_tc48MHZ_DIV), Counter0 is not available. If Counter0 is not available due to the choice of clock base frequency, then Counter0 does not use up an FIO channel.

Example: Scenario 1 Timer enabled, LJ_tc48MHz Counter0 disabled, Counter1 disabled TimerCounterPinOffset = 4 1 Timer enabled, LJ_tc48MHz Counter0 enabled, Counter1 disabled TimerCounterPinOffset = 4 1 Timer enabled, LJ_tc48MHz Counter0 disabled, Counter1 enabled TimerCounterPinOffset = 6 1 Timer enabled, LJ_tc48MHz Counter0 enabled, Counter1 enabled TimerCounterPinOffset = 6 2 Timers enabled, LJ_tc48MHz Counter0 enabled, Counter1 disabled TimerCounterPinOffset = 5 2 Timers enabled, LJ_tc48MHz Counter0 enabled, Counter1 enabled TimerCounterPinOffset = 8 1 Timer enabled, LJ_tc48MHz_DIV Counter0 unavailable, Counter1 enabled TimerCounterPinOffset = 4 Channel Assignments Timer0 FIO4

Timer0 FIO4 Counter0 FIO5 Timer0 FIO6 Counter1 FIO7 Timer0 FIO6 Counter0 FIO7 Counter1 EIO0 Timer0 FIO5 Timer1 FIO6 Counter0 FIO7 Timer0 EIO0 Timer1 EIO1 Counter0 EIO2 Counter1 EIO3 Timer0 FIO4 Counter1 FIO5

35

ECE Department Portland State University

Version 1.4

Example (Complete Program Both Counters & Timers):


/* -----------------------------------------------------------------------This program demonstrates a timer (for PWM) combined with a counter. Jumper a wire from FIO4 (PWM output) to FIO5 (counter input). ------------------------------------------------------------------------ */ #include <stdio.h> #include <windows.h> #include "c:\program files\labjack\drivers\LabJackUD.h" /* ErrorHandler code was written by the LabJack company */ void ErrorHandler (LJ_ERROR lngErrorcode, long lngLineNumber) { char err[255]; if (lngErrorcode != LJE_NOERROR) { ErrorToString(lngErrorcode, err); printf("Error # %d: %s\n", lngErrorcode, err); printf("Source line number = %d\n", lngLineNumber); if(lngErrorcode > LJE_MIN_GROUP_ERROR) { getchar(); exit(0); /* Quit if serious error. */ } } }

int main(void) { LJ_ERROR lngErrorcode; LJ_HANDLE lngHandle=0; double dblValue=0;

/* LabJack error code */ /* ID# assigned to the opened LabJack */ /* Counter state value */

/* Open the first found LabJack U3. */ lngErrorcode = OpenLabJack(LJ_dtU3, LJ_ctUSB, "1", 1, ErrorHandler(lngErrorcode, __LINE__);

&lngHandle);

/* Set all pin assignments to the factory default condition. */ lngErrorcode = ePut(lngHandle, LJ_ioPIN_CONFIGURATION_RESET, 0, 0, 0); ErrorHandler(lngErrorcode, __LINE__); /* Set the timer/counter pin offset to 4, which puts */ /* the first timer/counter on FIO4. */ lngErrorcode = ePut(lngHandle,LJ_ioPUT_CONFIG,LJ_chTIMER_COUNTER_PIN_OFFSET,4,0); ErrorHandler(lngErrorcode, __LINE__); /* Use the 48 MHz timer clock base with divider. Since we are */ /* using clock with divisor support, Counter0 is not available. */ lngErrorcode = ePut(lngHandle, LJ_ioPUT_CONFIG, LJ_chTIMER_CLOCK_BASE, LJ_tc48MHZ_DIV, 0); ErrorHandler(lngErrorcode, __LINE__); /* Set the divisor to 48 so the actual timer clock is 1 MHz. */ lngErrorcode = ePut(lngHandle, LJ_ioPUT_CONFIG, LJ_chTIMER_CLOCK_DIVISOR, 48, 0); ErrorHandler(lngErrorcode, __LINE__); /* Enable 1 timer. It will use FIO4. */ lngErrorcode = ePut(lngHandle, LJ_ioPUT_CONFIG, LJ_chNUMBER_TIMERS_ENABLED, 1,0); ErrorHandler(lngErrorcode, __LINE__);

36

ECE Department Portland State University

Version 1.4

/* Enable Counter1. It will use FIO5 since 1 timer is enabled. */ lngErrorcode = ePut(lngHandle, LJ_ioPUT_COUNTER_ENABLE, 1, 1, 0); ErrorHandler(lngErrorcode, __LINE__); /* Configure Timer0 as 8-bit PWM. Frequency is (1 MHz / 256) = 3906.25 Hz. */ lngErrorcode = ePut(lngHandle, LJ_ioPUT_TIMER_MODE, 0, LJ_tmPWM8, 0); ErrorHandler(lngErrorcode, __LINE__); /* Set the PWM duty cycle to 50%. */ lngErrorcode = ePut(lngHandle, LJ_ioPUT_TIMER_VALUE, 0, 32768, 0); ErrorHandler(lngErrorcode, __LINE__); /* Wait 1 second. Sleep() is in <windows.h> - not ANSI/ISO compliant. */ /* Argument has units of milliseconds. */ Sleep(1000); /* Request a read from the counter. */ lngErrorcode = eGet(lngHandle, LJ_ioGET_COUNTER, 1, ErrorHandler(lngErrorcode, __LINE__);

&dblValue, 0);

/* This should read roughly 4k counts if FIO4 is shorted to FIO5. */ printf("Counter = %.1f\n", dblValue); /* Wait 1 second. */ Sleep(1000); /* Request a read from the counter. */ lngErrorcode = eGet(lngHandle, LJ_ioGET_COUNTER, 1, ErrorHandler(lngErrorcode, __LINE__);

&dblValue, 0);

/* This should read about 3906 counts more than the previous read. */ printf("Counter = %.1f\n",dblValue); /* Reset all pin assignments to factory default condition. */ lngErrorcode = ePut(lngHandle, LJ_ioPIN_CONFIGURATION_RESET, 0, 0, 0); ErrorHandler(lngErrorcode, __LINE__); /* The PWM output sets FIO4 to output, so we do a read */ /* here to set it to input. */ lngErrorcode = eGet(lngHandle, LJ_ioGET_DIGITAL_BIT, 4, &dblValue, 0); ErrorHandler(lngErrorcode, __LINE__); return 0;

37

You might also like