Added LabJack Libraries

This commit is contained in:
Wayne Glettig
2021-02-09 00:58:15 +01:00
parent 29ab9f30e1
commit 6991609394
50 changed files with 15846 additions and 0 deletions

49
LabJackUE9/exodriver-master/.gitignore vendored Normal file
View File

@@ -0,0 +1,49 @@
*.o
*.dylib
*.so*
*~
.DS_Store
readModbusExample
testModbusFunctions
u12AISample
u3allio
u3BasicConfigU3
u3ConfigU3
u3Easy
u3EFunctions
u3Feedback
u3LJTDAC
u3Stream
u6allio
u6BasicConfigU6
u6ConfigU6
u6Easy
u6EFunctions
u6Feedback
u6LJTDAC
u6Stream
ue9allio
ue9BasicCommConfig
ue9CommConfig
ue9ControlConfig
ue9Easy
ue9EFunctions
ue9EthernetExample
ue9Feedback
ue9LJTDAC
ue9SingleIO
ue9Stream
ue9TimerCounter
ue9allio
readModbusExample
testModbusFunctions
writeModbusExample
u12AISample
u3BasicConfigU3
u3EFunctions
u6BasicConfigU6
u6EFunctions
ue9BasicCommConfig
ue9EFunctions
ue9EthernetExample

View File

@@ -0,0 +1,6 @@
SUBSYSTEM!="usb_device", ACTION!="add", GOTO="labjack_rules_end"
# LabJack Vendor ID
ATTRS{idVendor}=="0cd5", GROUP="adm"
LABEL="labjack_rules_end"

View File

@@ -0,0 +1,212 @@
Exodriver (liblabjackusb) Library Installation Instructions
============================================================
Table of Contents
-----------------
Linux Requirements
About These Instructions
liblabjackusb Library Script Installation
Compiling and Running the Example Programs
Machines Using VirtualBox
liblabjackusb Library Manual Installation
LabJackPython and the Exodriver on Ubuntu 10.04
Uninstalling the Old U3 and UE9 Driver
Linux Requirements
------------------
1. GNU C compiler (gcc).
For example in Ubuntu, run the following shell command to get it if needed:
$ sudo apt-get install build-essential
2. The libusb-1.0 library and development files. Download the source here:
http://sourceforge.net/projects/libusb/
3. Linux kernel 2.6.28 or higher. To use older 2.6.x kernels, you must upgrade
your firmware. These are the required firmware versions when using older
2.6 kernels:
* U3 with hardware version 1.30 or higher - Firmware 1.18 and higher
* U3 with hardware version less than 1.30 - Only kernel 2.6.28 and higher
supported. Unsupported on older kernels.
* U6 - Firmware 0.81 and greater
* UE9 - Comm Firmware 1.49 and greater
4. Uninstall any old U3 and UE9 kernel-module based drivers. The old driver
and custom kernel modules conflict with the current liblabjackusb library.
See the "Uninstalling the Old U3 and UE9 Driver" section for more
information.
About These Instructions
------------------------
All lines that start with a dollar sign ($) are commands and need to be run
from a terminal. For example, the Terminal application in Ubuntu version 10.04
is usually accessed through Applications -> Accessories -> Terminal.
liblabjackusb Library Script Installation
-----------------------------------------
In the exodriver/ directory, run the following command:
$ sudo ./install.sh
This script will attempt to build, install, and make any necessary system
configurations so that the user that runs it will be able to use LabJack
devices.
For information on allowing multiple users to use LabJack devices, see the
"Permissions" section under "liblabjackusb Library Manual Installation".
For more information, read the section titled liblabjackusb Library Manual
Installation later in this file.
Compiling and Running the Example Programs
------------------------------------------
The example code/programs use the liblabjackusb library and the labjackusb.h
header files in the liblabjackusb/ directory.
The examples are located in the U3, U6, and UE9 subdirectories in the examples/
directory. To compile the programs go to your device's directory and run
$ cd examples/U6/
$ make
Run one of example programs like this:
$ ./u6BasicConfigU6
Machines Using VirtualBox
-------------------------
Customers using Oracle's VirtualBox software should add themselves to the
vboxusers group, either through their distribution's GUI interface or through
the command: sudo usermod -a -G vboxusers USERNAME
liblabjackusb Library Manual Installation
-----------------------------------------
For Ubuntu 10.04, see the section titled "Up and running with LabJackPython
and the Exodriver on Ubuntu 10.04" later in this document.
In the liblabjackusb/ directory, run the following commands to compile and
install the library.
$ cd liblabjackusb/
$ make
$ sudo make install
Programs that use the liblabjackusb will need to access the USB device bus
at /dev/bus/usb/, typically with root permission. On Debian-based
distributions, we provide udev rules that allow members of the "adm" group
to access LabJack devices.
Install The udev Rules
To install the udev rules, run the following commands from the root
directory of this package.
$ sudo cp 10-labjack.rules /lib/udev/rules.d
$ sudo udevadm control --reload-rules
Older vesions of udevadm (e.g., the version included in Ubuntu 8.04) use an
underscore instead of a dash: "--reload_rules" instead of "--reload-rules":
$ sudo udevadm control --reload_rules
On Debian-based distributions, the above two commands are sufficient. If
your distribution does not have udevadm, restart udev or restart your
computer. On a Fedora machine run:
$ sudo /etc/init.d/udev-post reload
Permissions
Be sure to add any users that need to use LabJack devices to the "adm"
group. If a user is not in the adm group, they will need to execute
programs that use Exodriver with altered permissions. For example, they will
need to run `sudo ./labjack_program` rather than `./labjack_program`.
To check if the user with username USERNAME is in the adm group, type:
$ groups USERNAME
For this command, you can leave USERNAME blank if you are checking what groups
the current user is in.
If "adm" does not appear in the output, you need to add yourself to the
adm group, as follows.
To add a user with username USERNAME to the adm group, run the following
command:
$ sudo usermod -a -G adm USERNAME
For every user that is added to the adm group, they must log out and log
back in for the group changes to take effect. Re-run "groups" to double check.
LabJackPython and the Exodriver on Ubuntu 10.04
-----------------------------------------------
As we detailed in May 2010 (updated with the "liblabjackusb Library Manual
Installation" section's steps):
http://labjack.com/blog/running-labjackpython-and-exodriver-ubuntu-1004
Ubuntu 10.04 comes with a binary release of libusb-1.0, so building the
Exodriver is easier than ever. Install the dependencies with apt-get,
checkout the Exodriver source code, and build it. Here are the complete
steps, along with a handful of steps at the end that build LabJackPython
(http://labjack.com/support/labjackpython) which is our Python module
that works well with the Exodriver:
$ sudo apt-get install build-essential
$ sudo apt-get install libusb-1.0-0-dev
$ sudo apt-get install git-core
$ git clone git://github.com/labjack/exodriver.git
$ cd exodriver/
$ sudo ./install.sh
$ cd ..
$ git clone git://github.com/labjack/LabJackPython.git
$ cd LabJackPython/src/
$ sudo python setup.py install
$ python
>>> import u3
>>> d = u3.U3()
>>> d.configU3()
Uninstalling the Old U3 and UE9 Driver
--------------------------------------
The old U3 and UE9 driver used custom kernel modules, and will conflict with
with the current liblabjackusb library. To uninstall the old driver please
unload and delete the U3 and/or UE9 kernel modules, delete the liblabjackusb.so
library and remove any scripts or udev rules you may have been using to load
the kernel module's device nodes. The following commands, or similar depending
on the directories you copied files to, should help prepare your system for the
new liblabjackusb 2.0 library:
$ rmmod labjacku3
$ rm labjacku3.ko /lib/modules/`uname -r`/kernel/drivers/usb/misc/labjacku3.ko
$ depmod -a
$ rm /usr/lib/liblabjackusb.so
These commands remove the udev rules we provided on the forums:
$ rm /etc/udev/rules.d/10-labjack.rules
$ sudo udevadm control --reload-rules

View File

@@ -0,0 +1,224 @@
Exodriver (liblabjackusb) Library Installation Instructions
============================================================
Table of Contents
-----------------
Installation From Installer
Installation from Source Code
Mac OS X Requirements
About These Instructions
Installing libusb-1.0
liblabjackusb Library Script Installation
Compiling and Running the Example Programs
Optional: Build a combined 32-/64-bit Exodriver on Mac OS X
Uninstalling the Old U3 and UE9 Driver
Installation From Installer
============================
First, download the installer online here:
http://labjack.com/support/linux-and-mac-os-x-drivers
Next, unzip the downloaded file (if not done automatically) and run the
Exodriver_NativeUSB_Setup.pkg package installer. Follow the instructions
from the installer to install the Exodriver and required libusb-1.0 libraries.
Note that the installed libraries are both 32 and 64-bit binaries. The
installer does not have the source code installation requirements mentioned
below.
To install the latest Exodriver from source code instead, use the instructions
in the "Installation from Source Code" section below.
Installation from Source Code
==============================
Mac OS X Requirements
---------------------
1. XCode developer tools
2. The libusb-1.0 library. See the "Installing libusb-1.0" for the libusb-1.0
download and installation instructions.
3. Mac OS X 10.5 Leopard or 10.6 Snow Leopard. We haven't tested the library
on Tiger or Panther.
4. Uninstall any MacOSX_C_NativeUSB based drivers. The old driver conflicts
with the current liblabjackusb library. See the "Uninstalling the Old U3 and
UE9 Driver" section for more information.
About These Instructions
------------------------
All lines that start with a dollar sign ($) are commands and need to be run
from a terminal. For example, the Terminal application is usually located in
the Applications folder.
Installing libusb-1.0
---------------------
Mac OS X requires libusb-1.0 to be built from the source. Download the source
from SourceForge:
http://sourceforge.net/projects/libusb/files/libusb-1.0/
Version 1.0.9 is the latest as of April 2012. From the directory containing
the libusb source download, build it in the standard way:
$ tar xvfj libusb-1.0.9.tar.bz2
$ cd libusb-1.0.9/
$ ./configure
$ make
$ sudo make install
For building a combined 32/64-bit libusb-1.0 library, refer to the
"Optional: Build a combined 32-/64-bit Exodriver on Mac OS X" section.
liblabjackusb Library Script Installation
-----------------------------------
First, go to the Exodriver directory.
To install by script, run the following command:
$ sudo ./install.sh
This script will attempt to build, install, and make any necessary
system configurations.
Alternatively, without using the script go to the liblabjackusb/
directory and run the following commands:
$ cd liblabjackusb/
$ make
$ sudo make install
For building a combined 32/64-bit liblabjackusb library, refer to the
"Optional: Build a combined 32-/64-bit Exodriver on Mac OS X" section.
Compiling and Running the Example Programs
------------------------------------------
The example code/programs use the liblabjackusb library and the labjackusb.h
header files in the liblabjackusb/ directory.
The examples are located in the U3, U6, and UE9 subdirectories in the examples/
directory. To compile the programs go to your device's directory and run
$ cd examples/U6/
$ make
Run one of example programs like this:
$ ./u6BasicConfigU6
Optional: Build a combined 32-/64-bit Exodriver on Mac OS X
-----------------------------------------------------------
These steps are generally not needed, but there are circumstances that require
a combined 32-bit and 64-bit Exodriver. You need both architectures when you
get error messages like the one in "this LabJack forum
topic":http://forums.labjack.com/index.php?showtopic=4983
dlopen(liblabjackusb.dylib, 6): no suitable image found. Did find:
/usr/local/lib/liblabjackusb.dylib: mach-o, but wrong architecture
In this case, a 32-bit process tried to load a 64-bit Exodriver. Here's how it
happened: When following the instructions in the Quickstart, the compiler built
a copy of the Exodriver for its native architecture. On modern Mac OS X
systems, that's x86_64 (64-bit). Verify this by running:
$ file /usr/local/lib/liblabjackusb.dylib
/usr/local/lib/liblabjackusb.dylib: Mach-O 64-bit dynamically linked shared library x86_64
Normally, this is what you want. The programs you will use to call the
Exodriver will also be 64-bit. The built-in Python on Mac OS X, for example, is
compiled for three architectures, including x86_64:
$ file /usr/bin/python
/usr/bin/python: Mach-O universal binary with 3 architectures
/usr/bin/python (for architecture x86_64): Mach-O 64-bit executable x86_64
/usr/bin/python (for architecture i386): Mach-O executable i386
/usr/bin/python (for architecture ppc7400): Mach-O executable ppc
There are some programs on Mac OS X, though, that are not 64-bit (they're i368
only), and they can't load a 64-bit Exodriver. The Python download from
python.org, for example, is 32-bit at the time of this writing. We recommend
using the built-in Python on Mac OS X.
When you must load the Exodriver from a 32-bit process, you must compile
libusb-1.0 and the Exodriver to be combined 32-/64-bit libraries. Start with
libusb-1.0:
$ tar xvfj libusb-1.0.9.tar.bz2
$ cd libusb-1.0.9/
$ export CFLAGS="-arch i386 -arch x86_64"
$ ./configure --disable-dependency-tracking
$ make
$ sudo make install
Confirm it worked by running:
$ file /usr/local/lib/libusb-1.0.dylib
/usr/local/lib/libusb-1.0.dylib: Mach-O universal binary with 2 architectures
/usr/local/lib/libusb-1.0.dylib (for architecture i386): Mach-O dynamically linked shared library i386
/usr/local/lib/libusb-1.0.dylib (for architecture x86_64): Mach-O 64-bit dynamically linked shared library x86_64
After libusb-1.0 is installed correctly, move on to the Exodriver. Find the
Exodriver download directory
$ cd path/to/exodriver
$ cd liblabjackusb/
Now edit the Makefile in a text editor to comment out (put a # sign in front
of) this ARCHFLAGS line:
#ARCHFLAGS =
and uncomment (remove the # sign from) this ARCHFLAGS line two lines below it:
ARCHFLAGS = -arch i386 -arch x86_64
Now build and install the software
$ make clean
$ make
$ sudo make install
Verify that it worked by running:
$ file /usr/local/lib/liblabjackusb.dylib
/usr/local/lib/liblabjackusb.dylib: Mach-O universal binary with 2 architectures
/usr/local/lib/liblabjackusb.dylib (for architecture i386): Mach-O dynamically linked shared library i386
/usr/local/lib/liblabjackusb.dylib (for architecture x86_64): Mach-O 64-bit dynamically linked shared library x86_64
Because libusb-1.0 and the Exodriver are built for the i386 architecture,
32-bit applications can load them.
Uninstalling the Old U3 and UE9 Driver
--------------------------------------
The old U3 and UE9 driver, previous to the libusb 1.0 requirement, used custom
kernel modules, and will conflict with with the current liblabjackusb library.
To uninstall the old driver, delete the liblabjackusb.dylib:
$ sudo rm -f /usr/lib/liblabjackusb.dylib

View File

@@ -0,0 +1,63 @@
Exodriver: Linux (kernel 2.6+) and Mac OS X low-level LabJack U12, U3, U6, UE9,
Digit and T7 USB library 2.0 and C examples
04/01/2014
support@labjack.com
This package contains the liblabjackusb 2.0 USB library for low-level U3, U6,
UE9, Digit and T7 USB communications and C examples for select LabJack devices.
Refer to the INSTALL.Linux or INSTALL.MacOSX file for library requirements,
installation instructions, and compiling information (library and examples).
Note that the Exodriver requires the libusb-1.0 library.
Library source code files are located in the liblabjackusb directory.
C examples are provided for the LabJack U12, U3, U6, and UE9 in the examples
directory. They demonstrate basic open/write/read/close operations using
the liblabjackusb library and low-level function command/responses. Low-level
function documentation can be found in Section 5 of the LabJack U12, U3, U6,
and UE9 User Guides. The u3.h/u6.h/ue9.h, and u3.c/u6.h/ue9.c files contain
helpful functions for opening/closing USB connections, calculate checksums,
retrieving device analog calibration information, etc. There are 5 "easy"
functions (eAIN, eDAC, eDI, eDO, eTCConfig and eTCValues) that are similar to
our Windows LabJackUD driver's "easy" functions. All other .c files are
examples.
USB command/response times for the U3, U6 and UE9 can be found in section 3.1
of their User's Guide and were tested with the Feedback low-level function. USB
Stream times are in Section 3.2. These times were measured in Windows and are
similar in Linux and Mac OS X.
Examples are not provided for the Digit or T7 in this package. Please refer to
the LJM library package and documentation for their API.
The U12 also has a high-level library, which requires this library
(liblabjackusb), that provides the same API as the U12 Windows driver. It can
be downloaded here:
http://labjack.com/support/u12/ljacklm
LICENSE
All exodriver library and example source code are licensed under MIT X11.
Copyright (c) 2009 LabJack Corporation <support@labjack.com>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

View File

@@ -0,0 +1,28 @@
#
# Makefile for Modbus examples
#
TESTMODBUS_SRC=testModbusFunctions.c modbus.c
TESTMODBUS_OBJ=$(TESTMODBUS_SRC:.c=.o)
READMODBUS_SRC=readModbusExample.c modbus.c
READMODBUS_OBJ=$(READMODBUS_SRC:.c=.o)
WRITEMODBUS_SRC=writeModbusExample.c modbus.c
WRITEMODBUS_OBJ=$(WRITEMODBUS_SRC:.c=.o)
CFLAGS+=-Wall -g
LIBS=-lm -llabjackusb
all: testModbusFunctions readModbusExample writeModbusExample
testModbusFunctions: $(TESTMODBUS_OBJ)
$(CC) -o testModbusFunctions $(TESTMODBUS_OBJ) $(LDFLAGS) $(LIBS)
readModbusExample: $(READMODBUS_OBJ)
$(CC) -o readModbusExample $(READMODBUS_OBJ) $(LDFLAGS) $(LIBS)
writeModbusExample: $(WRITEMODBUS_OBJ)
$(CC) -o writeModbusExample $(WRITEMODBUS_OBJ) $(LDFLAGS) $(LIBS)
clean:
rm -f *.o *~ testModbusFunctions readModbusExample writeModbusExample

View File

@@ -0,0 +1,171 @@
/*
* A library to help you build modbus functions for LabJack devices.
*/
/* --------- Static Variables --------- */
static short nextTransactionId = 0x37;
/* --------- Read Functions --------- */
int buildReadHoldingRegistersPacket( unsigned char* sendBuffer, int startReg, int numRegs, int unitId, int prependZeros ) {
int offset = 0;
if(prependZeros != 0){
sendBuffer[0] = 0;
sendBuffer[1] = 0;
offset = 2;
}
// Bytes 0 and 1 are TransID
sendBuffer[0+offset] = (unsigned char)((nextTransactionId >> 8) & 0xff);
sendBuffer[1+offset] = (unsigned char)(nextTransactionId & 0xff);
nextTransactionId++;
// Bytes 2 and 3 are ProtocolID, set to 0
sendBuffer[2+offset] = 0;
sendBuffer[3+offset] = 0;
// Bytes 4 and 5 are length.
sendBuffer[4+offset] = 0;
sendBuffer[5+offset] = 6;
// Byte 6 is Unit ID.
sendBuffer[6+offset] = unitId;
// Byte 7 is Read Holding Registers ( function # 3 )
sendBuffer[7+offset] = 3;
// Bytes 8 and 9 are Address
sendBuffer[8+offset] = (unsigned char)((startReg >> 8) & 0xff);
sendBuffer[9+offset] = (unsigned char)(startReg & 0xff);
//Bytes 10 and 11 are NumRegs
sendBuffer[10+offset] = (unsigned char)((numRegs >> 8) & 0xff);
sendBuffer[11+offset] = (unsigned char)(numRegs & 0xff);
return 9+(numRegs*2);
}
float parseFPRegisterResponse(unsigned char* recBuffer, int offset) {
unsigned char fBuffer[4];
float* fPointer;
fBuffer[0] = recBuffer[offset + 3];
fBuffer[1] = recBuffer[offset + 2];
fBuffer[2] = recBuffer[offset + 1];
fBuffer[3] = recBuffer[offset];
fPointer = (float*)fBuffer;
return *fPointer;
}
int parseIntRegisterResponse(unsigned char* recBuffer, int offset) {
unsigned char iBuffer[4];
int* iPointer;
iBuffer[0] = recBuffer[offset + 3];
iBuffer[1] = recBuffer[offset + 2];
iBuffer[2] = recBuffer[offset + 1];
iBuffer[3] = recBuffer[offset];
iPointer = (int*)iBuffer;
return *iPointer;
}
short parseShortRegisterResponse(unsigned char* recBuffer, int offset) {
unsigned char sBuffer[4];
short* sPointer;
sBuffer[0] = recBuffer[offset + 1];
sBuffer[1] = recBuffer[offset];
sPointer = (short*)sBuffer;
return *sPointer;
}
int buildWriteHoldingRegistersPacket(unsigned char* sendBuffer, int startReg, int numRegs, int unitId, int prependZeros) {
int offset = 0;
if(prependZeros != 0){
sendBuffer[0] = 0;
sendBuffer[1] = 0;
offset = 2;
}
// Bytes 0 and 1 are TransID
sendBuffer[0+offset] = (unsigned char)((nextTransactionId >> 8) & 0xff);
sendBuffer[1+offset] = (unsigned char)(nextTransactionId & 0xff);
nextTransactionId++;
// Bytes 2 and 3 are ProtocolID, set to 0
sendBuffer[2+offset] = 0;
sendBuffer[3+offset] = 0;
// Bytes 4 and 5 are length.
sendBuffer[4+offset] = 0;
sendBuffer[5+offset] = 7 + (numRegs * 2);
// Byte 6 is Unit ID.
sendBuffer[6+offset] = unitId;
// Byte 7 is Read Holding Registers ( function # 3 )
sendBuffer[7+offset] = 16;
// Bytes 8 and 9 are Address
sendBuffer[8+offset] = (unsigned char)((startReg >> 8) & 0xff);
sendBuffer[9+offset] = (unsigned char)(startReg & 0xff);
// Bytes 10 and 11 are NumRegs
sendBuffer[10+offset] = (unsigned char)((numRegs >> 8) & 0xff);
sendBuffer[11+offset] = (unsigned char)(numRegs & 0xff);
// Byte 12 is Byte Count, or 2 * numReg
sendBuffer[12+offset] = (unsigned char)((numRegs * 2) & 0xff);
// The rest of the bytes are up to the user.
return 12; // Write Registers always return 12 bytes.
}
int putFPIntoBuffer( unsigned char* sendBuffer, int offset, float value) {
unsigned char* bPointer;
bPointer = (unsigned char*)&value;
sendBuffer[offset] = bPointer[3];
sendBuffer[offset+1] = bPointer[2];
sendBuffer[offset+2] = bPointer[1];
sendBuffer[offset+3] = bPointer[0];
return 0;
}
int putIntIntoBuffer( unsigned char* sendBuffer, int offset, int value ) {
unsigned char* bPointer;
bPointer = (unsigned char*)&value;
sendBuffer[offset] = bPointer[3];
sendBuffer[offset+1] = bPointer[2];
sendBuffer[offset+2] = bPointer[1];
sendBuffer[offset+3] = bPointer[0];
return 0;
}
int putShortIntoBuffer( unsigned char* sendBuffer, int offset, short value ) {
unsigned char* bPointer;
bPointer = (unsigned char*)&value;
sendBuffer[offset] = bPointer[1];
sendBuffer[offset+1] = bPointer[0];
return 0;
}

View File

@@ -0,0 +1,179 @@
/*
* A library to help you build Modbus functions for LabJack devices. For more
* information on Modbus, please see:
*
* http://labjack.com/support/modbus
*
* The flow for working with a LabJack device should go like this:
* 1. Open the device (LJUSB_OpenDevice)
* 2. Build the packet to write using buildReadHoldingRegistersPacket
* 3. Write the packet to the device (LJUSB_Write)
* 4. Read the result (LJUSB_Read)
* 5. Parse the result using a parse*RegisterResponse function
* 6. Close the device (LJUSB_CloseDevice)
*
* For writing to registers, the flow goes like this:
* 1. Open the device (LJUSB_OpenDevice)
* 2. Build the packet to write using buildWriteHoldingRegistersPacket
* 3. Insert the values to write to packet with put*ToBuffer functions
* 4. Write the packet to the device (LJUSB_Write)
* 5. Read the result (LJUSB_Read)
* 6. Close the device (LJUSB_CloseDevice)
*/
#ifndef _MODBUS_H_
#define _MODBUS_H_
/* --------- Read Functions --------- */
int buildReadHoldingRegistersPacket( unsigned char* sendBuffer, int startReg, int numRegs, int unitId, int prependZeros );
/* buildReadHoldingRegistersPacket takes a byte array and sets the bytes to be a
* Modbus packet to read a register. It returns the number of bytes to read.
*
* Args:
* - sendBuffer: an array of length 12 or 14 (if prependZeros != 0 )
* - startReg: The starting register.
* - numReg: The number of registers to read starting at startReg.
* - unitId: For U3/U6/UE9, always pass 0.
* - prependZeros: If this packet is going to be sent over USB, the UD family of
* devices require that the Modbus packet start with 2 extra
* bytes of zeros.
*
* Example Usage to read register 0 (AIN0):
unsigned char sendBuffer[14];
int startReg = 0; // Start at register 0
int numRegs = 2; // AIN0 is a floating point value, so need to read 2 registers
int unitId = 0; // For UD family devices, always 0
int prependZeros = 1; // For UD family devices on USB, always 1
int numBytesToRead;
numBytesToRead = buildReadHoldingRegistersPacket(
sendBuffer, startReg, numRegs, unitId, prependZeros );
*/
float parseFPRegisterResponse(unsigned char* recBuffer, int offset);
/*
* parseFPRegisterResponse takes the recBuffer and an offset, and returns the
* floating point value. recBuffer must have a length equal to offset+3.
*
* Args:
* - recBuffer: the buffer that was read from the device.
* - offset: the offset to start reading from. Usually, 9.
*
* Example Usage:
unsigned char recBuffer = { 0x40, 0x0, 0x0, 0x0 };
float value = parseFPRegisterResponse(recBuffer, 0);
// value -> 2.0
*/
int parseIntRegisterResponse(unsigned char* recBuffer, int offset);
/*
* parseIntRegisterResponse takes the recBuffer and an offset, and returns the
* integer value. recBuffer must have a length equal to offset+4.
*
* Args:
* - recBuffer: the buffer that was read from the device.
* - offset: the offset to start reading from. Usually, 9.
*
* Example Usage:
unsigned char recBuffer = { 0x0, 0x84, 0x5F, 0xED };
int value = parseIntRegisterResponse(recBuffer, 0);
// value -> 8675309
*/
short parseShortRegisterResponse(unsigned char* recBuffer, int offset);
/*
* parseShortRegisterResponse takes the recBuffer and an offset, and returns the
* short value. recBuffer must have a length equal to offset+2.
*
* Args:
* - recBuffer: the buffer that was read from the device.
* - offset: the offset to start reading from. Usually, 9.
*
* Example Usage:
unsigned char recBuffer = { 0x2, 0x10 };
short value = parseShortRegisterResponse(recBuffer, 0);
// value -> 528
*/
/* --------- Write Functions --------- */
int buildWriteHoldingRegistersPacket(unsigned char* sendBuffer, int startReg, int numReg, int unitId, int prependZeros);
/* buildReadHoldingRegistersPacket takes a byte array and sets the bytes to be a
* Modbus packet to write registers. It returns the number of bytes to read.
* After calling this function, you must use the put*ToBuffer functions to set
* the values on the end.
*
* Args:
* - sendBuffer: an array of length 13+(2*numReg) (+2 if prependZeros != 0 )
* - startReg: The starting register.
* - numReg: The number of registers to write starting at startReg.
* - unitId: For U3/U6/UE9, always pass 0.
* - prependZeros: If this packet is going to be sent over USB, the UD family of
* devices require that the Modbus packet start with 2 extra
* bytes of zeros.
*
* Example Usage to write 2.0 to register 5000 (DAC0):
int startReg = 0; // Start at register 0
int numRegs = 2; // DAC0 is a floating point value, so need to read 2 registers
int unitId = 0; // For UD family devices, always 0
int prependZeros = 1; // For UD family devices on USB, always 1
unsigned char sendBuffer[19]; // 13 + (2*2) + 2 = 19
int numBytesToRead;
numBytesToRead = buildWriteHoldingRegistersPacket(
sendBuffer, startReg, numRegs, unitId, prependZeros );
putFPIntoBuffer(sendBuffer, 15, 2.0);
//sendBuffer => [0x0, 0x0, 0x0, 0x38, 0x0, 0x0, 0x0, 0xB, 0x0, 0x10, 0x0, 0x0,
// 0x0, 0x2, 0x4, 0x40, 0x0, 0x0, 0x0]
*/
int putFPIntoBuffer( unsigned char* sendBuffer, int offset, float value);
/*
* putFPIntoBuffer writes the bytes of value into sendBuffer at offset.
* sendBuffer must have a length equal to offset+4. Returns zero for success.
*
* Args:
* - sendBuffer: the buffer to be written to the device.
* - offset: the offset to start overwriting. Usually, 15.
* - value: a float of the value to write.
*
* Example Usage:
unsigned char sendBuffer[4];
putFPIntoBuffer(sendBuffer, 0, 2.0);
// sendBuffer -> [0x40, 0x0, 0x0, 0x0]
*/
int putIntIntoBuffer( unsigned char* sendBuffer, int offset, int value );
/*
* putIntIntoBuffer writes the bytes of value into sendBuffer at offset.
* sendBuffer must have a length equal to offset+4. Returns zero for success.
*
* Args:
* - sendBuffer: the buffer to be written to the device.
* - offset: the offset to start overwriting. Usually, 15.
* - value: an int of the value to write.
*
* Example Usage:
unsigned char sendBuffer[4];
putIntIntoBuffer(sendBuffer, 0, 8675309);
// sendBuffer -> [0x0, 0x84, 0x5F, 0xED]
*/
int putShortIntoBuffer( unsigned char* sendBuffer, int offset, short value );
/*
* putShortIntoBuffer inserts the bytes of value into sendBuffer at offset.
* sendBuffer must have a length equal to offset+2. Returns zero for success.
*
* Args:
* - sendBuffer: the buffer to be written to the device.
* - offset: the offset to start overwriting. Usually, 15.
* - value: an int of the value to write.
*
* Example Usage:
unsigned char sendBuffer[2];
putShortIntoBuffer(sendBuffer, 0, (short)528);
// sendBuffer -> [0x2, 0x10]
*/
#endif // _MODBUS_H_

View File

@@ -0,0 +1,105 @@
/*
* A simple example that shows how to used modbus.h with the Exodriver by
* reading AIN0 and printing it to stdout.
*
* The most important thing to get right are your buffer lengths. In the case of
* read register, it's easy. The command to be written is always 14 bytes. The
* response is 9 + (2 * number of registers being read). So, if you are reading
* three registers, your receive buffer needs to be 9 + (3 * 2), or 15 bytes.
* What those bytes mean will depend on the register. Make sure to check out the
* Modbus support page:
* http://labjack.com/support/modbus
*/
#include <stdio.h>
#include "modbus.h"
#include "labjackusb.h"
// Set to 3 (U3), 6 (U6), or 9 (UE9).
#define DEVICE_TYPE 3
// Read Holding Register Packets are always 14 bytes over USB
#define READ_REGISTER_SEND_LENGTH 14
int main() {
HANDLE devHandle;
int i;
int r = 0; // For checking return values
int startReg = 0; // Start at register 0
int numRegs = 2; // AIN0 is floating point, so need to read 2 registers
int unitId = 0; // For UD family devices, always 0
int prependZeros = 1; // For UD family devices on USB, always 1
BYTE sendBuffer[READ_REGISTER_SEND_LENGTH]; // 2 (for extra zeros) + 12
int numBytesToRead = 13; // 9 + (2*numReg)
BYTE recBuffer[13]; // Same as numBytesToRead
float value; // Will hold parsed result
// Open the device
devHandle = LJUSB_OpenDevice(1, 0, DEVICE_TYPE);
if(devHandle <= 0){
printf("ERROR: Couldn't find a LabJack to open.\n");
return -1;
}
if(DEVICE_TYPE == 3){
printf("Opened first found U3.\n");
}
else if(DEVICE_TYPE == 6) {
printf("Opened first found U6.\n");
}
else {
printf("Opened first found UE9.\n");
}
// Build the packet.
numBytesToRead = buildReadHoldingRegistersPacket(sendBuffer, startReg, numRegs, unitId, prependZeros);
printf("Built Read Holding Registers Packet to read register 0 (AIN0).\n");
// Send packet to the device.
r = LJUSB_Write(devHandle, sendBuffer, READ_REGISTER_SEND_LENGTH);
if( r != READ_REGISTER_SEND_LENGTH ){
printf("ERROR: An error occurred while writing to the device.");
LJUSB_CloseDevice(devHandle);
return -1;
}
printf("Wrote command to device.\n");
printf("Sent = [");
for( i = 0; i < READ_REGISTER_SEND_LENGTH-1; i++){
printf("0x%X, ", sendBuffer[i]);
}
printf("0x%X]\n\n", sendBuffer[READ_REGISTER_SEND_LENGTH-1]);
// Read the response from the device.
r = LJUSB_Read(devHandle, recBuffer, numBytesToRead);
if( r != numBytesToRead ){
printf("ERROR: An error occurred while reading from the device.");
LJUSB_CloseDevice(devHandle);
return -1;
}
printf("Read the response.\n");
printf("Read = [");
for( i = 0; i < numBytesToRead-1; i++){
printf("0x%X, ", recBuffer[i]);
}
printf("0x%X]\n\n", recBuffer[numBytesToRead-1]);
// Parse out the value.
value = parseFPRegisterResponse(recBuffer, 9);
printf("AIN0: %f\n\n", value);
// Close the device.
LJUSB_CloseDevice(devHandle);
printf("Closed Device.\n");
return 0;
}

View File

@@ -0,0 +1,83 @@
/*
* This file shows how to uses the functions in modbus.h without requiring a
* LabJack, the Exodriver, or libusb.
*/
#include <stdio.h>
#include "modbus.h"
int main() {
int i;
printf("Modbus Function tests:\n\n");
// Build a packet to read register 0 (AIN0) and store it in sendBuffer
unsigned char sendBuffer[14];
int startReg = 0; // Start at register 0
int numRegs = 2; // AIN0 is floating point, so need to read 2 registers
int unitId = 0; // For UD family devices, always 0
int prependZeros = 1; // For UD family devices on USB, always 1
int numBytesToRead;
numBytesToRead = buildReadHoldingRegistersPacket( sendBuffer, startReg, numRegs, unitId, prependZeros );
printf("buildReadHoldingRegistersPacket:\n sendBuffer: [");
for(i = 0; i < 13; i++) {
printf("0x%X, ", sendBuffer[i]);
}
printf("0x%X]\n numBytesToRead: %d\n\n", sendBuffer[13], numBytesToRead);
// Parse a float from a byte array.
unsigned char recBuffer[] = { 0x40, 0x0, 0x0, 0x0 };
float fValue = parseFPRegisterResponse(recBuffer, 0);
printf("parseFPRegister: [0x40, 0x0, 0x0, 0x0] => %f\n\n", fValue);
// Parse an int from a byte array.
recBuffer[0] = 0x0;
recBuffer[1] = 0x84;
recBuffer[2] = 0x5F;
recBuffer[3] = 0xED;
int iValue = parseIntRegisterResponse(recBuffer, 0);
printf("parseIntRegister: [0x0, 0x84, 0x5F, 0xED] => %i\n\n", iValue);
// Parse a short from a byte array.
recBuffer[0] = 0x2;
recBuffer[1] = 0x10;
short sValue = parseShortRegisterResponse(recBuffer, 0);
printf("parseShortRegister: [0x2, 0x10] => %i\n\n", sValue);
// Start Write Functions
// Build an array of bytes to write 2.0, 8675309, and 528 starting at 0
startReg = 0; // Start at register 0
numRegs = 5; // 1 float (2 registers), 1 int (2 registers), 1 short (1 reg)
unitId = 0; // For UD family devices, always 0
prependZeros = 1; // For UD family devices on USB, always 1
unsigned char writeBuffer[25]; // 13 + (2*5) + 2 = 25
numBytesToRead = buildWriteHoldingRegistersPacket(writeBuffer, startReg, numRegs, unitId, prependZeros);
printf("buildWriteHoldingRegistersPacket:\n writeBuffer: [");
for(i = 0; i < 24; i++) {
printf("0x%X, ", writeBuffer[i]);
}
printf("0x%X]\n numBytesToRead: %d\n\n", writeBuffer[24], numBytesToRead);
putFPIntoBuffer(writeBuffer, 15, 2.0);
printf("putFPIntoBuffer: Appended 2.0 to packet.\n\n");
putIntIntoBuffer(writeBuffer, 19, 8675309);
printf("putIntIntoBuffer: Appended 8675309 to packet.\n\n");
putShortIntoBuffer(writeBuffer, 23, 528);
printf("putShortIntoBuffer: Appended 528 to packet.\n\n");
printf("Result:\n writeBuffer: [");
for(i = 0; i < 24; i++) {
printf("0x%X, ", writeBuffer[i]);
}
printf("0x%X]\n\n", writeBuffer[24]);
return 0;
}

View File

@@ -0,0 +1,124 @@
/*
* A simple example that shows how to used modbus.h with the Exodriver by
* writing 2.0 to DAC0.
*
* The most important thing to get right are your buffer lengths. With write
* register, it can be a little tricky. The base packet is 13 bytes, then 2
* extra bytes for every register you're going to write to. Because of a weird
* quirk with LabJacks, you need to prepend two bytes of zeros. This makes the
* equation as follows: send buffer length = 2 + 13 + (2 * number of registers).
*
* The response is always 12 bytes, so that part is easy.
*
* Another possible point of confusion with writing is that you have to setup
* the basic bytes with buildWriteHoldingRegistersPacket then insert the values
* with put*IntoBuffer functions. Your first value should always go in offset
* 15. If you are putting multiple values in one packet, the offset of the
* second value will depend on the type of the first value. Floats and Integers
* will both take 4 bytes, and Shorts will only take 2. So, if you are writing a
* Float then a Short, the Float will go in offset 15, the Short in offset 19.
* If it's a Short than a Float, the Short will have offset 15, and the Float
* should be put in offset 17.
*
* For more information about Modbus, please see the support page:
* http://labjack.com/support/modbus
*/
#include <stdio.h>
#include "modbus.h"
#include "labjackusb.h"
// Set to 3 (U3), 6 (U6), or 9 (UE9).
#define DEVICE_TYPE 3
// Set to what you want the DAC to output.
#define DAC_VALUE 2.0f
// 13 + (2*numReg) + 2 = 13 + (2*2) + 2 = 19
#define WRITE_REGISTER_SEND_LENGTH 19
// Write Holding Register Response Packets are always 12 bytes
#define WRITE_REGISTER_REC_LENGTH 12
int main() {
HANDLE devHandle;
int i;
int r = 0; // For checking return values
int startReg = 5000; // Start at register 5000
int numRegs = 2; // DAC0 is floating point, so need to write 2 registers
int unitId = 0; // For UD family devices, always 0
int prependZeros = 1; // For UD family devices on USB, always 1
int numBytesToRead = WRITE_REGISTER_REC_LENGTH;
BYTE sendBuffer[WRITE_REGISTER_SEND_LENGTH];
BYTE recBuffer[WRITE_REGISTER_REC_LENGTH]; // Same as numBytesToRead
// Open the device
devHandle = LJUSB_OpenDevice(1, 0, DEVICE_TYPE);
if(devHandle <= 0){
printf("ERROR: Couldn't find a LabJack to open.");
return -1;
}
if(DEVICE_TYPE == 3){
printf("Opened first found U3.\n");
}
else if(DEVICE_TYPE == 6) {
printf("Opened first found U6.\n");
}
else {
printf("Opened first found UE9.\n");
}
// Build the packet.
numBytesToRead = buildWriteHoldingRegistersPacket(sendBuffer, startReg, numRegs, unitId, prependZeros);
printf("Built Write Holding Registers Packet to write register 5000 (DAC0).\n");
// Puts DAC_VALUE into the buffer.
putFPIntoBuffer(sendBuffer, 15, DAC_VALUE);
printf("Added value %.2f to buffer.\n", DAC_VALUE);
// Send packet to the device.
r = LJUSB_Write(devHandle, sendBuffer, WRITE_REGISTER_SEND_LENGTH);
if( r != WRITE_REGISTER_SEND_LENGTH ){
printf("ERROR: An error occurred while writing to the device.");
LJUSB_CloseDevice(devHandle);
return -1;
}
printf("Wrote command to device.\n");
printf("Sent = [");
for( i = 0; i < WRITE_REGISTER_SEND_LENGTH-1; i++){
printf("0x%X, ", sendBuffer[i]);
}
printf("0x%X]\n\n", sendBuffer[WRITE_REGISTER_SEND_LENGTH-1]);
// Read the response from the device.
r = LJUSB_Read(devHandle, recBuffer, numBytesToRead);
if( r != numBytesToRead ){
printf("ERROR: An error occurred while reading from the device.\n r = %i", r);
LJUSB_CloseDevice(devHandle);
return -1;
}
printf("Read the response.\n");
printf("Read = [");
for( i = 0; i < numBytesToRead-1; i++){
printf("0x%X, ", recBuffer[i]);
}
printf("0x%X]\n\n", recBuffer[numBytesToRead-1]);
// Close the device.
LJUSB_CloseDevice(devHandle);
printf("Closed Device.\n");
return 0;
}

View File

@@ -0,0 +1,19 @@
#
# Makefile for U12 examples
#
U12AISAMPLE_SRC=u12AISample.c
U12AISAMPLE_OBJ=$(U12AISAMPLE_SRC:.c=.o)
SRCS=$(wildcard *.c)
HDRS=$(wildcard *.h)
CFLAGS+=-Wall -g
LIBS=-lm -llabjackusb
all: u12AISample
u12AISample: $(U12AISAMPLE_OBJ) $(HDRS)
$(CC) -o u12AISample $(U12AISAMPLE_OBJ) $(LDFLAGS) $(LIBS)
clean:
rm -f *.o *~ u12AISample

View File

@@ -0,0 +1,157 @@
/*
An example that shows a minimal use of Exodriver without the use of functions
hidden in header files.
You can compile this example with the following command:
$ g++ -lm -llabjackusb u12AISample.c
It is also included in the Makefile.
*/
/* Includes */
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include "labjackusb.h"
#include <libusb-1.0/libusb.h>
// All U12 commands are 8 bytes.
#define U12_COMMAND_LENGTH 8
/* LabJack Related Helper Functions Protoypes */
int writeRead(HANDLE devHandle, BYTE * sendBuffer, BYTE * recBuffer );
// Demonstrates how to build the AIStream packet.
void buildAISampleBytes(BYTE * sendBuffer);
// Demonstrates how to parse the response of AIStream.
void parseAISampleBytes(BYTE * recBuffer);
int main() {
// Setup the variables we will need.
int r = 0; // For checking return values
HANDLE devHandle = 0;
BYTE sendBuffer[U12_COMMAND_LENGTH], recBuffer[U12_COMMAND_LENGTH];
// Open the U12
devHandle = LJUSB_OpenDevice(1, 0, U12_PRODUCT_ID);
if( devHandle == NULL ) {
printf("Couldn't open U12. Please connect one and try again.\n");
exit(-1);
}
// Builds the AISample command
buildAISampleBytes(sendBuffer);
// Write the command, and read the response.
r = writeRead(devHandle, sendBuffer, recBuffer );
// If the U12 is freshly plugged in, then it will not respond to the
// first command. Write it again.
if( r == -1){
r = writeRead(devHandle, sendBuffer, recBuffer );
if(r != 0){
// If you still have errors after the first try, then you have
// bigger problems.
printf("Command timed out twice. Exiting...");
LJUSB_CloseDevice(devHandle);
exit(-1);
}
}
// Parse the response into something useful
parseAISampleBytes(recBuffer);
//Close the device.
LJUSB_CloseDevice(devHandle);
return 0;
}
/* ------------- LabJack Related Helper Functions Definitions ------------- */
int writeRead(HANDLE devHandle, BYTE * sendBuffer, BYTE * recBuffer ) {
int r = 0;
// Write the command to the device.
// LJUSB_Write( handle, sendBuffer, length of sendBuffer )
r = LJUSB_Write( devHandle, sendBuffer, U12_COMMAND_LENGTH );
if( r != U12_COMMAND_LENGTH ) {
printf("An error occurred when trying to write the buffer. The error was: %d\n", errno);
// *Always* close the device when you error out.
LJUSB_CloseDevice(devHandle);
exit(-1);
}
// Read the result from the device.
// LJUSB_Read( handle, recBuffer, number of bytes to read)
r = LJUSB_Read( devHandle, recBuffer, U12_COMMAND_LENGTH );
if( r != U12_COMMAND_LENGTH ) {
if(errno == LIBUSB_ERROR_TIMEOUT) {
return -1;
}
printf("An error occurred when trying to read from the U12. The error was: %d\n", errno);
LJUSB_CloseDevice(devHandle);
exit(-1);
}
return 0;
}
// Uses information from section 5.1 of the U12 User's Guide to make a AISample
// packet.
// http://labjack.com/support/u12/users-guide/5.1
void buildAISampleBytes(BYTE * sendBuffer) {
// Build up the bytes
sendBuffer[0] = 8; // Set PGAMUX for single-ended AI0
sendBuffer[1] = 9; // Set PGAMUX for single-ended AI1
sendBuffer[2] = 10; // Set PGAMUX for single-ended AI2
sendBuffer[3] = 11; // Set PGAMUX for single-ended AI3
sendBuffer[4] = 1; // UpdateIO = 0, LEDState = 1
sendBuffer[5] = 192; // 0b11000000 = (AISample)
sendBuffer[6] = 0; // XXXXXXXX
sendBuffer[7] = 0; // Echo Value
// The bytes have been set. We are ready to write to the U12.
}
// Parses the AISample packet into something useful.
void parseAISampleBytes(BYTE * recBuffer){
int temp;
double ai0, ai1, ai2, ai3;
// Apply the single-ended conversion to results
temp = (recBuffer[2] >> 4) & 0xf;
temp = (temp << 8) + recBuffer[3];
ai0 = ((double)temp * 20.0 / 4096.0) - 10;
temp = recBuffer[2] & 0xf;
temp = (temp << 8) + recBuffer[4];
ai1 = ((double)temp * 20.0 / 4096.0) - 10;
temp = (recBuffer[5] >> 4) & 0xf;
temp = (temp << 8) + recBuffer[6];
ai2 = ((double)temp * 20.0 / 4096.0) - 10;
temp = recBuffer[5] & 0xf;
temp = (temp << 8) + recBuffer[7];
ai3 = ((double)temp * 20.0 / 4096.0) - 10;
printf("Results of AISample:\n");
printf(" AI0 = %f\n", ai0);
printf(" AI1 = %f\n", ai1);
printf(" AI2 = %f\n", ai2);
printf(" AI3 = %f\n", ai3);
printf(" PGA Overvoltage = %d\n", (recBuffer[0] >> 4) & 1);
printf(" IO3 to IO0 States = %d\n", recBuffer[0] & 15);
printf(" TimerCounterMask = %d\n", recBuffer[22]);
}

View File

@@ -0,0 +1,49 @@
#
# Makefile for U3 examples
#
U3FEEDBACK_SRC=u3Feedback.c u3.c
U3FEEDBACK_OBJ=$(U3FEEDBACK_SRC:.c=.o)
U3CONFIGU3_SRC=u3BasicConfigU3.c
U3CONFIGU3_OBJ=$(U3CONFIGU3_SRC:.c=.o)
U3ALLIO_SRC=u3allio.c u3.c
U3ALLIO_OBJ=$(U3ALLIO_SRC:.c=.o)
U3STREAM_SRC=u3Stream.c u3.c
U3STREAM_OBJ=$(U3STREAM_SRC:.c=.o)
U3EFUNCTIONS_SRC=u3EFunctions.c u3.c
U3EFUNCTIONS_OBJ=$(U3EFUNCTIONS_SRC:.c=.o)
U3LJTDAC_SRC=u3LJTDAC.c u3.c
U3LJTDAC_OBJ=$(U3LJTDAC_SRC:.c=.o)
SRCS=$(wildcard *.c)
HDRS=$(wildcard *.h)
CFLAGS +=-Wall -g
LIBS=-lm -llabjackusb
all: u3BasicConfigU3 u3Feedback u3allio u3Stream u3EFunctions u3LJTDAC
u3BasicConfigU3: $(U3CONFIGU3_OBJ)
$(CC) -o u3BasicConfigU3 $(U3CONFIGU3_OBJ) $(LDFLAGS) $(LIBS)
u3Feedback: $(U3FEEDBACK_OBJ) $(HDRS)
$(CC) -o u3Feedback $(U3FEEDBACK_OBJ) $(LDFLAGS) $(LIBS)
u3allio: $(U3ALLIO_OBJ) $(HDRS)
$(CC) -o u3allio $(U3ALLIO_OBJ) $(LDFLAGS) $(LIBS)
u3Stream: $(U3STREAM_OBJ) $(HDRS)
$(CC) -o u3Stream $(U3STREAM_OBJ) $(LDFLAGS) $(LIBS)
u3EFunctions: $(U3EFUNCTIONS_OBJ) $(HDRS)
$(CC) -o u3EFunctions $(U3EFUNCTIONS_OBJ) $(LDFLAGS) $(LIBS)
u3LJTDAC: $(U3LJTDAC_OBJ) $(HDRS)
$(CC) -o u3LJTDAC $(U3LJTDAC_OBJ) $(LDFLAGS) $(LIBS)
clean:
rm -f *.o *~ u3Feedback u3BasicConfigU3 u3allio u3Stream u3EFunctions u3LJTDAC

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,691 @@
//Author: LabJack
//December 27, 2011
//Header for U3 example helper functions.
//
//History
//-added easy functions
//-added I2C function and LJTDAC functions and structure (09/04/2007)
//-fixed memory leak in ehFeedback and I2C functions (09/27/2007)
//-fixed some bugs in "easy" functions (09/27/2007)
//-added U3-LV/HV support (04/07/2008)
//-fixed bug in eAIN for positive channel 30 - temp sensor (04/25/2008)
//-Modified calibration constants structs. Modified the names and code of the
// functions that apply the calibration constants. (06/25/2009)
//-Replaced LJUSB_BulkWrite/Read with LJUSB_write/Read calls. Added serial
// number support to openUSBConnection. (12/27/2011)
#ifndef U3_H_
#define U3_H_
#include <sys/time.h>
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#include "labjackusb.h"
typedef unsigned char uint8;
typedef unsigned short uint16;
typedef unsigned int uint32;
//Structure for storing calibration constants
struct U3_CALIBRATION_INFORMATION {
uint8 prodID;
double hardwareVersion; //helps to determine which calibration calculations
//to use
int highVoltage; //indicates if the device is U3-HV
double ccConstants[20];
/*
Calibration constants order
0 - LV AIN SE Slope
1 - LV AIN SE Offset
2 - LV AIN Diff Slope
3 - LV AIN Diff Offset
4 - DAC0 Slope
5 - DAC0 Offset
6 - DAC1 Slope
7 - DAC1 Offset
8 - Temp Slope
9 - Vref @Cal
10 - Vref*1.5 @Cal
11 - Vreg @Cal
12 - HV AIN0 Slope
13 - HV AIN1 Slope
14 - HV AIN2 Slope
15 - HV AIN3 Slope
16 - HV AIN0 Offset
17 - HV AIN1 Offset
18 - HV AIN2 Offset
19 - HV AIN3 Offset
*/
};
typedef struct U3_CALIBRATION_INFORMATION u3CalibrationInfo;
//Structure for storing LJTDAC calibration constants
struct U3_TDAC_CALIBRATION_INFORMATION {
uint8 prodID;
double ccConstants[4];
/*
DAC Calibration constants order
0 - SlopeA;
1 - OffsetA;
2 - SlopeB;
3 - OffsetB;
*/
};
typedef struct U3_TDAC_CALIBRATION_INFORMATION u3TdacCalibrationInfo;
/* Functions */
void normalChecksum( uint8 *b,
int n);
//Adds checksum to a data packet for normal command format.
//b = data packet for normal command
//n = size of data packet
void extendedChecksum( uint8 *b,
int n);
//Adds checksum to a data packet for extended command format.
//b = data packet for extended command
//n = size of data packet
uint8 normalChecksum8( uint8 *b,
int n);
//Returns the Checksum8 for a normal command data packet.
//b = data packet for normal command
//n = size of data packet
uint16 extendedChecksum16( uint8 *b,
int n);
//Returns the Checksum16 for a extended command data packet.
//b = data packet for extended command
//n = size of data packet
uint8 extendedChecksum8( uint8 *b);
//Returns the Checksum8 for a extended command data packet.
//b = data packet for extended command
HANDLE openUSBConnection( int localID);
//Opens a U3 connection over USB. Returns NULL on failure, or a HANDLE on
//success.
//localID = the local ID or serial number of the U3 you want to open
void closeUSBConnection( HANDLE hDevice);
//Closes a HANDLE to a U3 device.
long getTickCount();
//Returns the number of milliseconds that has elasped since the system was
//started.
long getCalibrationInfo( HANDLE hDevice,
u3CalibrationInfo *caliInfo);
//Gets calibration information from memory blocks 0-4 of a U3. Returns the
//calibration information in a calibrationInfo structure.
//hDevice = handle to a U3 device
//caliInfo = structure where calibrarion information will be stored
long getTdacCalibrationInfo( HANDLE hDevice,
u3TdacCalibrationInfo *caliInfo,
uint8 DIOAPinNum);
//Gets calibration information from the EEPROM of a LJTick-DAC (LJTDAC).
//Returns the calibration information in a u3TdacCalibrationInfo structure.
//hDevice = handle to a U3 device
//caliInfo = structure where LJTDAC calibration information will be stored
//DIOAPinNum = The U3 digital IO line where the LJTDAC DIOA pin is connected.
// The DIOB pin is assumed to be the next digital IO line.
double FPuint8ArrayToFPDouble( uint8 *buffer,
int startIndex);
//Converts a fixed point byte array (starting a startIndex) to a floating point
//double value. This function is used primarily by getCalibrationInfo.
long isCalibrationInfoValid(u3CalibrationInfo *caliInfo);
//Performs a simple check to determine if the caliInfo struct was set up by
//getCalibrationInfo. Returns 0 if caliInfo is not valid, or 1 if it is.
//caliInfo = structure where calibrarion information is stored
long isTdacCalibrationInfoValid(u3TdacCalibrationInfo *caliInfo);
//Performs a simple check to determine if the caliInfo struct was set up by
//getLJTDACCalibrationInfo. Returns 0 if caliInfo is not valid, or 1 if it is.
//caliInfo = structure where LJTDAC calibration information is stored
long getAinVoltCalibrated( u3CalibrationInfo *caliInfo,
int dac1Enabled,
uint8 negChannel,
uint16 bytesVolt,
double *analogVolt);
//Translates the binary AIN reading from the U3, to a voltage value
//(calibrated) in Volts. Call getCalibrationInfo first to set up caliInfo.
//Returns -1 on error, 0 on success.
//This function is for U3 hardware versions 1.20 and 1.21. Function will also
//work for hardware version 1.30 U3-LV, but not U3-HV.
//caliInfo = structure where calibrarion information is stored
//dac1Enabled = If this is nonzero (True), then it is indicated that DAC1 is
// enabled and analog voltage will be calculated with Vreg. If
// this is 0 (False), then it is indicated that DAC1 is disabled
// and the analog voltage will be calculated with the AIN slopes
// and offsets.
//negChannel = the negative channel of the differential analog reading
//bytesVolt = the 2 byte voltage that will be converted
//analogVolt = the converted analog voltage
long getAinVoltCalibrated_hw130( u3CalibrationInfo *caliInfo,
uint8 positiveChannel,
uint8 negChannel,
uint16 bytesVolt,
double *analogVolt);
//Translates the binary AIN reading from the U3, to a voltage value
//(calibrated) in Volts. Call getCalibrationInfo first to set up caliInfo.
//Returns -1 on error, 0 on success.
//This function is for U3 hardware versions 1.30 (U3-LV/HV).
//caliInfo = structure where calibrarion information is stored
//positiveChannel = the positive channel of the differential analog reading
//negChannel = the negative channel of the differential analog reading
//bytesVolt = the 2 byte voltage that will be converted
//analogVolt = the converted analog voltage
long getDacBinVoltCalibrated( u3CalibrationInfo *caliInfo,
int dacNumber,
double analogVolt,
uint8 *bytesVolt);
//Translates a analog output voltage value (Volts) to a binary 8 bit value
//(calibrated) that can be sent to a U3. Call getCalibrationInfo first to set
//up caliInfo. Returns -1 on error, 0 on success.
//This function is for U3 hardware versions 1.20, 1.21 and 1.30, and does the
//same thing as the analogToCalibratedBinary8BitVoltage function.
//caliInfo = structure where calibrarion information is stored
//DACNumber - channel number of the DAC
//analogVolt = the analog voltage that will be converted
//bytesVolt = the converted binary 8 bit value
long getDacBinVoltCalibrated8Bit( u3CalibrationInfo *caliInfo,
int dacNumber,
double analogVolt,
uint8 *bytesVolt8);
//Translates a analog output voltage value (Volts) to a binary 8 bit value
//(calibrated) that can be sent to a U3. Call getCalibrationInfo first to set
//up caliInfo. Returns -1 on error, 0 on success.
//This function is for U3 hardware versions 1.20, 1.21 and 1.30.
//caliInfo = structure where calibrarion information is stored
//dacNumber - channel number of the DAC
//analogVolt = the analog voltage that will be converted
//bytesVolt8 = the converted binary 8 bit value
long getDacBinVoltCalibrated16Bit( u3CalibrationInfo *caliInfo,
int dacNumber,
double analogVolt,
uint16 *bytesVolt16);
//Translates a analog output voltage value (Volts) to a binary 16 bit value
//(calibrated) that can be sent to a U3. Call getCalibrationInfo first to set
//up caliInfo. Returns -1 on error, 0 on success.
//This function is for U3 hardware versions 1.30 (U3-LV/HV).
//caliInfo = structure where calibrarion information is stored
//dacNumber - channel number of the DAC
//analogVolt = the analog voltage that will be converted
//bytesVolt16 = the converted binary 16 bit value
long getTdacBinVoltCalibrated( u3TdacCalibrationInfo *caliInfo,
int dacNumber,
double analogVolt,
uint16 *bytesVolt);
//Translates a voltage value (Volts) to binary analog input bytes (calibrated)
//that can be sent to a LJTick-DAC (LJTDAC). Call getTdacCalibrationInfo
//first to set up caliInfo. Returns -1 on error, 0 on success.
//caliInfo = structure where LJTDAC calibrarion information is stored
//dacNumber - channel number of the DAC (0 = DACA, 1 = DACB)
//analogVolt = the analog voltage that will be converted
//bytesVolt = the converted 2 byte voltage
long getTempKCalibrated( u3CalibrationInfo *caliInfo,
uint32 bytesTemp,
double *kelvinTemp);
//Translates the binary reading from the U3, to a temperature value
//(calibrated) in Kelvins. Call getCalibrationInfo first to set up caliInfo.
//Returns -1 on error, 0 on success.
//caliInfo = structure where calibrarion information is stored
//bytesTemp = the 2 byte binary temperature that will be converted
//kelvinTemp = the converted Kelvin temperature
long getAinVoltUncalibrated( int dac1Enabled,
uint8 negChannel,
uint16 bytesVolt,
double *analogVolt);
//Translates the binary AIN reading from the U3, to a voltage value
//(uncalibrated) in Volts. Returns -1 on error, 0 on success.
//This function is for U3 hardware versions 1.20 and 1.21.
//dac1Enabled = If this is nonzero (True), then it is indicated that DAC1 is
// enabled and analog voltage will be calculated with Vreg. If
// this is 0 (False), then it is indicated that DAC1 is disabled
// and the analog voltage will be calculated with the AIN slopes
// and offsets.
//negChannel = the negative channel of the differential analog reading
//bytesVolt = the 2 byte voltage that will be converted
//analogVolt = the converted analog voltage
long getAinVoltUncalibrated_hw130( int highVoltage,
uint8 positiveChannel,
uint8 negChannel,
uint16 bytesVolt,
double *analogVolt);
//Translates the binary AIN reading from the U3, to a voltage value
//(uncalibrated) in Volts. Returns -1 on error, 0 on success.
//This function is for U3 hardware versions 1.30 (U3-LV/HV).
//highVoltage = Set to 1 to indicate that U3-HV calculations should be used
// for the binary to voltage conversion, otherwise U3-LV voltage
// calculations will be used.
//positiveChannel = the positive channel of the differential analog reading
//negChannel = the negative channel of the differential analog reading
//bytesVolt = the 2 byte voltage that will be converted
//analogVolt = the converted analog voltage
long getDacBinVoltUncalibrated( int dacNumber,
double analogVolt,
uint8 *bytesVolt);
//Translates a DAC voltage value (Volts) to a binary 8 bit value (uncalibrated)
//that can be sent to a U3. Returns -1 on error, 0 on success.
//This function is for U3 hardware versions 1.20 and 1.21, and does the same
//thing as the analogToUncalibratedBinary8BitVoltage function.
//dacNumber - channel number of the DAC
//analogVolt = the analog voltage that will be converted
//bytesVolt = the converted binary 8 bit value
long getDacBinVoltUncalibrated8Bit( int dacNumber,
double analogVolt,
uint8 *bytesVolt8);
//Translates a DAC voltage value (Volts) to a binary 8 bit value (uncalibrated)
//that can be sent to a U3. Returns -1 on error, 0 on success.
//This function is for U3 hardware versions 1.20 and 1.21.
//dacNumber - channel number of the DAC
//analogVoltage = the analog voltage that will be converted
//bytesVoltage = the converted binary 8 bit value
long getDacBinVoltUncalibrated16Bit( int dacNumber,
double analogVolt,
uint16 *bytesVolt16);
//Translates a DAC voltage value (Volts) to a binary 16 bit value
//(uncalibrated) that can be sent to a U3-LV/HV. Returns -1 on error, 0 on
//success.
//This function is for U3 hardware versions 1.30 (U3-LV/HV).
//dacNumber - channel number of the DAC
//analogVoltage = the analog voltage that will be converted
//bytesVoltage = the converted binary 16 bit value
long getTempKUncalibrated( uint16 bytesTemp,
double *kelvinTemp);
//Translates the binary analog bytes read from the U3, to a temperature value
//(uncalibrated) in Kelvins. Call getCalibrationInfo first to set up caliInfo.
//Returns -1 on error, 0 on success.
//bytesTemp = the 2 byte binary temperature that will be converted
//kelvinTemp = the converted Kelvin temperature
long I2C( HANDLE hDevice,
uint8 I2COptions,
uint8 SpeedAdjust,
uint8 SDAPinNum,
uint8 SCLPinNum,
uint8 Address,
uint8 NumI2CBytesToSend,
uint8 NumI2CBytesToReceive,
uint8 *I2CBytesCommand,
uint8 *Errorcode,
uint8 *AckArray,
uint8 *I2CBytesResponse);
//This function will perform the I2C low-level function call. Please refer to
//section 5.3.19 of the U3 User's Guide for parameter documentation. Returns
//-1 on error, 0 on success.
//hDevice = handle to a U3 device
//I2COptions = byte 6 of the command
//SpeedAdjust = byte 7 of the command
//SDAPinNum = byte 8 of the command
//SCLPinNum = byte 9 of the command
//Address = byte 10 of the command
//NumI2CBytesToSend = byte 12 of the command
//NumI2CBytesToReceive = byte 13 of the command
//*I2CBytesCommand = Array that holds bytes 14 and above of the command. Needs
// to be at least NumI2CBytesToSend elements in size.
//*Errorcode = returns byte 6 of the response
//*AckArray = Array that returns bytes 8 - 11 of the response. Needs to be at
// least 4 elements in size.
//*I2CBytesResponse = Array that returns bytes 12 and above of the response.
// Needs to be at least NumI2CBytesToReceive elements in
// size.
/* Easy Functions (Similar to the easy functions in the Windows UD driver) */
long eAIN( HANDLE Handle,
u3CalibrationInfo *CalibrationInfo,
long ConfigIO,
long *DAC1Enable,
long ChannelP,
long ChannelN,
double *Voltage,
long Range,
long Resolution,
long Settling,
long Binary,
long Reserved1,
long Reserved2);
//An "easy" function that returns a reading from one analog input. This
//function does not automatically configure the specified channels as analog
//input, unless ConfigIO is set as True. Returns 0 for no error, or -1 or >0
//value (low-level errorcode) on error.
//Call getCalibrationInfo first to set up CalibrationInfo.
//Handle = Handle to a U3 device.
//CalibrationInfo = Structure where calibration information is stored.
//ConfigIO = If this is nonzero (True), then 1 or 2 ConfigIO low-level function
// calls will be made in addition to the 1 Feedback call to set the
// specified Channels to analog inputs. If this is 0 (False), then
// only a Feedback low-level call will be made, and an error will be
// returned if the specified Channels are not already set to analog
// inputs.
//DAC1Enable = This parameter helps to determine the appropriate equation to
// use when calculating Voltage. If the long variable that is
// being pointed to is nonzero (True), then it is indicated that
// DAC1 is enabled. If it is 0 (False), then it is indicated that
// DAC1 is disabled. For both case, if ConfigIO is set to True,
// then input value will be ignored and the output value will be
// set to the current DAC1Enable value in the ConfigIO low-level
// response.
//ChannelP = The positive AIN channel to acquire.
//ChannelN = The negative AIN channel to acquire. For single-ended channels on
// the U3, this parameter should be 31 (see Section 2.6.1).
//Voltage = Returns the analog input reading, which is generally a voltage.
//Range = Ignored on the U3.
//Resolution = Pass a nonzero value to enable QuickSample.
//Settling = Pass a nonzero value to enable LongSettling.
//Binary = If this is nonzero (True), the Voltage parameter will return the raw
// binary value.
//Reserved (1&2) = Pass 0.
long eDAC( HANDLE Handle,
u3CalibrationInfo *CalibrationInfo,
long ConfigIO,
long Channel,
double Voltage,
long Binary,
long Reserved1,
long Reserved2);
//An "easy" function that writes a value to one analog output. This function
//does not automatically enable the specified analog output, unless ConfigIO is
//set as True. Returns 0 for no error, or -1 or >0 value (low-level errorcode)
//on error.
//Call getCalibrationInfo first to set up CalibrationInfo.
//Handle = Handle to a U3 device.
//CalibrationInfo = structure where calibrarion information is stored
//ConfigIO = If this is nonzero (True) and Channel is 1, then 1 ConfigIO
// low-level function call will be made in addition to the 1 Feedback
// call to enable DAC1. If this is 0 (False), then only a Feedback
// low-level call will be made, and an error will be returned if DAC1
// is not already enabled.
//Channel = The analog output channel to write to.
//Voltage = The voltage to write to the analog output.
//Binary = If this is nonzero (True), the value passed for Voltage should be
// binary.
//Reserved (1&2) = Pass 0.
long eDI( HANDLE Handle,
long ConfigIO,
long Channel,
long *State);
//An "easy" function that reads the state of one digital input. This function
//does not automatically configure the specified channel as digital, unless
//ConfigIO is set as True. Returns 0 for no error, or -1 or >0 value
//(low-level errorcode) on error.
//Handle = Handle to a U3 device.
//ConfigIO = If this is nonzero (True), then 2 ConfigIO low-level functions
// calls will be made in addition to the 1 Feedback call to set
// Channel as digital. If this is 0 (False), then only a Feedback
// low-level call will be made, and an error will be returned if
// Channel is not already set as digital.
//Channel = The channel to read. 0-19 corresponds to FIO0-CIO3.
// For U3 hardware versions 1.30, HV model, Channel needs to be 4-19,
//State = Returns the state of the digital input. 0=False=Low and 1=True=High.
long eDO( HANDLE Handle,
long ConfigIO,
long Channel,
long State);
//An "easy" function that writes the state of one digital output. This
//function does not automatically configure the specified channel as digital,
//unless ConfigIO is set as True. Returns 0 for no error, or -1 or >0 value
//(low-level errorcode) on error.
//Handle = Handle to a U3 device.
//ConfigIO = If this is nonzero (True), then 2 ConfigIO low-level functions
// calls will be made in addition to the 1 Feedback call to set
// Channel as digital. If this is 0 (False), then only a Feedback
// low-level call will be made, and an error will be returned if
// Channel is not already set as digital.
//Channel = The channel to write to. 0-19 corresponds to FIO0-CIO3.
// For U3 hardware versions 1.30, HV model, Channel needs to be 4-19,
//State = The state to write to the digital output. 0=False=Low and
// 1=True=High.
long eTCConfig( HANDLE Handle,
long *aEnableTimers,
long *aEnableCounters,
long TCPinOffset,
long TimerClockBaseIndex,
long TimerClockDivisor,
long *aTimerModes,
double *aTimerValues,
long Reserved1,
long Reserved2);
//An "easy" function that configures and initializes all the timers and
//counters. When needed, this function automatically configures the needed
//lines as digital. Returns 0 for no error, or -1 or >0 value (low-level
//errorcode) on error.
//Handle = Handle to a U3 device.
//aEnableTimers = An array where each element specifies whether that timer is
// enabled. Timers must be enabled in order starting from 0, so
// for instance, Timer1 cannot be enabled without enabling Timer
// 0 also. A nonzero for an array element specifies to enable
// that timer. For the U3, this array must always have at least
// 2 elements.
//aEnableCounters = An array where each element specifies whether that counter
// is enabled. Counters do not have to be enabled in order
// starting from 0, so Counter1 can be enabled when Counter0
// is disabled. A nonzero value for an array element
// specifies to enable that counter. For the U3, this array
// must always have at least 2 elements.
//TCPinOffset = Value from 0-8 specifies where to start assigning timers and
// counters.
// For U3 hardware versions 1.30, HV model, value needs to be 4-8.
//TimerClockBaseIndex = Pass a constant to set the timer base clock. The
// default is LJ_tc48MHZ.
//TimerClockDivisor = Pass a divisor from 0-255 where 0 is a divisor of 256.
//aTimerModes = An array where each element is a constant specifying the mode
// for that timer. For the U3, this array must always have at
// least 2 elements.
//aTimerValues = An array where each element specifies the initial value for
// that timer. For the U3, this array must always have at least
// 2 elements.
//Reserved (1&2) = Pass 0.
long eTCValues( HANDLE Handle,
long *aReadTimers,
long *aUpdateResetTimers,
long *aReadCounters,
long *aResetCounters,
double *aTimerValues,
double *aCounterValues,
long Reserved1,
long Reserved2);
//An "easy" function that updates and reads all the timers and counters.
//Returns 0 for no error, or -1 or >0 value (low-level errorcode) on error.
//Handle = Handle to a U3 device.
//aReadTimers = An array where each element specifies whether to read that
// timer. A nonzero value for an array element specifies to read
// that timer. For the U3, this array must always have at least 2
// elements.
//aUpdateResetTimers = An array where each element specifies whether to
// update/reset that timers. A nonzero value for an array
// element specifies to update/reset that timer. For the
// U3, this array must always have at least 2 elements.
//aReadCounters = An array where each element specifies whether to read that
// counter. A nonzero value for an array element specifies to
// read that counter. For the U3, this array must always have
// at least 2 elements.
//aResetCounters = An array where each element specifies whether to reset that
// counter. A nonzero value for an array element specifies to
// reset that counter. For the U3, this array must always have
// at least 2 elements.
//aTimerValues = Input: An array where each element is the new value for that
// timer. Each value is only updated if the appropriate element
// is set in the aUpdateResetTimers array.
// Output: An array where each element is the value read from
// that timer if the appropriate element is set in the
// aReadTimers array. If the timer mode set for the timer is
// Quadrature Input, the value needs to be converted from an
// unsigned 32-bit integer to a signed 32-bit integer (2s
// complement). For the U3, this array must always have at least
// 2 elements.
//aCounterValues = An array where each element is the value read from that
// counter if the appropriate element is set in the aReadTimers
// array. For the U3, this array must always have at least 2
// elements.
//Reserved (1&2) = Pass 0.
/* Easy Function Helpers */
long ehConfigIO( HANDLE hDevice,
uint8 inWriteMask,
uint8 inTimerCounterConfig,
uint8 inDAC1Enable,
uint8 inFIOAnalog,
uint8 inEIOAnalog,
uint8 *outTimerCounterConfig,
uint8 *outDAC1Enable,
uint8 *outFIOAnalog,
uint8 *outEIOAnalog);
//Used by the eAIN, eDAC, eDI, eDO and eTCConfig easy functions. This function
//takes the ConfigIO low-level command and response bytes (not including
//checksum and command bytes) as its parameter and performs a ConfigIO call
//with the U3. Returns -1 or errorcode (>1 value) on error, 0 on success.
long ehConfigTimerClock( HANDLE hDevice,
uint8 inTimerClockConfig,
uint8 inTimerClockDivisor,
uint8 *outTimerClockConfig,
uint8 *outTimerClockDivisor);
//Used by the eTCConfig easy function. This function takes the
//ConfigTimerClock low-level command and response bytes (not including checksum
//and command bytes) as its parameter and performs a ConfigTimerClock call with
//the U3. Returns -1 or errorcode (>1 value) on error, 0 on success.
long ehFeedback( HANDLE hDevice,
uint8 *inIOTypesDataBuff,
long inIOTypesDataSize,
uint8 *outErrorcode,
uint8 *outErrorFrame,
uint8 *outDataBuff,
long outDataSize);
//Used by the all of the easy functions. This function takes the Feedback
//low-level command and response bytes (not including checksum and command
//bytes) as its parameter and performs a Feedback call with the U3. Returns -1
//or errorcode (>1 value) on error, 0 on success.
/* Easy function constants */
/* Timer clocks for Hardware Version 1.20 or lower */
// 2 MHz
#define LJ_tc2MHZ 10
// 6 MHz
#define LJ_tc6MHZ 11
// 24 MHz
#define LJ_tc24MHZ 12
// 500/Divisor KHz
#define LJ_tc500KHZ_DIV 13
// 2/Divisor MHz
#define LJ_tc2MHZ_DIV 14
// 6/Divisor MHz
#define LJ_tc6MHZ_DIV 15
// 24/Divisor MHz
#define LJ_tc24MHZ_DIV 16
/* Timer clocks for Hardware Version 1.21 or higher */
// 4 MHz
#define LJ_tc4MHZ 20
// 12 MHz
#define LJ_tc12MHZ 21
// 48 MHz
#define LJ_tc48MHZ 22
// 1/Divisor MHz
#define LJ_tc1MHZ_DIV 23
// 4/Divisor MHz
#define LJ_tc4MHZ_DIV 24
// 12/Divisor MHz
#define LJ_tc12MHZ_DIV 25
// 48/Divisor MHz
#define LJ_tc48MHZ_DIV 26
/* Timer modes */
// 16 bit PWM
#define LJ_tmPWM16 0
// 8 bit PWM
#define LJ_tmPWM8 1
// 32-bit rising to rising edge measurement
#define LJ_tmRISINGEDGES32 2
// 32-bit falling to falling edge measurement
#define LJ_tmFALLINGEDGES32 3
// duty cycle measurement
#define LJ_tmDUTYCYCLE 4
// firmware based rising edge counter
#define LJ_tmFIRMCOUNTER 5
// firmware counter with debounce
#define LJ_tmFIRMCOUNTERDEBOUNCE 6
// frequency output
#define LJ_tmFREQOUT 7
// Quadrature
#define LJ_tmQUAD 8
// stops another timer after n pulses
#define LJ_tmTIMERSTOP 9
// read lower 32-bits of system timer
#define LJ_tmSYSTIMERLOW 10
// read upper 32-bits of system timer
#define LJ_tmSYSTIMERHIGH 11
// 16-bit rising to rising edge measurement
#define LJ_tmRISINGEDGES16 12
// 16-bit falling to falling edge measurement
#define LJ_tmFALLINGEDGES16 13
#endif

View File

@@ -0,0 +1,251 @@
/*
An example that shows a minimal use of Exodriver without the use of functions
hidden in header files.
You can compile this example with the following command:
$ g++ -lm -llabjackusb u3BasicConfigU3.c
It is also included in the Makefile.
*/
/* Includes */
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include "labjackusb.h"
// Defines how long the command is
#define CONFIGU3_COMMAND_LENGTH 26
// Defines how long the response is
#define CONFIGU3_RESPONSE_LENGTH 38
/* Buffer Helper Functions Protypes */
// Takes a buffer and an offset, and turns it into a 32-bit integer
int makeInt(BYTE * buffer, int offset);
// Takes a buffer and an offset, and turns it into a 16-bit integer
int makeShort(BYTE * buffer, int offset);
// Takes a buffer and calculates the checksum8 of it.
BYTE calculateChecksum8(BYTE* buffer);
// Takes a buffer and length, and calculates the checksum16 of the buffer.
int calculateChecksum16(BYTE* buffer, int len);
/* LabJack Related Helper Functions Protoypes */
// Demonstrates how to build the ConfigU3 packet.
void buildConfigU3Bytes(BYTE * sendBuffer);
// Demonstrates how to check a response for errors.
int checkResponseForErrors(BYTE * recBuffer);
// Demonstrates how to parse the response of ConfigU3.
void parseConfigU3Bytes(BYTE * recBuffer);
int main() {
// Setup the variables we will need.
int r = 0; // For checking return values
HANDLE devHandle = 0;
BYTE sendBuffer[CONFIGU3_COMMAND_LENGTH], recBuffer[CONFIGU3_RESPONSE_LENGTH];
// Open the U3
devHandle = LJUSB_OpenDevice(1, 0, U3_PRODUCT_ID);
if( devHandle == NULL ) {
printf("Couldn't open U3. Please connect one and try again.\n");
exit(-1);
}
// Builds the ConfigU3 command
buildConfigU3Bytes(sendBuffer);
// Write the command to the device.
// LJUSB_Write( handle, sendBuffer, length of sendBuffer )
r = LJUSB_Write( devHandle, sendBuffer, CONFIGU3_COMMAND_LENGTH );
if( r != CONFIGU3_COMMAND_LENGTH ) {
printf("An error occurred when trying to write the buffer. The error was: %d\n", errno);
// *Always* close the device when you error out.
LJUSB_CloseDevice(devHandle);
exit(-1);
}
// Read the result from the device.
// LJUSB_Read( handle, recBuffer, number of bytes to read)
r = LJUSB_Read( devHandle, recBuffer, CONFIGU3_RESPONSE_LENGTH );
if( r != CONFIGU3_RESPONSE_LENGTH ) {
printf("An error occurred when trying to read from the U3. The error was: %d\n", errno);
LJUSB_CloseDevice(devHandle);
exit(-1);
}
// Check the command for errors
if( checkResponseForErrors(recBuffer) != 0 ){
LJUSB_CloseDevice(devHandle);
exit(-1);
}
// Parse the response into something useful
parseConfigU3Bytes(recBuffer);
//Close the device.
LJUSB_CloseDevice(devHandle);
return 0;
}
/* ------------- LabJack Related Helper Functions Definitions ------------- */
// Uses information from section 5.2.2 of the U3 User's Guide to make a ConfigU3
// packet.
// http://labjack.com/support/u3/users-guide/5.2.2
void buildConfigU3Bytes(BYTE * sendBuffer) {
int i; // For loops
int checksum = 0;
// Build up the bytes
//sendBuffer[0] = Checksum8
sendBuffer[1] = 0xF8;
sendBuffer[2] = 0x0A;
sendBuffer[3] = 0x08;
//sendBuffer[4] = Checksum16 (LSB)
//sendBuffer[5] = Checksum16 (MSB)
// We just want to read, so we set the WriteMask to zero, and zero out the
// rest of the bytes.
sendBuffer[6] = 0;
for( i = 7; i < CONFIGU3_COMMAND_LENGTH; i++){
sendBuffer[i] = 0;
}
// Calculate and set the checksum16
checksum = calculateChecksum16(sendBuffer, CONFIGU3_COMMAND_LENGTH);
sendBuffer[4] = (BYTE)( checksum & 0xff );
sendBuffer[5] = (BYTE)( (checksum / 256) & 0xff );
// Calculate and set the checksum8
sendBuffer[0] = calculateChecksum8(sendBuffer);
// The bytes have been set, and the checksum calculated. We are ready to
// write to the U3.
}
// Checks the response for any errors.
int checkResponseForErrors(BYTE * recBuffer) {
if(recBuffer[0] == 0xB8 && recBuffer[1] == 0xB8) {
// If the packet is [ 0xB8, 0xB8 ], that's a bad checksum.
printf("The U3 detected a bad checksum. Double check your checksum calculations and try again.\n");
return -1;
}
else if (recBuffer[1] != 0xF8 || recBuffer[2] != 0x10 || recBuffer[3] != 0x08) {
// Make sure the command bytes match what we expect.
printf("Got the wrong command bytes back from the U3.\n");
return -1;
}
// Calculate the checksums.
int checksum16 = calculateChecksum16(recBuffer, CONFIGU3_RESPONSE_LENGTH);
BYTE checksum8 = calculateChecksum8(recBuffer);
if ( checksum8 != recBuffer[0] || recBuffer[4] != (BYTE)( checksum16 & 0xff ) || recBuffer[5] != (BYTE)( (checksum16 / 256) & 0xff ) ) {
// Check the checksum
printf("Response had invalid checksum.\n%d != %d, %d != %d, %d != %d\n", checksum8, recBuffer[0], (BYTE)( checksum16 & 0xff ), recBuffer[4], (BYTE)( (checksum16 / 256) & 0xff ), recBuffer[5] );
return -1;
}
else if ( recBuffer[6] != 0 ) {
// Check the error code in the packet. See section 5.3 of the U3
// User's Guide for errorcode descriptions.
printf("Command returned with an errorcode = %d\n", recBuffer[6]);
return -1;
}
return 0;
}
// Parses the ConfigU3 packet into something useful.
void parseConfigU3Bytes(BYTE * recBuffer){
printf("Results of ConfigU3:\n");
printf(" FirmwareVersion = %d.%02d\n", recBuffer[10], recBuffer[9]);
printf(" BootloaderVersion = %d.%02d\n", recBuffer[12], recBuffer[11]);
printf(" HardwareVersion = %d.%02d\n", recBuffer[14], recBuffer[13]);
printf(" SerialNumber = %d\n", makeInt(recBuffer, 15));
printf(" ProductID = %d\n", makeShort(recBuffer, 19));
printf(" LocalID = %d\n", recBuffer[21]);
printf(" TimerCounterMask = %d\n", recBuffer[22]);
printf(" FIOAnalog = %d\n", recBuffer[23]);
printf(" FIODireciton = %d\n", recBuffer[24]);
printf(" FIOState = %d\n", recBuffer[25]);
printf(" EIOAnalog = %d\n", recBuffer[26]);
printf(" EIODirection = %d\n", recBuffer[27]);
printf(" EIOState = %d\n", recBuffer[28]);
printf(" CIODirection = %d\n", recBuffer[29]);
printf(" CIOState = %d\n", recBuffer[30]);
printf(" DAC1Enable = %d\n", recBuffer[31]);
printf(" DAC0 = %d\n", recBuffer[32]);
printf(" DAC1 = %d\n", recBuffer[33]);
printf(" TimerClockConfig = %d\n", recBuffer[34]);
printf(" TimerClockDivisor = %d\n", recBuffer[35]);
printf(" CompatibilityOptions = %d\n", recBuffer[36]);
printf(" VersionInfo = %d\n", recBuffer[37]);
if( recBuffer[37] == 0 ){
printf(" DeviceName = U3A\n");
}
else if(recBuffer[37] == 1) {
printf(" DeviceName = U3B\n");
}
else if(recBuffer[37] == 2) {
printf(" DeviceName = U3-LV\n");
}
else if(recBuffer[37] == 18) {
printf(" DeviceName = U3-HV\n");
}
}
/* ---------------- Buffer Helper Functions Definitions ---------------- */
// Takes a buffer and an offset, and turns into an 32-bit integer
int makeInt(BYTE * buffer, int offset){
return (buffer[offset+3] << 24) + (buffer[offset+2] << 16) + (buffer[offset+1] << 8) + buffer[offset];
}
// Takes a buffer and an offset, and turns into an 16-bit integer
int makeShort(BYTE * buffer, int offset) {
return (buffer[offset+1] << 8) + buffer[offset];
}
// Calculates the checksum8
BYTE calculateChecksum8(BYTE* buffer){
int i; // For loops
int temp; // For holding a value while we working.
int checksum = 0;
for( i = 1; i < 6; i++){
checksum += buffer[i];
}
temp = checksum/256;
checksum = ( checksum - 256 * temp ) + temp;
temp = checksum/256;
return (BYTE)( ( checksum - 256 * temp ) + temp );
}
// Calculates the checksum16
int calculateChecksum16(BYTE* buffer, int len){
int i;
int checksum = 0;
for( i = 6; i < len; i++){
checksum += buffer[i];
}
return checksum;
}

View File

@@ -0,0 +1,121 @@
//Author: LabJack
//April 7, 2008
//This examples demonstrates how to read from analog inputs (AIN) and digital
//inputs(FIO), set analog outputs (DAC) and digital outputs (FIO), and how to
//configure and enable timers and counters and read input timers and counters
//values using the "easy" functions.
#include "u3.h"
#include <unistd.h>
int main(int argc, char **argv)
{
HANDLE hDevice;
u3CalibrationInfo caliInfo;
int localID;
long DAC1Enable, error;
//Open first found U3 over USB
localID = -1;
if( (hDevice = openUSBConnection(localID)) == NULL )
goto done;
//Get calibration information from U3
if( getCalibrationInfo(hDevice, &caliInfo) < 0 )
goto close;
/* Note: The eAIN, eDAC, eDI, and eDO "easy" functions have the ConfigIO
parameter. If calling, for example, eAIN to read AIN3 in a loop, set the
ConfigIO parameter to 1 (True) on the first iteration so that the
ConfigIO low-level function is called to ensure that channel 3 is set to
an analog input. For the rest of the iterations in the loop, set the
ConfigIO parameter to 0 (False) since the channel is already set as
analog. */
//Set DAC0 to 2.1 volts.
printf("Calling eDAC to set DAC0 to 2.1 V\n");
if( (error = eDAC(hDevice, &caliInfo, 0, 0, 2.1, 0, 0, 0)) != 0 )
goto close;
sleep(1);
/* Note: The eAIN "easy" function has the DAC1Enable parameter that needs to
be set to calculate the correct voltage. In addition to the earlier
note, if running eAIN in a loop, set ConfigIO to 1 (True) on the first
iteration to also set the output of the DAC1Enable parameter with the
current setting on the U3. For the rest of the iterations, set ConfigIO
to 0 (False) and use the outputted DAC1Enable parameter from the first
interation from then on. If DAC1 is enabled/disabled from a later eDAC
or ConfigIO low-level call, change the DAC1Enable parameter accordingly
or make another eAIN call with the ConfigIO parameter set to 1. */
//Read the single-ended voltage from AIN3
printf("\nCalling eAIN to read voltage from AIN3\n");
double dblVoltage;
if( (error = eAIN(hDevice, &caliInfo, 1, &DAC1Enable, 3, 31, &dblVoltage, 0, 0, 0, 0, 0, 0)) != 0 )
goto close;
printf("AIN3 value = %.3f\n", dblVoltage);
//Set FIO5 to output-high
printf("\nCalling eDO to set FIO5 to output-high\n");
if( (error = eDO(hDevice, 1, 5, 1)) != 0 )
goto close;
//Read state of FIO4
printf("\nCalling eDI to read the state of FIO4\n");
long lngState;
if( (error = eDI(hDevice, 1, 4, &lngState)) != 0 )
goto close;
printf("FIO4 state = %ld\n", lngState);
//Enable and configure 1 output timer and 1 input timer, and enable counter0
printf("\nCalling eTCConfig to enable and configure 1 output timer (Timer0) and 1 input timer (Timer1), and enable counter0\n");
long alngEnableTimers[2] = {1, 1}; //Enable Timer0-Timer1
long alngTimerModes[2] = {LJ_tmPWM8, LJ_tmRISINGEDGES32}; //Set timer modes
double adblTimerValues[2] = {16384, 0}; //Set PWM8 duty-cycles to 75%
long alngEnableCounters[2] = {1, 0}; //Enable Counter0
if( (error = eTCConfig(hDevice, alngEnableTimers, alngEnableCounters, 4, LJ_tc48MHZ, 0, alngTimerModes, adblTimerValues, 0, 0)) != 0 )
goto close;
printf("\nWaiting for 1 second...\n");
sleep(1);
//Read and reset the input timer (Timer1), read and reset Counter0, and
//update the value (duty-cycle) of the output timer (Timer0)
printf("\nCalling eTCValues to read and reset the input Timer1 and Counter0, and update the value (duty-cycle) of the output Timer0\n");
long alngReadTimers[2] = {0, 1}; //Read Timer1
long alngUpdateResetTimers[2] = {1, 0}; //Update timer0
long alngReadCounters[2] = {1, 0}; //Read Counter0
long alngResetCounters[2] = {0, 0}; //Reset no Counters
double adblCounterValues[2] = {0, 0};
adblTimerValues[0] = 32768; //Change Timer0 duty-cycle to 50%
if( (error = eTCValues(hDevice, alngReadTimers, alngUpdateResetTimers, alngReadCounters, alngResetCounters, adblTimerValues, adblCounterValues, 0, 0)) != 0 )
goto close;
printf("Timer1 value = %.0f\n", adblTimerValues[1]);
printf("Counter0 value = %.0f\n", adblCounterValues[0]);
//Disable all timers and counters
alngEnableTimers[0] = 0;
alngEnableTimers[1] = 0;
alngEnableCounters[0] = 0;
alngEnableCounters[1] = 0;
if( (error = eTCConfig(hDevice, alngEnableTimers, alngEnableCounters, 4, 0, 0, alngTimerModes, adblTimerValues, 0, 0)) != 0 )
goto close;
printf("\nCalling eTCConfig to disable all timers and counters\n");
close:
if( error > 0 )
printf("Received an error code of %ld\n", error);
closeUSBConnection(hDevice);
done:
return 0;
}

View File

@@ -0,0 +1,848 @@
//Author : LabJack
//December 27, 2011
//For U3s with hardware versions 1.20, 1.21 and 1.30 LV, this example will
//set FIO0 and FIO1 to analog input, FIO2 to digital output set to low, and
//FIO3 to digital input. FIO4 and FIO5 will be set as timers 0 and 1 with
//timer modes PMW8 and PMW16. FIO6 will be set as counter 1. Also, DAC0 will
//be set to 1.5 volts and the temperature will be read.
//For U3s with hardware version 1.30 HV, this example will read AIN0-AIN4 and
//set FIO7 to digital input. FIO4 and FIO5 will be set as timers 0 and 1 with
//timer modes PMW8 and PMW16. FIO6 will be set as counter 1. Also, DAC0 will
//be set to 3.5 volts and the temperature will be read.
#include <unistd.h>
#include <termios.h>
#include "u3.h"
static struct termios termNew, termOrig;
static int peek = -1;
int configIO_example(HANDLE hDevice, int enable, int *isDAC1Enabled);
int configTimerClock_example(HANDLE hDevice);
int feedback_setup_example(HANDLE hDevice, u3CalibrationInfo *caliInfo);
int feedback_setup_HV_example(HANDLE hDevice, u3CalibrationInfo *caliInfo);
int feedback_loop_example(HANDLE hDevice, u3CalibrationInfo *caliInfo, int isDAC1Enabled);
int feedback_loop_HV_example(HANDLE hDevice, u3CalibrationInfo *caliInfo);
void setTerm();
int kbhit();
void unsetTerm();
int main(int argc, char **argv)
{
HANDLE hDevice;
u3CalibrationInfo caliInfo;
int dac1Enabled;
//setting terminal settings
setTerm();
//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, 1, &dac1Enabled) != 0 )
goto close;
if( configTimerClock_example(hDevice) != 0 )
goto close;
if( caliInfo.hardwareVersion >= 1.30 && caliInfo.highVoltage == 1 )
{
if( feedback_setup_HV_example(hDevice, &caliInfo) != 0 )
goto close;
if( feedback_loop_HV_example(hDevice, &caliInfo) != 0 )
goto close;
}
else
{
if( feedback_setup_example(hDevice, &caliInfo) != 0 )
goto close;
if( feedback_loop_example(hDevice, &caliInfo, dac1Enabled) != 0 )
goto close;
}
configIO_example(hDevice, 0, &dac1Enabled);
close:
closeUSBConnection(hDevice);
done:
printf("\nDone\n");
//Setting terminal settings to previous settings
unsetTerm();
return 0;
}
//Sends a ConfigIO low-level command that configures the FIOs, DAC, Timers and
//Counters for this example.
int configIO_example(HANDLE hDevice, int enable, int *isDAC1Enabled)
{
uint8 sendBuff[12], recBuff[12];
uint8 timerCounterConfig, fioAnalog;
uint16 checksumTotal;
int sendChars, recChars;
if( enable == 0 )
{
timerCounterConfig = 64; //Disabling timers (bits 0 and 1) and Counters
//(bits 2 and 3), setting TimerCounterPinOffset
//to 4 (bits 4-7)
fioAnalog = 255; //Setting all FIOs to analog
}
else
{
timerCounterConfig = 74; //Enabling 2 timers (bits 0 and 1), Counter 1 (bit 3)
//and setting TimerCounterPinOffset (bits 4-7) to
//4. Note that Counter 0 will not be available
//since the timer clock will use a divisor in this
//example. Also, for hardware version 1.30, HV
//models need to have a TimerCounterPinOffset of 4-8,
//otherwise an error will occur since FIO0-FIO3 can only
//be analog inputs.
fioAnalog = 3; //Setting FIO0 (bit 0) and FIO1 (bit 1) to analog input. Note that
//hardware version 1.30, U3-HV models will always have FIO0-4 set as
//analog inputs, and will ignore setting chages. In this case, FIO2
//and FIO3 will ignore the the digital setting and still be analog
//inputs.
}
sendBuff[1] = (uint8)(0xF8); //Command byte
sendBuff[2] = (uint8)(0x03); //Number of data words
sendBuff[3] = (uint8)(0x0B); //Extended command number
sendBuff[6] = 5; //Writemask : Setting writemask for timerCounterConfig (bit 0)
//and FIOAnalog (bit 2)
sendBuff[7] = 0; //Reserved
sendBuff[8] = timerCounterConfig; //TimerCounterConfig
sendBuff[9] = 0; //DAC1 enable : not enabling, though could already be enabled.
//If U3 hardware version 1.30, DAC1 is always enabled.
sendBuff[10] = fioAnalog; //FIOAnalog
sendBuff[11] = 0; //EIOAnalog : Not setting anything
extendedChecksum(sendBuff, 12);
//Sending command to U3
if( (sendChars = LJUSB_Write(hDevice, sendBuff, 12)) < 12 )
{
if( sendChars == 0 )
printf("ConfigIO error : write failed\n");
else
printf("ConfigIO error : did not write all of the buffer\n");
return -1;
}
//Reading response from U3
if( (recChars = LJUSB_Read(hDevice, recBuff, 12)) < 12 )
{
if( recChars == 0 )
printf("ConfigIO error : read failed\n");
else
printf("ConfigIO error : did not read all of the buffer\n");
return -1;
}
checksumTotal = extendedChecksum16(recBuff, 12);
if( (uint8)((checksumTotal / 256 ) & 0xFF) != recBuff[5] )
{
printf("ConfigIO error : read buffer has bad checksum16(MSB)\n");
return -1;
}
if( (uint8)(checksumTotal & 0xFF) != recBuff[4] )
{
printf("ConfigIO error : read buffer has bad checksum16(LBS)\n");
return -1;
}
if( extendedChecksum8(recBuff) != recBuff[0] )
{
printf("ConfigIO error : read buffer has bad checksum8\n");
return -1;
}
if( recBuff[1] != (uint8)(0xF8) || recBuff[2] != (uint8)(0x03) || recBuff[3] != (uint8)(0x0B) )
{
printf("ConfigIO error : read buffer has wrong command bytes\n");
return -1;
}
if( recBuff[6] != 0 )
{
printf("ConfigIO error : read buffer received errorcode %d\n", recBuff[6]);
return -1;
}
if( recBuff[8] != timerCounterConfig )
{
printf("ConfigIO error : TimerCounterConfig did not get set correctly\n");
return -1;
}
if( recBuff[10] != fioAnalog && recBuff[10] != (fioAnalog|(0x0F)) )
{
printf("ConfigIO error : FIOAnalog(%d) did not set correctly\n", recBuff[10]);
return -1;
}
*isDAC1Enabled = (int)recBuff[9];
return 0;
}
//Sends a ConfigTimerClock low-level command that configures the timer clock
//for this example.
int configTimerClock_example(HANDLE hDevice)
{
uint8 sendBuff[10], recBuff[10];
uint16 checksumTotal;
int sendChars, recChars;
sendBuff[1] = (uint8)(0xF8); //Command byte
sendBuff[2] = (uint8)(0x02); //Number of data words
sendBuff[3] = (uint8)(0x0A); //Extended command number
sendBuff[6] = 0; //Reserved
sendBuff[7] = 0; //Reserved
sendBuff[8] = 134; //TimerClockConfig : Configuring the clock (bit 7) and
//setting the TimerClockBase (bits 0-2) to
//24MHz/TimerClockDivisor
sendBuff[9] = 2; //TimerClockDivisor : Setting to 2, so the actual timer
//clock is 12 MHz
extendedChecksum(sendBuff, 10);
//Sending command to U3
if( (sendChars = LJUSB_Write(hDevice, sendBuff, 10)) < 10 )
{
if( sendChars == 0 )
printf("ConfigTimerClock error : write failed\n");
else
printf("ConfigTimerClock error : did not write all of the buffer\n");
return -1;
}
//Reading response from U3
if( (recChars = LJUSB_Read(hDevice, recBuff, 10)) < 10 )
{
if( recChars == 0 )
printf("ConfigTimerClock error : read failed\n");
else
printf("ConfigTimerClock error : did not read all of the buffer\n");
return -1;
}
checksumTotal = extendedChecksum16(recBuff, 10);
if( (uint8)((checksumTotal / 256 ) & 0xFF) != recBuff[5] )
{
printf("ConfigTimerClock error : read buffer has bad checksum16(MSB)\n");
return -1;
}
if( (uint8)(checksumTotal & 0xFF) != recBuff[4] )
{
printf("ConfigTimerClock error : read buffer has bad checksum16(LBS)\n");
return -1;
}
if( extendedChecksum8(recBuff) != recBuff[0] )
{
printf("ConfigTimerClock error : read buffer has bad checksum8\n");
return -1;
}
if( recBuff[1] != (uint8)(0xF8) || recBuff[2] != (uint8)(0x02) || recBuff[3] != (uint8)(0x0A) )
{
printf("ConfigTimerClock error : read buffer has wrong command bytes\n");
return -1;
}
if( recBuff[6] != 0 )
{
printf("ConfigTimerClock error : read buffer received errorcode %d\n", recBuff[6]);
return -1;
}
/*
if( recBuff[8] != timerClockConfig )
{
printf("ConfigTimerClock error : TimerClockConfig did not get set correctly %d\n", recBuff[7]);
return -1;
}
if( recBuff[9] != timerClockDivisor )
{
printf("ConfigTimerClock error : TimerClockDivisor did not get set correctly %d\n", recBuff[7]);
return -1;
}
*/
return 0;
}
//Sends a Feedback low-level command that configures digital directions, states,
//timer modes and DAC0 for this example. Will work with U3 hardware versions
//1.20, 1.21 and 1.30 LV.
int feedback_setup_example(HANDLE hDevice, u3CalibrationInfo *caliInfo)
{
uint8 sendBuff[32], recBuff[18];
uint16 checksumTotal;
int sendChars, recChars;
sendBuff[1] = (uint8)(0xF8); //Command byte
sendBuff[2] = 13; //Number of data words (.5 word for echo, 8 words for
//IOTypes and data, and .5 words for the extra byte)
sendBuff[3] = (uint8)(0x00); //Extended command number
sendBuff[6] = 0; //Echo
sendBuff[7] = 13; //IOType is BitDirWrite
sendBuff[8] = 130; //IONumber (bits 0 - 4) is 2 and Direction (bit 7) is
//output
sendBuff[9] = 13; //IOType is BitDirWrite
sendBuff[10] = 3; //IONumber (bits 0 - 4) is 3 and Direction (bit 7) is
//input
sendBuff[11] = 11; //IOType is BitStateWrite
sendBuff[12] = 2; //IONumber (bits 0 - 4) is 2 and State (bit 7) is low
sendBuff[13] = 43; //IOType is Timer0Config
sendBuff[14] = 0; //TimerMode is 16 bit PWM output (mode 0)
sendBuff[15] = 0; //Value LSB
sendBuff[16] = 0; //Value MSB, Whole value is 32768
sendBuff[17] = 42; //IOType is Timer0
sendBuff[18] = 1; //UpdateReset
sendBuff[19] = 0; //Value LSB
sendBuff[20] = 128; //Value MSB, Whole Value is 32768
sendBuff[21] = 45; //IOType is Timer1Config
sendBuff[22] = 1; //TimerMode is 8 bit PWM output (mode 1)
sendBuff[23] = 0; //Value LSB
sendBuff[24] = 0; //Value MSB, Whole value is 32768
sendBuff[25] = 44; //IOType is Timer1
sendBuff[26] = 1; //UpdateReset
sendBuff[27] = 0; //Value LSB
sendBuff[28] = 128; //Value MSB, Whole Value is 32768
sendBuff[29] = 34; //IOType is DAC0 (8-bit)
//Value is 1.5 volts (in binary form)
getDacBinVoltCalibrated8Bit(caliInfo, 0, 1.5, &sendBuff[30]);
sendBuff[31] = 0; //Extra byte
extendedChecksum(sendBuff, 32);
//Sending command to U3
if( (sendChars = LJUSB_Write(hDevice, sendBuff, 32)) < 32 )
{
if( sendChars == 0 )
printf("Feedback setup error : write failed\n");
else
printf("Feedback setup error : did not write all of the buffer\n");
return -1;
}
//Reading response from U3
if( (recChars = LJUSB_Read(hDevice, recBuff, 18)) < 18 )
{
if( recChars == 0 )
{
printf("Feedback setup error : read failed\n");
return -1;
}
else
printf("Feedback setup error : did not read all of the buffer\n");
}
checksumTotal = extendedChecksum16(recBuff, 18);
if( (uint8)((checksumTotal / 256 ) & 0xFF) != recBuff[5] )
{
printf("Feedback setup error : read buffer has bad checksum16(MSB)\n");
return -1;
}
if( (uint8)(checksumTotal & 0xFF) != recBuff[4] )
{
printf("Feedback setup error : read buffer has bad checksum16(LBS)\n");
return -1;
}
if( extendedChecksum8(recBuff) != recBuff[0] )
{
printf("Feedback setup error : read buffer has bad checksum8\n");
return -1;
}
if( recBuff[1] != (uint8)(0xF8) || recBuff[2] != 6 || recBuff[3] != (uint8)(0x00) )
{
printf("Feedback setup error : read buffer has wrong command bytes \n");
return -1;
}
if( recBuff[6] != 0 )
{
printf("Feedback setup error : received errorcode %d for frame %d in Feedback response. \n", recBuff[6], recBuff[7]);
return -1;
}
return 0;
}
//Sends a Feedback low-level command that configures digital directions, states,
//timer modes and DAC0 for this example. Meant for U3 hardware versions 1.30 HV
//example purposes, but will work with LV as well.
int feedback_setup_HV_example(HANDLE hDevice, u3CalibrationInfo *caliInfo)
{
uint8 sendBuff[28], recBuff[18];
uint16 binVoltage16, checksumTotal;
int sendChars, recChars;
sendBuff[1] = (uint8)(0xF8); //Command byte
sendBuff[2] = 11; //Number of data words (.5 word for echo, 10.5 words for
//IOTypes and data)
sendBuff[3] = (uint8)(0x00); //Extended command number
sendBuff[6] = 0; //Echo
sendBuff[7] = 13; //IOType is BitDirWrite
sendBuff[8] = 7; //IONumber (bits 0 - 4) is 7 and Direction (bit 7) is
//input
sendBuff[9] = 43; //IOType is Timer0Config
sendBuff[10] = 0; //TimerMode is 16 bit PWM output (mode 0)
sendBuff[11] = 0; //Value LSB
sendBuff[12] = 0; //Value MSB, Whole value is 32768
sendBuff[13] = 42; //IOType is Timer0
sendBuff[14] = 1; //UpdateReset
sendBuff[15] = 0; //Value LSB
sendBuff[16] = 128; //Value MSB, Whole Value is 32768
sendBuff[17] = 45; //IOType is Timer1Config
sendBuff[18] = 1; //TimerMode is 8 bit PWM output (mode 1)
sendBuff[19] = 0; //Value LSB
sendBuff[20] = 0; //Value MSB, Whole value is 32768
sendBuff[21] = 44; //IOType is Timer1
sendBuff[22] = 1; //UpdateReset
sendBuff[23] = 0; //Value LSB
sendBuff[24] = 128; //Value MSB, Whole Value is 32768
sendBuff[25] = 38; //IOType is DAC0 (16-bit)
//Value is 3.5 volts (in binary form)
getDacBinVoltCalibrated16Bit(caliInfo, 0, 3.5, &binVoltage16);
sendBuff[26] = (uint8)(binVoltage16&255); //Value LSB
sendBuff[27] = (uint8)((binVoltage16&65280)/256); //Value MSB
extendedChecksum(sendBuff, 28);
//Sending command to U3
if( (sendChars = LJUSB_Write(hDevice, sendBuff, 28)) < 28 )
{
if( sendChars == 0 )
printf("Feedback setup HV error : write failed\n");
else
printf("Feedback setup HV error : did not write all of the buffer\n");
return -1;
}
//Reading response from U3
if( (recChars = LJUSB_Read(hDevice, recBuff, 18)) < 18 )
{
if( recChars == 0 )
{
printf("Feedback setup HV error : read failed\n");
return -1;
}
else
printf("Feedback setup HV error : did not read all of the buffer\n");
}
checksumTotal = extendedChecksum16(recBuff, 18);
if( (uint8)((checksumTotal / 256 ) & 0xFF) != recBuff[5] )
{
printf("Feedback setup HV error : read buffer has bad checksum16(MSB)\n");
return -1;
}
if( (uint8)(checksumTotal & 0xFF) != recBuff[4] )
{
printf("Feedback setup HV error : read buffer has bad checksum16(LBS)\n");
return -1;
}
if( extendedChecksum8(recBuff) != recBuff[0] )
{
printf("Feedback setup HV error : read buffer has bad checksum8\n");
return -1;
}
if( recBuff[1] != (uint8)(0xF8) || recBuff[2] != 6 || recBuff[3] != (uint8)(0x00) )
{
printf("Feedback setup HV error : read buffer has wrong command bytes \n");
return -1;
}
if( recBuff[6] != 0 )
{
printf("Feedback setup HV error : received errorcode %d for frame %d in Feedback response. \n", recBuff[6], recBuff[7]);
return -1;
}
return 0;
}
//Calls a Feedback low-level call to read AIN0, AIN1, FIO3, Counter1(FIO6) and
//temperature. Will work with U3 hardware versions 1.20, 1.21 and 1.30 LV.
int feedback_loop_example(HANDLE hDevice, u3CalibrationInfo *caliInfo, int isDAC1Enabled)
{
uint8 sendBuff[32], recBuff[28];
uint16 checksumTotal;
int sendChars, recChars;
long count;
double voltage, temperature;
sendBuff[1] = (uint8)(0xF8); //Command byte
sendBuff[2] = 13; //Number of data words (.5 word for echo, 12.5 words for
//IOTypes)
sendBuff[3] = (uint8)(0x00); //Extended command number
sendBuff[6] = 0; //Echo
sendBuff[7] = 1; //IOType is AIN
sendBuff[8] = 0; //Positive channel (bits 0-4) is 0, LongSettling (bit 6)
//is not set and QuickSample (bit 7) is not set
sendBuff[9] = 31; //Negative channel is 31 (SE)
sendBuff[10] = 1; //IOType is AIN
sendBuff[11] = 1; //Positive channel (bits 0-4) is 1, LongSettling (bit 6)
//is not set and QuickSample (bit 7) is not set
sendBuff[12] = 31; //Negative channel is 31 (SE)
sendBuff[13] = 1; //IOType is AIN
sendBuff[14] = 0; //Positive channel (bits 0-4) is 0, LongSettling (bit 6)
//is not set and QuickSample (bit 7) is not set
sendBuff[15] = 1; //Negative channel is 1 (FIO1)
sendBuff[16] = 1; //IOType is AIN
sendBuff[17] = 1; //Positive channel (bits 0-4) is 1, LongSettling (bit 6)
//is not set and QuickSample (bit 7) is not set
sendBuff[18] = 0; //Negative channel is 0 (FIO0)
sendBuff[19] = 1; //IOType is AIN
sendBuff[20] = 0; //Positive channel (bits 0-4) is 0, LongSettling (bit 6)
//is not set and QuickSample (bit 7) is not set
sendBuff[21] = 30; //Negative channel is 30 (Vref)
sendBuff[22] = 1; //IOType is AIN
sendBuff[23] = 1; //Positive channel (bits 0-4) is 1, LongSettling (bit 6)
//is not set and QuickSample (bit 7) is not set
sendBuff[24] = 30; //Negative channel is 30 (Vref)
sendBuff[25] = 10; //IOType is BitStateRead
sendBuff[26] = 3; //IO number is 3 (FIO3)
sendBuff[27] = 55; //IOType is Counter1
sendBuff[28] = 0; //Reset (bit 0) is not set
sendBuff[29] = 1; //IOType is AIN
sendBuff[30] = 30; //Positive channel is 30 (temp sensor)
sendBuff[31] = 31; //Negative channel is 31 (SE)
extendedChecksum(sendBuff, 32);
printf("Running Feedback calls in a loop\n");
count = 0;
while( !kbhit() )
{
count++;
printf("Iteration %ld\n", count);
//Sending command to U3
if( (sendChars = LJUSB_Write(hDevice, sendBuff, 32)) < 32 )
{
if( sendChars == 0 )
printf("Feedback loop error : write failed\n");
else
printf("Feedback loop error : did not write all of the buffer\n");
return -1;
}
//Reading response from U3
if( (recChars = LJUSB_Read(hDevice, recBuff, 28)) < 28 )
{
if( recChars == 0 )
{
printf("Feedback loop error : read failed\n");
return -1;
}
else
printf("Feedback loop error : did not read all of the expected buffer\n");
}
if( recChars < 10 )
{
printf("Feedback loop error : response is not large enough\n");
return -1;
}
checksumTotal = extendedChecksum16(recBuff, recChars);
if( (uint8)((checksumTotal / 256 ) & 0xFF) != recBuff[5] )
{
printf("Feedback loop error : read buffer has bad checksum16(MSB)\n");
return -1;
}
if( (uint8)(checksumTotal & 0xFF) != recBuff[4] )
{
printf("Feedback loop error : read buffer has bad checksum16(LBS)\n");
return -1;
}
if( extendedChecksum8(recBuff) != recBuff[0] )
{
printf("Feedback loop error : read buffer has bad checksum8\n");
return -1;
}
if( recBuff[1] != (uint8)(0xF8) || recBuff[3] != (uint8)(0x00) )
{
printf("Feedback loop error : read buffer has wrong command bytes \n");
return -1;
}
if( recBuff[6] != 0 )
{
printf("Feedback loop error : received errorcode %d for frame %d ", recBuff[6], recBuff[7]);
switch( recBuff[7] )
{
case 1: printf("(AIN(SE))\n"); break;
case 2: printf("(AIN(SE))\n"); break;
case 3: printf("(AIN(Neg. chan. 1))\n"); break;
case 4: printf("(AIN(Neg. chan. 0))\n"); break;
case 5: printf("(AIN(Neg. chan. Vref))\n"); break;
case 6: printf("(AIN(Neg. chan. Vref))\n"); break;
case 7: printf("(BitStateRead for FIO3)\n"); break;
case 8: printf("(Counter1)\n"); break;
case 9: printf("(Temp. Sensor\n"); break;
default: printf("(Unknown)\n"); break;
}
return -1;
}
getAinVoltCalibrated(caliInfo, isDAC1Enabled, 31, recBuff[9] + recBuff[10]*256, &voltage);
printf("AIN0(SE) : %.3f volts\n", voltage);
getAinVoltCalibrated(caliInfo, isDAC1Enabled, 31, recBuff[11] + recBuff[12]*256, &voltage);
printf("AIN1(SE) : %.3f volts\n", voltage);
getAinVoltCalibrated(caliInfo, isDAC1Enabled, 1, recBuff[13] + recBuff[14]*256, &voltage);
printf("AIN0(Neg. chan. 1) : %.3f volts\n", voltage);
getAinVoltCalibrated(caliInfo, isDAC1Enabled, 0, recBuff[15] + recBuff[16]*256, &voltage);
printf("AIN1(Neg. chan. 0): %.3f volts\n", voltage);
getAinVoltCalibrated(caliInfo, isDAC1Enabled, 30, recBuff[17] + recBuff[18]*256, &voltage);
printf("AIN0(Neg. chan. Vref) : %.3f volts\n", voltage);
getAinVoltCalibrated(caliInfo, isDAC1Enabled, 30, recBuff[19] + recBuff[20]*256, &voltage);
printf("AIN1(Neg. chan. Vref): %.3f volts\n", voltage);
printf("FIO3 state : %d\n", recBuff[21]);
printf("Counter1(FIO6) : %u\n\n", recBuff[22] + recBuff[23]*256 + recBuff[24]*65536 + recBuff[25]*16777216);
getTempKCalibrated(caliInfo, recBuff[26] + recBuff[27]*256, &temperature);
printf("Temperature : %.3f K\n\n", temperature);
sleep(1);
}
return 0;
}
//Calls a Feedback low-level call to read AIN0, AIN1, FIO7, Counter1(FIO6) and
//temperature. Will work with U3 hardware versions 1.30 HV.
int feedback_loop_HV_example(HANDLE hDevice, u3CalibrationInfo *caliInfo)
{
uint8 sendBuff[26], recBuff[24];
uint16 checksumTotal;
int sendChars, recChars;
long count;
double voltage, temperature;
sendBuff[1] = (uint8)(0xF8); //Command byte
sendBuff[2] = 10; //Number of data words (.5 word for echo, 9.5 words for
//IOTypes)
sendBuff[3] = (uint8)(0x00); //Extended command number
sendBuff[6] = 0; //Echo
sendBuff[7] = 1; //IOType is AIN
sendBuff[8] = 0; //Positive channel (bits 0-4) is 0, LongSettling (bit 6)
//is not set and QuickSample (bit 7) is not set
sendBuff[9] = 31; //Negative channel is 31 (SE)
sendBuff[10] = 1; //IOType is AIN
sendBuff[11] = 1; //Positive channel (bits 0-4) is 1, LongSettling (bit 6)
//is not set and QuickSample (bit 7) is not set
sendBuff[12] = 31; //Negative channel is 31 (SE)
sendBuff[13] = 1; //IOType is AIN
sendBuff[14] = 2; //Positive channel (bits 0-4) is 3, LongSettling (bit 6)
//is not set and QuickSample (bit 7) is not set
sendBuff[15] = 31; //Negative channel is 31 (SE)
sendBuff[16] = 1; //IOType is AIN
sendBuff[17] = 3; //Positive channel (bits 0-4) is 4, LongSettling (bit 6)
//is not set and QuickSample (bit 7) is not set
sendBuff[18] = 31; //Negative channel is 31 (SE)
sendBuff[19] = 10; //IOType is BitStateRead
sendBuff[20] = 7; //IO number is 7 (FIO7)
sendBuff[21] = 55; //IOType is Counter1
sendBuff[22] = 0; //Reset (bit 0) is not set
sendBuff[23] = 1; //IOType is AIN
sendBuff[24] = 30; //Positive channel is 30 (temp sensor)
sendBuff[25] = 31; //Negative channel is 31 (SE)
extendedChecksum(sendBuff, 26);
printf("Running Feedback calls in a loop\n");
count = 0;
while( !kbhit() )
{
count++;
printf("Iteration %ld\n", count);
//Sending command to U3
if( (sendChars = LJUSB_Write(hDevice, sendBuff, 26)) < 26 )
{
if( sendChars == 0 )
printf("Feedback loop HV error : write failed\n");
else
printf("Feedback loop HV error : did not write all of the buffer\n");
return -1;
}
//Reading response from U3
if( (recChars = LJUSB_Read(hDevice, recBuff, 24)) < 24 )
{
if( recChars == 0 )
{
printf("Feedback loop HV error : read failed\n");
return -1;
}
else
printf("Feedback loop HV error : did not read all of the expected buffer\n");
}
if( recChars < 10 )
{
printf("Feedback loop HV error : response is not large enough\n");
return -1;
}
checksumTotal = extendedChecksum16(recBuff, recChars);
if( (uint8)((checksumTotal / 256 ) & 0xFF) != recBuff[5] )
{
printf("Feedback loop HV error : read buffer has bad checksum16(MSB)\n");
return -1;
}
if( (uint8)(checksumTotal & 0xFF) != recBuff[4] )
{
printf("Feedback loop HV error : read buffer has bad checksum16(LBS)\n");
return -1;
}
if( extendedChecksum8(recBuff) != recBuff[0] )
{
printf("Feedback loop HV error : read buffer has bad checksum8\n");
return -1;
}
if( recBuff[1] != (uint8)(0xF8) || recBuff[3] != (uint8)(0x00) )
{
printf("Feedback loop HV error : read buffer has wrong command bytes \n");
return -1;
}
if( recBuff[6] != 0 )
{
printf("Feedback loop HV error : received errorcode %d for frame %d ", recBuff[6], recBuff[7]);
switch( recBuff[7] )
{
case 1: printf("(AIN0(SE))\n"); break;
case 2: printf("(AIN1(SE))\n"); break;
case 3: printf("(AIN2(SE))\n"); break;
case 4: printf("(AIN3(SE))\n"); break;
case 5: printf("(BitStateRead for FIO7)\n"); break;
case 6: printf("(Counter1)\n"); break;
case 7: printf("(Temp. Sensor\n"); break;
default: printf("(Unknown)\n"); break;
}
return -1;
}
getAinVoltCalibrated_hw130(caliInfo, 0, 31, recBuff[9] + recBuff[10]*256, &voltage);
printf("AIN0(SE) : %.3f volts\n", voltage);
getAinVoltCalibrated_hw130(caliInfo, 1, 31, recBuff[11] + recBuff[12]*256, &voltage);
printf("AIN1(SE) : %.3f volts\n", voltage);
getAinVoltCalibrated_hw130(caliInfo, 2, 31, recBuff[13] + recBuff[14]*256, &voltage);
printf("AIN2(SE) : %.3f volts\n", voltage);
getAinVoltCalibrated_hw130(caliInfo, 3, 31, recBuff[15] + recBuff[16]*256, &voltage);
printf("AIN3(SE) : %.3f volts\n", voltage);
printf("FIO7 state : %d\n", recBuff[17]);
printf("Counter1(FIO6) : %u\n\n", recBuff[18] + recBuff[19]*256 + recBuff[20]*65536 + recBuff[21]*16777216);
getTempKCalibrated(caliInfo, recBuff[22] + recBuff[23]*256, &temperature);
printf("Temperature : %.3f K\n\n", temperature);
sleep(1);
}
return 0;
}
void setTerm()
{
tcgetattr(0, &termOrig);
termNew = termOrig;
termNew.c_lflag &= ~ICANON;
termNew.c_lflag &= ~ECHO;
termNew.c_lflag &= ~ISIG;
termNew.c_cc[VMIN] = 1;
termNew.c_cc[VTIME] = 0;
tcsetattr(0, TCSANOW, &termNew);
}
int kbhit()
{
char ch;
int nread;
if( peek != -1 )
return 1;
termNew.c_cc[VMIN] = 0;
tcsetattr(0, TCSANOW, &termNew);
nread = read(0, &ch, 1);
termNew.c_cc[VMIN] = 1;
tcsetattr(0, TCSANOW, &termNew);
if(nread == 1)
{
peek = ch;
return 1;
}
return 0;
}
void unsetTerm()
{
tcsetattr(0, TCSANOW, &termOrig);
}

View File

@@ -0,0 +1,331 @@
//Author: LabJack
//December 27, 2011
//Communicates with an LJTick-DAC using low level functions. The LJTDAC should
//be plugged into FIO4/FIO5 for this example.
//Tested with U3 firmware V1.44, and requires hardware version 1.21 or greater.
#include "u3.h"
#include <unistd.h>
int configIO_example(HANDLE hDevice);
int checkI2CErrorcode(uint8 errorcode);
int LJTDAC_example(HANDLE hDevice, u3TdacCalibrationInfo *caliInfo);
int main(int argc, char **argv)
{
HANDLE hDevice;
u3TdacCalibrationInfo caliInfo;
//Opening first found U3 over USB
if( (hDevice = openUSBConnection(-1)) == NULL )
goto done;
if( configIO_example(hDevice) != 0 )
goto close;
//Getting calibration information from LJTDAC
if( getTdacCalibrationInfo(hDevice, &caliInfo, 4) < 0 )
goto close;
LJTDAC_example(hDevice, &caliInfo);
close:
closeUSBConnection(hDevice);
done:
return 0;
}
//Sends a ConfigIO low-level command that configures the FIO4 and FIO5 lines to
//digital.
int configIO_example(HANDLE hDevice)
{
uint8 sendBuff[12], recBuff[12];
uint16 checksumTotal;
int sendChars, recChars;
sendBuff[1] = (uint8)(0xF8); //Command byte
sendBuff[2] = (uint8)(0x03); //Number of data words
sendBuff[3] = (uint8)(0x0B); //Extended command number
sendBuff[6] = 7; //Writemask : Setting writemask for TimerCounterConfig (bit 0),
// DAC1Enable (bit 1) and FIOAnalog (bit 2)
sendBuff[7] = 0; //Reserved
sendBuff[8] = 64; //TimerCounterConfig : disable timers and counters. set
// TimerCounterPinOffset to 4 (bits 4-7)
sendBuff[9] = 0; //DAC1 enable : disabling
sendBuff[10] = 0; //FIOAnalog : setting FIO channels to digital
sendBuff[11] = 0; //EIOAnalog : Not setting anything
extendedChecksum(sendBuff, 12);
//Sending command to U3
if( (sendChars = LJUSB_Write(hDevice, sendBuff, 12)) < 12 )
{
if( sendChars == 0 )
printf("ConfigIO error : write failed\n");
else
printf("ConfigIO error : did not write all of the buffer\n");
return -1;
}
//Reading response from U3
if( (recChars = LJUSB_Read(hDevice, recBuff, 12)) < 12 )
{
if( recChars == 0 )
printf("ConfigIO error : read failed\n");
else
printf("ConfigIO error : did not read all of the buffer\n");
return -1;
}
checksumTotal = extendedChecksum16(recBuff, 12);
if( (uint8)((checksumTotal / 256 ) & 0xFF) != recBuff[5] )
{
printf("ConfigIO error : read buffer has bad checksum16(MSB)\n");
return -1;
}
if( (uint8)(checksumTotal & 0xFF) != recBuff[4] )
{
printf("ConfigIO error : read buffer has bad checksum16(LBS)\n");
return -1;
}
if( extendedChecksum8(recBuff) != recBuff[0] )
{
printf("ConfigIO error : read buffer has bad checksum8\n");
return -1;
}
if( recBuff[1] != (uint8)(0xF8) || recBuff[2] != (uint8)(0x03) || recBuff[3] != (uint8)(0x0B) )
{
printf("ConfigIO error : read buffer has wrong command bytes\n");
return -1;
}
if( recBuff[6] != 0 )
{
printf("ConfigIO error : read buffer received errorcode %d\n", recBuff[6]);
return -1;
}
if( recBuff[8] != 64 )
{
printf("ConfigIO error : TimerCounterConfig did not get set correctly\n");
return -1;
}
if( recBuff[10] != 0 && recBuff[10] != (uint8)(0x0F) )
{
printf("ConfigIO error : FIOAnalog did not set correctly\n");
return -1;
}
return 0;
}
int checkI2CErrorcode(uint8 errorcode)
{
if(errorcode != 0)
{
printf("I2C error : received errorcode %d in response\n", errorcode);
return -1;
}
return 0;
}
int LJTDAC_example(HANDLE hDevice, u3TdacCalibrationInfo *caliInfo)
{
uint8 options, speedAdjust, sdaPinNum, sclPinNum;
uint8 address, numBytesToSend, numBytesToReceive, errorcode;
uint8 bytesCommand[5], bytesResponse[64], ackArray[4];
uint16 binaryVoltage;
int err, i;
err = 0;
//Setting up parts I2C command that will remain the same throughout this
//example
options = 0; //I2COptions : 0
speedAdjust = 0; //SpeedAdjust : 0 (for max communication speed of about
//130 kHz)
sdaPinNum = 5; //SDAPinNum : FIO5 connected to pin DIOB
sclPinNum = 4; //SCLPinNum : FIO4 connected to pin DIOA
/* Set DACA to 1.2 volts. */
//Setting up I2C command
//Make note that the I2C command can only update 1 DAC channel at a time.
address = (uint8)(0x24); //Address : h0x24 is the address for DAC
numBytesToSend = 3; //NumI2CByteToSend : 3 bytes to specify DACA and the
//value
numBytesToReceive = 0; //NumI2CBytesToReceive : 0 since we are only setting
//the value of the DAC
bytesCommand[0] = (uint8)(0x30); //LJTDAC command byte : h0x30 (DACA)
getTdacBinVoltCalibrated(caliInfo, 0, 1.2, &binaryVoltage);
bytesCommand[1] = (uint8)(binaryVoltage/256); //value (high)
bytesCommand[2] = (uint8)(binaryVoltage & (0x00FF)); //value (low)
//Performing I2C low-level call
err = I2C(hDevice, options, speedAdjust, sdaPinNum, sclPinNum, address, numBytesToSend, numBytesToReceive, bytesCommand, &errorcode, ackArray, bytesResponse);
if( checkI2CErrorcode(errorcode) == -1 || err == -1 )
return -1;
printf("DACA set to 1.2 volts\n\n");
/* Set DACB to 2.3 volts. */
//Setting up I2C command
address = (uint8)(0x24); //Address : h0x24 is the address for DAC
numBytesToSend = 3; //NumI2CByteToSend : 3 bytes to specify DACB and the
//value
numBytesToReceive = 0; //NumI2CBytesToReceive : 0 since we are only setting
//the value of the DAC
bytesCommand[0] = (uint8)(0x31); //LJTDAC command byte : h0x31 (DACB)
getTdacBinVoltCalibrated(caliInfo, 1, 2.3, &binaryVoltage);
bytesCommand[1] = (uint8)(binaryVoltage/256); //value (high)
bytesCommand[2] = (uint8)(binaryVoltage & (0x00FF)); //value (low)
//Performing I2C low-level call
err = I2C(hDevice, options, speedAdjust, sdaPinNum, sclPinNum, address, numBytesToSend, numBytesToReceive, bytesCommand, &errorcode, ackArray, bytesResponse);
if( checkI2CErrorcode(errorcode) == -1 || err == -1 )
return -1;
printf("DACB set to 2.3 volts\n\n");
/* More advanced operations. */
/* Display LJTDAC calibration constants. Code for getting the calibration
* constants is in the getLJTDACCalibrationInfo function in the u3.c file.
*/
printf("DACA Slope = %.1f bits/volt\n", caliInfo->ccConstants[0]);
printf("DACA Offset = %.1f bits\n", caliInfo->ccConstants[1]);
printf("DACB Slope = %.1f bits/volt\n", caliInfo->ccConstants[2]);
printf("DACB Offset = %.1f bits\n\n", caliInfo->ccConstants[3]);
/* Read the serial number. */
//Setting up I2C command
address = (uint8)(0xA0); //Address : h0xA0 is the address for EEPROM
numBytesToSend = 1; //NumI2CByteToSend : 1 byte for the EEPROM address
numBytesToReceive = 4; //NumI2CBytesToReceive : getting 4 bytes starting at
//EEPROM address specified in I2CByte0
bytesCommand[0] = 96; //I2CByte0 : Memory Address, starting at address 96
//(Serial Number)
//Performing I2C low-level call
err = I2C(hDevice, options, speedAdjust, sdaPinNum, sclPinNum, address, numBytesToSend, numBytesToReceive, bytesCommand, &errorcode, ackArray, bytesResponse);
if( checkI2CErrorcode(errorcode) == -1 || err == -1 )
return -1;
printf("LJTDAC Serial Number = %u\n\n", (bytesResponse[0] + bytesResponse[1]*256 + bytesResponse[2]*65536 + bytesResponse[3]*16777216));
/* User memory example. We will read the memory, update a few elements, and
* write the memory. The user memory is just stored as bytes, so almost any
* information can be put in there such as integers, doubles, or strings.
*/
/* Read the user memory : need to perform 2 I2C calls since command/response
packets can only be 64 bytes in size */
//Setting up 1st I2C command
address = (uint8)(0xA0); //Address : h0xA0 is the address for EEPROM
numBytesToSend = 1; //NumI2CByteToSend : 1 byte for the EEPROM address
numBytesToReceive = 52; //NumI2CBytesToReceive : getting 52 bytes starting
//at EEPROM address specified in I2CByte0
bytesCommand[0] = 0; //I2CByte0 : Memory Address, starting at address 0
//(User Area)
//Performing I2C low-level call
err = I2C(hDevice, options, speedAdjust, sdaPinNum, sclPinNum, address, numBytesToSend, numBytesToReceive, bytesCommand, &errorcode, ackArray, bytesResponse);
if( checkI2CErrorcode(errorcode) == -1 || err == -1 )
return -1;
//Setting up 2nd I2C command
numBytesToReceive = 12; //NumI2CBytesToReceive : getting 12 bytes starting
//at EEPROM address specified in I2CByte0
bytesCommand[0] = 52; //I2CByte0 : Memory Address, starting at address 52
//(User Area)
//Performing I2C low-level call
err = I2C(hDevice, options, speedAdjust, sdaPinNum, sclPinNum, address, numBytesToSend, numBytesToReceive, bytesCommand, &errorcode, ackArray, bytesResponse + 52);
if( checkI2CErrorcode(errorcode) == -1 || err == -1 )
return -1;
//Display the first 4 elements.
printf("Read User Mem [0-3] = %d, %d, %d, %d\n", bytesResponse[0], bytesResponse[1], bytesResponse[2], bytesResponse[3]);
/* Create 4 new pseudo-random numbers to write. We will update the first
* 4 elements of user memory, but the rest will be unchanged. */
//Setting up I2C command
address = (uint8)(0xA0); //Address : h0xA0 is the address for EEPROM
numBytesToSend = 5; //NumI2CByteToSend : 1 byte for the EEPROM address and
//the rest for the bytes to write
numBytesToReceive = 0; //NumI2CBytesToReceive : 0 since we are only writing to memory
bytesCommand[0] = 0; //I2CByte0 : Memory Address, starting at address 0
//(User Area)
srand((unsigned int)getTickCount());
for(i = 1; i < 5; i++)
{
//I2CByte : byte in user memory
bytesCommand[i] = (uint8)(255 * ((float)rand()/RAND_MAX));
}
printf("Write User Mem [0-3] = %d, %d, %d, %d\n", bytesCommand[1], bytesCommand[2], bytesCommand[3], bytesCommand[4]);
//Performing I2C low-level call
err = I2C(hDevice, options, speedAdjust, sdaPinNum, sclPinNum, address, numBytesToSend, numBytesToReceive, bytesCommand, &errorcode, ackArray, bytesResponse);
if( checkI2CErrorcode(errorcode) == -1 || err == -1 )
return -1;
//Delay for 2 ms to allow the EEPROM to finish writing.
//Re-read the user memory.
usleep(2000);
//Setting up 1st I2C command
address = (uint8)(0xA0); //Address : h0xA0 is the address for EEPROM
numBytesToSend = 1; //NumI2CByteToSend : 1 byte for the EEPROM address
numBytesToReceive = 52; //NumI2CBytesToReceive : getting 52 bytes starting
//at EEPROM address specified in I2CByte0
bytesCommand[0] = 0; //I2CByte0 : Memory Address, starting at address 0
//(User Area)
//Performing I2C low-level call
err = I2C(hDevice, options, speedAdjust, sdaPinNum, sclPinNum, address, numBytesToSend, numBytesToReceive, bytesCommand, &errorcode, ackArray, bytesResponse);
if( checkI2CErrorcode(errorcode) == -1 || err == -1 )
return -1;
//Setting up 2nd I2C command
numBytesToReceive = 12; //NumI2CBytesToReceive : getting 12 bytes starting
//at EEPROM address specified in I2CByte0
bytesCommand[0] = 52; //I2CByte0 : Memory Address, starting at address 52
//(User Area)
//Performing I2C low-level call
err = I2C(hDevice, options, speedAdjust, sdaPinNum, sclPinNum, address, numBytesToSend, numBytesToReceive, bytesCommand, &errorcode, ackArray, bytesResponse + 52);
if( checkI2CErrorcode(errorcode) == -1 || err == -1 )
return -1;
//Display the first 4 elements.
printf("Read User Mem [0-3] = %d, %d, %d, %d\n", bytesResponse[0], bytesResponse[1], bytesResponse[2], bytesResponse[3]);
return err;
}

View File

@@ -0,0 +1,521 @@
//Author: LabJack
//December 27, 2011
//This example program reads analog inputs AI0-AI4 using stream mode. Requires
//a U3 with hardware version 1.21 or higher.
#include "u3.h"
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 = 5; //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;
}
//Sends a ConfigIO low-level command that configures the FIOs, DAC, Timers and
//Counters for this example
int ConfigIO_example(HANDLE hDevice, int *isDAC1Enabled)
{
uint8 sendBuff[12], recBuff[12];
uint16 checksumTotal;
int sendChars, recChars;
sendBuff[1] = (uint8)(0xF8); //Command byte
sendBuff[2] = (uint8)(0x03); //Number of data words
sendBuff[3] = (uint8)(0x0B); //Extended command number
sendBuff[6] = 13; //Writemask : Setting writemask for timerCounterConfig (bit 0),
// FIOAnalog (bit 2) and EIOAnalog (bit 3)
sendBuff[7] = 0; //Reserved
sendBuff[8] = 64; //TimerCounterConfig: Disabling all timers and counters,
// set TimerCounterPinOffset to 4 (bits 4-7)
sendBuff[9] = 0; //DAC1Enable
sendBuff[10] = 255; //FIOAnalog : setting all FIOs as analog inputs
sendBuff[11] = 255; //EIOAnalog : setting all EIOs as analog inputs
extendedChecksum(sendBuff, 12);
//Sending command to U3
if( (sendChars = LJUSB_Write(hDevice, sendBuff, 12)) < 12 )
{
if( sendChars == 0 )
printf("ConfigIO error : write failed\n");
else
printf("ConfigIO error : did not write all of the buffer\n");
return -1;
}
//Reading response from U3
if( (recChars = LJUSB_Read(hDevice, recBuff, 12)) < 12 )
{
if( recChars == 0 )
printf("ConfigIO error : read failed\n");
else
printf("ConfigIO error : did not read all of the buffer\n");
return -1;
}
checksumTotal = extendedChecksum16(recBuff, 12);
if( (uint8)((checksumTotal / 256 ) & 0xFF) != recBuff[5] )
{
printf("ConfigIO error : read buffer has bad checksum16(MSB)\n");
return -1;
}
if( (uint8)(checksumTotal & 0xFF) != recBuff[4] )
{
printf("ConfigIO error : read buffer has bad checksum16(LBS)\n");
return -1;
}
if( extendedChecksum8(recBuff) != recBuff[0] )
{
printf("ConfigIO error : read buffer has bad checksum8\n");
return -1;
}
if( recBuff[1] != (uint8)(0xF8) || recBuff[2] != (uint8)(0x03) || recBuff[3] != (uint8)(0x0B) )
{
printf("ConfigIO error : read buffer has wrong command bytes\n");
return -1;
}
if( recBuff[6] != 0 )
{
printf("ConfigIO error : read buffer received errorcode %d\n", recBuff[6]);
return -1;
}
if( recBuff[8] != 64 )
{
printf("ConfigIO error : TimerCounterConfig did not get set correctly\n");
return -1;
}
if( recBuff[10] != 255 && recBuff[10] != (uint8)(0x0F) )
{
printf("ConfigIO error : FIOAnalog did not set get correctly\n");
return -1;
}
if( recBuff[11] != 255 )
{
printf("ConfigIO error : EIOAnalog did not set get correctly (%d)\n", recBuff[11]);
return -1;
}
*isDAC1Enabled = (int)recBuff[9];
return 0;
}
//Sends a StreamConfig low-level command to configure the stream.
int StreamConfig_example(HANDLE hDevice)
{
uint8 sendBuff[64], recBuff[8];
uint16 checksumTotal, scanInterval;
int sendBuffSize, sendChars, recChars, i;
sendBuffSize = 12+NumChannels*2;
sendBuff[1] = (uint8)(0xF8); //Command byte
sendBuff[2] = 3 + NumChannels; //Number of data words = NumChannels + 3
sendBuff[3] = (uint8)(0x11); //Extended command number
sendBuff[6] = NumChannels; //NumChannels
sendBuff[7] = SamplesPerPacket; //SamplesPerPacket
sendBuff[8] = 0; //Reserved
sendBuff[9] = 1; //ScanConfig:
// Bit 7: Reserved
// Bit 6: Reserved
// Bit 3: Internal stream clock frequency = b0: 4 MHz
// Bit 2: Divide Clock by 256 = b0
// Bits 0-1: Resolution = b01: 11.9-bit effective
scanInterval = 4000;
sendBuff[10] = (uint8)(scanInterval & (0x00FF)); //Scan interval (low byte)
sendBuff[11] = (uint8)(scanInterval / 256); //Scan interval (high byte)
for( i = 0; i < NumChannels; i++ )
{
sendBuff[12 + i*2] = i; //PChannel = i
sendBuff[13 + i*2] = 31; //NChannel = 31: Single Ended
}
extendedChecksum(sendBuff, sendBuffSize);
//Sending command to U3
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;
}
for( i = 0; i < 8; i++ )
recBuff[i] = 0;
//Reading response from U3
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, %d (StreamConfig).\n", recChars);
for( i = 0; i < 8; i++ )
printf("%d ", recBuff[i]);
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(LBS) (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) || recBuff[7] != (uint8)(0x00) )
{
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 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 = 6;
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( i = 0; i < numDisplay; i++ )
{
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]);
}
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;
}
//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 U3
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 U3
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) || recBuff[3] != (uint8)(0x00) )
{
printf("Error : read buffer has wrong command bytes (StreamStop).\n");
return -1;
}
if( recBuff[2] != 0 )
{
printf("Errorcode # %d from StreamStop read.\n", (unsigned int)recBuff[2]);
return -1;
}
return 0;
}

View File

@@ -0,0 +1,381 @@
//Author : LabJack
//December 27, 2011
//This example demonstrates how to write and read some or all analog and digital
//I/O. It records the time for 1000 iterations and divides by 1000, to allow
//measurement of the basic command/response communication times. These times
//should be comparable to the Windows command/response communication times
//documented in Section 3.1 of the U3 User's Guide.
#include <stdlib.h>
#include "u3.h"
const uint8 numChannels = 8; //Number of AIN channels, 0-16.
const uint8 quickSample = 1; //Set to TRUE for quick AIN sampling.
const uint8 longSettling = 0; //Set to TRUE for extra AIN settling time.
int configAllIO(HANDLE hDevice, int *isDAC1Enabled);
int allIO(HANDLE hDevice, u3CalibrationInfo *caliInfo, int isDAC1Enabled);
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( configAllIO(hDevice, &dac1Enabled) < 0 )
goto close;;
allIO(hDevice, &caliInfo, dac1Enabled);
close:
closeUSBConnection(hDevice);
done:
return 0;
}
//Sends a ConfigIO low-level command that will set desired lines as analog, and
//all else as digital.
int configAllIO(HANDLE hDevice, int *isDAC1Enabled)
{
uint8 sendBuff[12], recBuff[12];
uint16 checksumTotal, FIOEIOAnalog;
int sendChars, recChars;
sendBuff[1] = (uint8)(0xF8); //Command byte
sendBuff[2] = (uint8)(0x03); //Number of data words
sendBuff[3] = (uint8)(0x0B); //Extended command number
sendBuff[6] = 13; //Writemask : Setting writemask for TimerCounterConfig (bit 0),
// FIOAnalog (bit 2) and EIOAnalog (bit 3)
sendBuff[7] = 0; //Reserved
sendBuff[8] = 64; //TimerCounterConfig: disable timer and counter, set
// TimerCounterPinOffset to 4 (bits 4-7)
sendBuff[9] = 0; //DAC1 enable : not enabling, though could already be enabled
sendBuff[10] = 0;
FIOEIOAnalog = pow(2.0, numChannels)-1;
sendBuff[10] = (FIOEIOAnalog & 0xFF); //FIOAnalog
sendBuff[11] = FIOEIOAnalog / 256; //EIOAnalog
extendedChecksum(sendBuff, 12);
//Sending command to U3
if( (sendChars = LJUSB_Write(hDevice, sendBuff, 12)) < 12 )
{
if( sendChars == 0 )
printf("ConfigIO error : write failed\n");
else
printf("ConfigIO error : did not write all of the buffer\n");
return -1;
}
//Reading response from U3
if( (recChars = LJUSB_Read(hDevice, recBuff, 12)) < 12 )
{
if( recChars == 0 )
printf("ConfigIO error : read failed\n");
else
printf("ConfigIO error : did not read all of the buffer\n");
return -1;
}
checksumTotal = extendedChecksum16(recBuff, 12);
if( (uint8)((checksumTotal / 256) & 0xFF) != recBuff[5] )
{
printf("ConfigIO error : read buffer has bad checksum16(MSB)\n");
return -1;
}
if( (uint8)(checksumTotal & 0xFF) != recBuff[4] )
{
printf("ConfigIO error : read buffer has bad checksum16(LBS)\n");
return -1;
}
if( extendedChecksum8(recBuff) != recBuff[0] )
{
printf("ConfigIO error : read buffer has bad checksum8\n");
return -1;
}
if( recBuff[1] != (uint8)(0xF8) || recBuff[2] != (uint8)(0x03) || recBuff[3] != (uint8)(0x0B) )
{
printf("ConfigIO error : read buffer has wrong command bytes\n");
return -1;
}
if( recBuff[6] != 0 )
{
printf("ConfigIO error : read buffer received errorcode %d\n", recBuff[6]);
return -1;
}
if( recBuff[10] != (FIOEIOAnalog&(0xFF)) && recBuff[10] != ((FIOEIOAnalog&(0xFF))|(0x0F)) )
{
printf("ConfigIO error : FIOAnalog did not set correctly");
return -1;
}
if( recBuff[11] != FIOEIOAnalog/256 )
{
printf("ConfigIO error : EIOAnalog did not set correctly");
return -1;
}
*isDAC1Enabled = (int)recBuff[9];
return 0;
}
//Calls a Feedback low-level command 1000 times.
int allIO(HANDLE hDevice, u3CalibrationInfo *caliInfo, int isDAC1Enabled)
{
uint8 *sendBuff, *recBuff;
uint16 checksumTotal, ainBytes;
int sendChars, recChars, sendSize, recSize;
int valueDIPort, ret, i, j;
double valueAIN[16];
long time, numIterations;
double hardwareVersion;
hardwareVersion = caliInfo->hardwareVersion;
for( i = 0; i < 16; i++ )
valueAIN[i] = 9999;
valueDIPort = 0;
numIterations = 1000; //Number of iterations (how many times Feedback will
//be called)
//Setting up a Feedback command that will set CIO0-3 as input
sendBuff = (uint8 *)malloc(14*sizeof(uint8)); //Creating an array of size 14
recBuff = (uint8 *)malloc(10*sizeof(uint8)); //Creating an array of size 10
sendBuff[1] = (uint8)(0xF8); //Command byte
sendBuff[2] = 4; //Number of data words (.5 word for echo, 3.5 words for
// IOTypes and data)
sendBuff[3] = (uint8)(0x00); //Extended command number
sendBuff[6] = 0; //Echo
sendBuff[7] = 29; //IOType is PortDirWrite
sendBuff[8] = 0; //Writemask (for FIO)
sendBuff[9] = 0; //Writemask (for EIO)
sendBuff[10] = 15; //Writemask (for CIO)
sendBuff[11] = 0; //Direction (for FIO)
sendBuff[12] = 0; //Direction (for EIO)
sendBuff[13] = 0; //Direction (for CIO)
extendedChecksum(sendBuff, 14);
//Sending command to U3
if( (sendChars = LJUSB_Write(hDevice, sendBuff, 14)) < 14 )
{
if( sendChars == 0 )
printf("Feedback (CIO input) error : write failed\n");
else
printf("Feedback (CIO input) error : did not write all of the buffer\n");
ret = -1;
goto cleanmem;
}
//Reading response from U3
if( (recChars = LJUSB_Read(hDevice, recBuff, 10)) < 10 )
{
if( recChars == 0 )
{
printf("Feedback (CIO input) error : read failed\n");
ret = -1;
goto cleanmem;
}
else
printf("Feedback (CIO input) error : did not read all of the buffer\n");
}
checksumTotal = extendedChecksum16(recBuff, 10);
if( (uint8)((checksumTotal / 256) & 0xFF) != recBuff[5] )
{
printf("Feedback (CIO input) error : read buffer has bad checksum16(MSB)\n");
ret = -1;
goto cleanmem;
}
if( (uint8)(checksumTotal & 0xFF) != recBuff[4] )
{
printf("Feedback (CIO input) error : read buffer has bad checksum16(LBS)\n");
ret = -1;
goto cleanmem;
}
if( extendedChecksum8(recBuff) != recBuff[0] )
{
printf("Feedback (CIO input) error : read buffer has bad checksum8\n");
ret = -1;
goto cleanmem;
}
if( recBuff[1] != (uint8)(0xF8) || recBuff[3] != (uint8)(0x00) )
{
printf("Feedback (CIO input) error : read buffer has wrong command bytes \n");
ret = -1;
goto cleanmem;
}
if( recBuff[6] != 0 )
{
printf("Feedback (CIO input) error : received errorcode %d for frame %d in Feedback response. \n", recBuff[6], recBuff[7]);
ret = -1;
goto cleanmem;
}
free(sendBuff);
free(recBuff);
//Setting up Feedback command that will run 1000 times
if( ((sendSize = 7+2+1+numChannels*3) % 2) != 0 )
sendSize++;
//Creating an array of size sendSize
sendBuff = (uint8 *)malloc(sendSize*sizeof(uint8));
if( ((recSize = 9+3+numChannels*2) % 2) != 0 )
recSize++;
//Creating an array of size recSize
recBuff = (uint8 *)malloc(recSize*sizeof(uint8));
sendBuff[1] = (uint8)(0xF8); //Command byte
sendBuff[2] = (sendSize - 6)/2; //Number of data words
sendBuff[3] = (uint8)(0x00); //Extended command number
sendBuff[6] = 0; //Echo
//Setting DAC0 with 2.5 volt output
sendBuff[7] = 34; //IOType is DAC0
//Value is 2.5 volts (in binary)
getDacBinVoltCalibrated(caliInfo, 0, 2.5, &sendBuff[8]);
sendBuff[9] = 26; //IOType is PortStateRead
//Setting AIN read commands
for( j = 0; j < numChannels; j++ )
{
sendBuff[10 + j*3] = 1; //IOType is AIN
//Positive Channel (bits 0 - 4), LongSettling (bit 6) and QuickSample (bit 7)
sendBuff[11 + j*3] = j + (longSettling&(0x01))*64 + (quickSample&(0x01))*128;
sendBuff[12 + j*3] = 31; //Negative Channel is single-ended
}
if( (sendSize % 2) != 0 )
sendBuff[sendSize - 1] = 0;
extendedChecksum(sendBuff, sendSize);
time = getTickCount();
for( i = 0; i < numIterations; i++ )
{
//Sending command to U3
if( (sendChars = LJUSB_Write(hDevice, sendBuff, sendSize)) < sendSize )
{
if( sendChars == 0 )
printf("Feedback error (Iteration %d): write failed\n", i);
else
printf("Feedback error (Iteration %d): did not write all of the buffer\n", i);
ret = -1;
goto cleanmem;
}
//Reading response from U3
if( (recChars = LJUSB_Read(hDevice, recBuff, recSize)) < recSize )
{
if( recChars == 0 )
{
printf("Feedback error (Iteration %d): read failed\n", i);
ret = -1;
goto cleanmem;
}
else
printf("Feedback error (Iteration %d): did not read all of the expected buffer\n", i);
}
checksumTotal = extendedChecksum16(recBuff, recChars);
if( (uint8)((checksumTotal / 256) & 0xFF) != recBuff[5] )
{
printf("Feedback error (Iteration %d): read buffer has bad checksum16(MSB)\n", i);
ret = -1;
goto cleanmem;
}
if( (uint8)(checksumTotal & 0xFF) != recBuff[4] )
{
printf("Feedback error (Iteration %d): read buffer has bad checksum16(LBS)\n", i);
ret = -1;
goto cleanmem;
}
if( extendedChecksum8(recBuff) != recBuff[0] )
{
printf("Feedback error (Iteration %d): read buffer has bad checksum8\n", i);
ret = -1;
goto cleanmem;
}
if( recBuff[1] != (uint8)(0xF8) || recBuff[3] != (uint8)(0x00) )
{
printf("Feedback error (Iteration %d): read buffer has wrong command bytes \n", i);
ret = -1;
goto cleanmem;
}
if( recBuff[6] != 0 )
{
printf("Feedback error (Iteration %d): received errorcode %d for frame %d in Feedback response. \n", i, recBuff[6], recBuff[7]);
ret = -1;
goto cleanmem;
}
if( recChars != recSize )
{
ret = -1;
goto cleanmem;
}
//Getting CIO digital states
valueDIPort = recBuff[11];
//Getting AIN voltages
for( j = 0; j < numChannels; j++ )
{
ainBytes = recBuff[12+j*2] + recBuff[13+j*2]*256;
if( hardwareVersion >= 1.30 )
getAinVoltCalibrated_hw130(caliInfo, j, 31, ainBytes, &valueAIN[j]);
else
getAinVoltCalibrated(caliInfo, isDAC1Enabled, 31, ainBytes, &valueAIN[j]);
}
}
time = getTickCount() - time;
printf("Milliseconds per iteration = %.3f\n", (double)time / (double)numIterations);
printf("\nDigital Input = %d\n", valueDIPort);
printf("\nAIN readings from last iteration:\n");
for( j = 0; j < numChannels; j++ )
printf("%.3f\n", valueAIN[j]);
cleanmem:
free(sendBuff);
free(recBuff);
sendBuff = NULL;
recBuff = NULL;
return ret;
}

View File

@@ -0,0 +1,55 @@
#
# Makefile for U6 examples
#
U6ALLIO_SRC=u6allio.c u6.c
U6ALLIO_OBJ=$(U6ALLIO_SRC:.c=.o)
U6BASICCONFIGU6_SRC=u6BasicConfigU6.c
U6BASICCONFIGU6_OBJ=$(U6BASICCONFIGU6_SRC:.c=.o)
U6CONFIGU6_SRC=u6ConfigU6.c u6.c
U6CONFIGU6_OBJ=$(U6CONFIGU6_SRC:.c=.o)
U6EASY_SRC=u6EFunctions.c u6.c
U6EASY_OBJ=$(U6EASY_SRC:.c=.o)
U6FEEDBACK_SRC=u6Feedback.c u6.c
U6FEEDBACK_OBJ=$(U6FEEDBACK_SRC:.c=.o)
U6STREAM_SRC=u6Stream.c u6.c
U6STREAM_OBJ=$(U6STREAM_SRC:.c=.o)
U6LJTDAC_SRC=u6LJTDAC.c u6.c
U6LJTDAC_OBJ=$(U6LJTDAC_SRC:.c=.o)
SRCS=$(wildcard *.c)
HDRS=$(wildcard *.h)
CFLAGS +=-Wall -g
LIBS=-lm -llabjackusb
all: u6BasicConfigU6 u6ConfigU6 u6allio u6EFunctions u6Feedback u6Stream u6LJTDAC
u6BasicConfigU6: $(U6BASICCONFIGU6_OBJ)
$(CC) -o u6BasicConfigU6 $(U6BASICCONFIGU6_OBJ) $(LDFLAGS) $(LIBS)
u6ConfigU6: $(U6CONFIGU6_OBJ)
$(CC) -o u6ConfigU6 $(U6CONFIGU6_OBJ) $(LDFLAGS) $(LIBS)
u6allio: $(U6ALLIO_OBJ) $(HDRS)
$(CC) -o u6allio $(U6ALLIO_OBJ) $(LDFLAGS) $(LIBS)
u6EFunctions: $(U6EASY_OBJ) $(HDRS)
$(CC) -o u6EFunctions $(U6EASY_OBJ) $(LDFLAGS) $(LIBS)
u6Feedback: $(U6FEEDBACK_OBJ) $(HDRS)
$(CC) -o u6Feedback $(U6FEEDBACK_OBJ) $(LDFLAGS) $(LIBS)
u6Stream: $(U6STREAM_OBJ) $(HDRS)
$(CC) -o u6Stream $(U6STREAM_OBJ) $(LDFLAGS) $(LIBS)
u6LJTDAC: $(U6LJTDAC_OBJ) $(HDRS)
$(CC) -o u6LJTDAC $(U6LJTDAC_OBJ) $(LDFLAGS) $(LIBS)
clean:
rm -f *.o *~ u6Feedback u6BasicConfigU6 u6ConfigU6 u6allio u6Stream u6EFunctions u6LJTDAC

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,554 @@
//Author: LabJack
//April 6, 2011
//Header for U6 example helper functions.
#ifndef _U6_H
#define _U6_H
#include <sys/time.h>
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#include "labjackusb.h"
typedef unsigned char uint8;
typedef unsigned short uint16;
typedef unsigned int uint32;
//Structure for storing calibration constants
struct U6_CALIBRATION_INFORMATION {
uint8 prodID;
uint8 hiRes;
double ccConstants[40];
/*
Calibration constants order
0 - AIN +-10V Slope, GainIndex=0
1 - AIN +-10V Offset, GainIndex=0
2 - AIN +-1V Slope, GainIndex=1
3 - AIN +-1V Offset, GainIndex=1
4 - AIN +-100mV Slope, GainIndex=2
5 - AIN +-100mV Offset, GainIndex=2
6 - AIN +-10mV Slope, GainIndex=3
7 - AIN +-10mV Offset, GainIndex=3
8 - AIN +-10V Neg. Slope, GainIndex=0
9 - AIN +-10V Center Pt., GainIndex=0
10 - AIN +-1V Neg. Slope, GainIndex=1
11 - AIN +-1V Center Pt., GainIndex=1
12 - AIN +-100mV Neg. Slope, GainIndex=2
13 - AIN +-100mV Center Pt., GainIndex=2
14 - AIN +-10mV Neg. Slope, GainIndex=3
15 - AIN +-10mV Center Pt., GainIndex=3
16 - DAC0 Slope
17 - DAC0 Offset
18 - DAC1 Slope
19 - DAC1 Offset
20 - Current Output 0
21 - Current Output 1
22 - Temperature Slope
23 - Temperature Offset
High Resolution
24 - AIN +-10V Slope, GainIndex=0
25 - AIN +-10V Offset, GainIndex=0
26 - AIN +-1V Slope, GainIndex=1
27 - AIN +-1V Offset, GainIndex=1
28 - AIN +-100mV Slope, GainIndex=2
29 - AIN +-100mV Offset, GainIndex=2
30 - AIN +-10mV Slope, GainIndex=3
31 - AIN +-10mV Offset, GainIndex=3
32 - AIN +-10V Neg. Slope, GainIndex=0
33 - AIN +-10V Center Pt., GainIndex=0
34 - AIN +-1V Neg. Slope, GainIndex=1
35 - AIN +-1V Center Pt., GainIndex=1
36 - AIN +-100mV Neg. Slope, GainIndex=2
37 - AIN +-100mV Center Pt., GainIndex=2
38 - AIN +-10mV Neg. Slope, GainIndex=3
39 - AIN +-10mV Center Pt., GainIndex=3
*/
};
typedef struct U6_CALIBRATION_INFORMATION u6CalibrationInfo;
//Structure for storing LJTDAC calibration constants
struct U6_TDAC_CALIBRATION_INFORMATION{
uint8 prodID;
double ccConstants[4];
/*
DAC Calibration constants order
0 - SlopeA;
1 - OffsetA;
2 - SlopeB;
3 - OffsetB;
*/
};
typedef struct U6_TDAC_CALIBRATION_INFORMATION u6TdacCalibrationInfo;
/* Functions */
void normalChecksum( uint8 *b,
int n);
//Adds checksum to a data packet for normal command format.
//b = data packet for normal command
//n = size of data packet
void extendedChecksum( uint8 *b,
int n);
//Adds checksum to a data packet for extended command format.
//b = data packet for extended command
//n = size of data packet
uint8 normalChecksum8( uint8 *b,
int n);
//Returns the Checksum8 for a normal command data packet.
//b = data packet for normal command
//n = size of data packet
uint16 extendedChecksum16( uint8 *b,
int n);
//Returns the Checksum16 for a extended command data packet.
//b = data packet for extended command
//n = size of data packet
uint8 extendedChecksum8( uint8 *b);
//Returns the Checksum8 for a extended command data packet.
//b = data packet for extended command
HANDLE openUSBConnection( int localID);
//Opens a U6 connection over USB. Returns NULL on failure, or a HANDLE
//on success.
//localID = the local ID or serial number of the U6 you want to open
void closeUSBConnection( HANDLE hDevice);
//Closes a HANDLE to a U6 device.
long getTickCount();
//Returns the number of milliseconds that has elasped since the system was
//started.
long getCalibrationInfo( HANDLE hDevice,
u6CalibrationInfo *caliInfo);
//Gets calibration information from memory blocks 0-10 of a U6. Returns the
//calibration information in a calibrationInfo structure.
//hDevice = handle to a U6 device
//caliInfo = structure where calibrarion information will be stored
long getTdacCalibrationInfo( HANDLE hDevice,
u6TdacCalibrationInfo *caliInfo,
uint8 DIOAPinNum);
//Gets calibration information from the EEPROM of a LJTick-DAC (LJTDAC).
//Returns the calibration information in a u6TdacCalibrationInfo structure.
//hDevice = handle to a U6 device
//caliInfo = structure where LJTDAC calibration information will be stored
//DIOAPinNum = The U6 digital IO line where the LJTDAC DIOA pin is connected.
// The DIOB pin is assumed to be the next digital IO line.
double FPuint8ArrayToFPDouble( uint8 *buffer,
int startIndex);
//Converts a fixed point byte array (starting a startIndex) to a floating point
//double value. This function is used primarily by getCalibrationInfo.
long isCalibrationInfoValid( u6CalibrationInfo *caliInfo);
//Performs a simple check to determine if the caliInfo struct was set up by
//getCalibrationInfo. Returns 0 if caliInfo is not valid, or 1 if it is.
//caliInfo = structure where calibrarion information is stored
long isTdacCalibrationInfoValid( u6TdacCalibrationInfo *caliInfo);
//Performs a simple check to determine if the caliInfo struct was set up by
//getTdacCalibrationInfo. Returns 0 if caliInfo is not valid, or 1 if it is.
//caliInfo = structure where LJTDAC calibration information is stored
long getAinVoltCalibrated( u6CalibrationInfo *caliInfo,
int resolutionIndex,
int gainIndex,
int bits24,
uint32 bytesVolt,
double *analogVolt);
//Translates the binary AIN reading from the U6 to a voltage value (calibrated)
//in Volts. Call getCalibrationInfo first to set up caliInfo. Returns -1 on
//error, 0 on success.
//caliInfo = structure where calibrarion information is stored
//resolutionIndex = The resolution index used when read the binary AIN voltage.
// 0=default, 1-8 for high speed ADC, 9-13 for higres ADC (U6-Pro).
//gainIndex = The gain index used when reading the binary AIN voltage.
// 0 = +-10V, 1 = +-1V, 2 = +-100mV, 3 = +-10mV
//bits24 = Indicates if the voltage bytes passed is a 24-bit binary value,
// otherwise considered to be 16-bits.
//bytesVolt = The binary voltage that will be converted. Can be a 16 or 24 bit
// value.
//analogVolt = The converted analog voltage.
long getDacBinVoltCalibrated8Bit( u6CalibrationInfo *caliInfo,
int dacNumber,
double analogVolt,
uint8 *bytesVolt8);
//Translates an analog output voltage value (Volts) to a binary 8 bit value
//(calibrated) that can be sent to a U6. Call getCalibrationInfo first to set
//up caliInfo. Returns -1 on error, 0 on success.
//caliInfo = Structure where calibrarion information is stored
//dacNumber = Channel number of the DAC.
//analogVolt = The analog voltage that will be converted.
//bytesVolt8 = The converted binary 8 bit value.
long getDacBinVoltCalibrated16Bit( u6CalibrationInfo *caliInfo,
int dacNumber,
double analogVolt,
uint16 *bytesVolt16);
//Translates a analog output voltage value (Volts) to a binary 16 bit value
//(calibrated) that can be sent to a U6. Call getCalibrationInfo first to set
//up caliInfo. Returns -1 on error, 0 on success.
//caliInfo = Structure where calibrarion information is stored.
//dacNumber = Channel number of the DAC.
//analogVolt = The analog voltage that will be converted.
//bytesVolt16 = The converted binary 16 bit value.
long getTempKCalibrated( u6CalibrationInfo *caliInfo,
int resolutionIndex,
int gainIndex,
int bits24,
uint32 bytesTemp,
double *kelvinTemp);
//Translates the binary reading from the U6 to a temperature value
//(calibrated) in Kelvin. Call getCalibrationInfo first to set up caliInfo.
//Returns -1 on error, 0 on success.
//caliInfo = Structure where calibration information is stored.
//resolutionIndex = The resolution index used when reading the temperature.
// 0=default, 1-8 for high speed ADC, 9-13 for higres ADC (U6-Pro).
//gainIndex = The gain index used when reading the temperature.
// 0 = +-10V, 1 = +-1V, 2 = +-100mV, 3 = +-10mV
//bits24 = Indicates if the temperature bytes passed is a 24-bit value value,
// otherwise considered to be 16-bits.
//bytesTemp = The binary temperature that will be converted. Can be a 16 or 24 bit
// value.
//kelvinTemp = The converted Kelvins temperature.
long getTdacBinVoltCalibrated( u6TdacCalibrationInfo *caliInfo,
int dacNumber,
double analogVolt,
uint16 *bytesVolt);
//Translates a voltage value (Volts) to binary analog input bytes (calibrated)
//that can be sent to a LJTick-DAC (LJTDAC). Call getLJTDACCalibrationInfo
//first to set up caliInfo. Returns -1 on error, 0 on success.
//caliInfo = Structure where LJTDAC calibrarion information is stored.
//dacNumber = Channel number of the DAC (0 = DACA, 1 = DACB).
//analogVoltage = The analog voltage that will be converted.
//bytesVoltage = The converted 2 byte voltage.
long getAinVoltUncalibrated( int resolutionIndex,
int gainIndex,
int bits24,
uint32 bytesVolt,
double *analogVolt);
//Translates the binary AIN reading from the U6 to a voltage value
//(uncalibrated) in Volts. Returns -1 on error, 0 on success.
//resolutionIndex = The resolution index used when read the binary AIN voltage.
// 0=default, 1-8 for high speed ADC, 9-13 for higres ADC (U6-Pro).
//gainIndex,= The gain index used when reading the binary AIN voltage.
// 0 = +-10V, 1 = +-1V, 2 = +-100mV, 3 = +-10mV
//bits24,= Indicates if the voltage bytes passed is a 24-bit binary value,
// otherwise considered to be 16-bits.
//bytesVolt = The binary voltage that will be converted. Can be a 16 or 24 bit
// value.
//analogVolt = The converted analog voltage.
long getDacBinVoltUncalibrated8Bit( int dacNumber,
double analogVolt,
uint8 *bytesVolt8);
//Translates a DAC voltage value (Volts) to a binary 8 bit value (uncalibrated)
//that can be sent to a U6. Returns -1 on error, 0 on success.
//dacNumber = Channel number of the DAC.
//analogVolt = The analog voltage that will be converted.
//bytesVolt = The converted binary 8 bit value.
long getDacBinVoltUncalibrated16Bit( int dacNumber,
double analogVolt,
uint16 *bytesVolt16);
//Translates a DAC voltage value (Volts) to a binary 16 bit value
//(uncalibrated) that can be sent to a U6. Returns -1 on error, 0 on
//success.
//dacNumber = Channel number of the DAC.
//analogVolt = The analog voltage that needs to be converted.
//bytesVolt = The converted binary 16 bit value.
long getTempKUncalibrated( int resolutionIndex,
int gainIndex,
int bits24,
uint32 bytesTemp,
double *kelvinTemp);
//Translates the binary reading from the U6, to a temperature value
//(uncalibrated) in Kelvin.
//Returns -1 on error, 0 on success.
//resolutionIndex = The resolution index used when reading the temperature.
// 0=default, 1-8 for high speed ADC, 9-13 for higres ADC (U6-Pro).
//gainIndex = The gain index used when reading the temperature.
// 0 = +-10V, 1 = +-1V, 2 = +-100mV, 3 = +-10mV
//bits24 = Indicates if the temperature bytes passed is a 24-bit value value,
// otherwise considered to be 16-bits.
//bytesTemp = the 2 byte binary temperature that will be converted.
//kelvinTemp = the converted Kelvins temperature
long I2C( HANDLE hDevice,
uint8 I2COptions,
uint8 SpeedAdjust,
uint8 SDAPinNum,
uint8 SCLPinNum,
uint8 Address,
uint8 NumI2CBytesToSend,
uint8 NumI2CBytesToReceive,
uint8 *I2CBytesCommand,
uint8 *Errorcode,
uint8 *AckArray,
uint8 *I2CBytesResponse);
//This function will perform the I2C low-level function call. Please refer to
//section 5.3.19 of the U6 User's Guide for parameter documentation. Returns
//-1 on error, 0 on success.
//hDevice = handle to a U6 device
//I2COptions = byte 6 of the command
//SpeedAdjust = byte 7 of the command
//SDAPinNum = byte 8 of the command
//SCLPinNum = byte 9 of the command
//Address = byte 10 of the command
//NumI2CBytesToSend = byte 12 of the command
//NumI2CBytesToReceive = byte 13 of the command
//*I2CBytesCommand = Array that holds bytes 14 and above of the command. Needs
// to be at least NumI2CBytesToSend elements in size.
//*Errorcode = returns byte 6 of the response
//*AckArray = Array that returns bytes 8 - 11 of the response. Needs to be at
// least 4 elements in size.
//*I2CBytesResponse = Array that returns bytes 12 and above of the response.
// Needs to be at least NumI2CBytesToReceive elements in
// size.
/* Easy Functions (Similar to the easy functions in the UD driver for Windows) */
long eAIN( HANDLE Handle,
u6CalibrationInfo *CalibrationInfo,
long ChannelP,
long ChannelN,
double *Voltage,
long Range,
long Resolution,
long Settling,
long Binary,
long Reserved1,
long Reserved2);
//An "easy" function that returns a reading from one analog input. Returns 0
//for no error, or -1 or >0 value (low-level errorcode) on error.
//Call getCalibrationInfo first to set up CalibrationInfo.
//Handle = Handle to a U6 device.
//CalibrationInfo = Structure where calibration information is stored.
//ChannelP = The positive AIN channel to acquire.
//ChannelN = The negative AIN channel to acquire. For differential readings,
// this should be ChannelP+1. For single-ended readings, this
// parameter should be 0 or 15
//Voltage = Returns the analog input reading, which is generally a voltage.
//Range = Pass a range constant.
//Resolution = Pass a resolution index.
//Settling = Pass a settling factor.
//Binary = If this is nonzero (True), the Voltage parameter will return the raw
// binary value.
//Reserved (1&2) = Pass 0.
long eDAC( HANDLE Handle,
u6CalibrationInfo *CalibrationInfo,
long Channel,
double Voltage,
long Binary,
long Reserved1,
long Reserved2);
//An "easy" function that writes a value to one analog output. Returns 0 for
//no error, or -1 or >0 value (low-level errorcode) on error.
//Call getCalibrationInfo first to set up CalibrationInfo.
//Handle = Handle to a U6 device.
//CalibrationInfo = Structure where calibrarion information is stored
//Channel = The analog output channel to write to.
//Voltage = The voltage to write to the analog output.
//Binary = If this is nonzero (True), the value passed for Voltage should be
// binary.
//Reserved (1&2) = Pass 0.
long eDI( HANDLE Handle,
long Channel,
long *State);
//An "easy" function that reads the state of one digital input. Returns 0 for
//no error, or -1 or >0 value (low-level errorcode) on error.
//Handle = Handle to a U6 device.
//Channel = The channel to read. 0-19 corresponds to FIO0-CIO3.
//State = Returns the state of the digital input. 0=False=Low and 1=True=High.
long eDO( HANDLE Handle,
long Channel,
long State);
//An "easy" function that writes the state of one digital output. This
//function does not automatically configure the specified channel as digital,
//unless ConfigIO is set as True. Returns 0 for no error, or -1 or >0 value
//(low-level errorcode) on error.
//Handle = Handle to a U6 device.
//Channel = The channel to write to. 0-19 corresponds to FIO0-CIO3.
//State = The state to write to the digital output. 0=False=Low and
// 1=True=High.
long eTCConfig( HANDLE Handle,
long *aEnableTimers,
long *aEnableCounters,
long TCPinOffset,
long TimerClockBaseIndex,
long TimerClockDivisor,
long *aTimerModes,
double *aTimerValues,
long Reserved1,
long Reserved2);
//An "easy" function that configures and initializes all the timers and
//counters. When needed, this function automatically configures the needed
//lines as digital. Returns 0 for no error, or -1 or >0 value (low-level
//errorcode) on error.
//Handle = Handle to a U6 device.
//aEnableTimers = An array where each element specifies whether that timer is
// enabled. Timers must be enabled in order starting from 0, so
// for instance, Timer1 cannot be enabled without enabling Timer
// 0 also. A nonzero for an array element specifies to enable
// that timer. For the U6, this array must always have at least
// 4 elements.
//aEnableCounters = An array where each element specifies whether that counter
// is enabled. Counters do not have to be enabled in order
// starting from 0, so Counter1 can be enabled when Counter0
// is disabled. A nonzero value for an array element
// specifies to enable that counter. For the U6, this array
// must always have at least 2 elements.
//TCPinOffset = Value from 0-8 specifies where to start assigning timers and
// counters.
//TimerClockBaseIndex = Pass a constant to set the timer base clock. The
// default is LJ_tc48MHZ.
//TimerClockDivisor = Pass a divisor from 0-255 where 0 is a divisor of 256.
//aTimerModes = An array where each element is a constant specifying the mode
// for that timer. For the U6, this array must always have at
// least 4 elements.
//aTimerValues = An array where each element specifies the initial value for
// that timer. For the U6, this array must always have at least
// 2 elements.
//Reserved (1&2) = Pass 0.
long eTCValues( HANDLE Handle,
long *aReadTimers,
long *aUpdateResetTimers,
long *aReadCounters,
long *aResetCounters,
double *aTimerValues,
double *aCounterValues,
long Reserved1,
long Reserved2);
//An "easy" function that updates and reads all the timers and counters.
//Returns 0 for no error, or -1 or >0 value (low-level errorcode) on error.
//Handle = Handle to a U6 device.
//aReadTimers = An array where each element specifies whether to read that
// timer. A nonzero value for an array element specifies to read
// that timer. For the U6, this array must always have at least 4
// elements.
//aUpdateResetTimers = An array where each element specifies whether to
// update/reset that timers. A nonzero value for an array
// element specifies to update/reset that timer. For the
// U6, this array must always have at least 4 elements.
//aReadCounters = An array where each element specifies whether to read that
// counter. A nonzero value for an array element specifies to
// read that counter. For the U6, this array must always have
// at least 2 elements.
//aResetCounters = An array where each element specifies whether to reset that
// counter. A nonzero value for an array element specifies to
// reset that counter. For the U6, this array must always have
// at least 2 elements.
//aTimerValues = Input: An array where each element is the new value for that
// timer. Each value is only updated if the appropriate element
// is set in the aUpdateResetTimers array.
// Output: An array where each element is the value read from
// that timer if the appropriate element is set in the
// aReadTimers array. If the timer mode set for the timer is
// Quadrature Input, the value needs to be converted from an
// unsigned 32-bit integer to a signed 32-bit integer (2s
// complement). For the U6, this array must always have at least
// 4 elements.
//aCounterValues = An array where each element is the value read from that
// counter if the appropriate element is set in the aReadTimers
// array. For the U6, this array must always have at least 2
// elements.
//Reserved (1&2) = Pass 0.
/* Easy Function Helpers */
long ehConfigIO( HANDLE hDevice,
uint8 inWriteMask,
uint8 inNumberTimersEnabled,
uint8 inCounterEnable,
uint8 inPinOffset,
uint8 *outNumberTimersEnabled,
uint8 *outCounterEnable,
uint8 *outPinOffset);
//Used by the eTCConfig easy functions. This function takes the ConfigIO
//low-level command and response bytes (not including checksum and command
//bytes) as its parameter and performs a ConfigIO call with the U6. Returns
//-1 or errorcode (>1 value) on error, 0 on success.
long ehConfigTimerClock( HANDLE hDevice,
uint8 inTimerClockConfig,
uint8 inTimerClockDivisor,
uint8 *outTimerClockConfig,
uint8 *outTimerClockDivisor);
//Used by the eTCConfig easy function. This function takes the
//ConfigTimerClock low-level command and response bytes (not including checksum
//and command bytes) as its parameter and performs a ConfigTimerClock call with
//the U6. Returns -1 or errorcode (>1 value) on error, 0 on success.
long ehFeedback( HANDLE hDevice,
uint8 *inIOTypesDataBuff,
long inIOTypesDataSize,
uint8 *outErrorcode,
uint8 *outErrorFrame,
uint8 *outDataBuff,
long outDataSize);
//Used by the all of the easy functions. This function takes the Feedback
//low-level command and response bytes (not including checksum and command
//bytes) as its parameter and performs a Feedback call with the U6. Returns -1
//or errorcode (>1 value) on error, 0 on success.
/* Easy function constants */
// ranges:
#define LJ_rgAUTO 0
#define LJ_rgBIP10V 2 // -10V to +10V
#define LJ_rgBIP1V 8 // -1V to +1V
#define LJ_rgBIPP1V 10 // -0.1V to +0.1V
#define LJ_rgBIPP01V 11 // -0.01V to +0.01V
// timer clocks:
#define LJ_tc4MHZ 20
#define LJ_tc12MHZ 21
#define LJ_tc48MHZ 22
#define LJ_tc1MHZ_DIV 23
#define LJ_tc4MHZ_DIV 24
#define LJ_tc12MHZ_DIV 25
#define LJ_tc48MHZ_DIV 26
// timer modes:
#define LJ_tmPWM16 0 // 16 bit PWM
#define LJ_tmPWM8 1 // 8 bit PWM
#define LJ_tmRISINGEDGES32 2 // 32-bit rising to rising edge measurement
#define LJ_tmFALLINGEDGES32 3 // 32-bit falling to falling edge measurement
#define LJ_tmDUTYCYCLE 4 // duty cycle measurement
#define LJ_tmFIRMCOUNTER 5 // firmware based rising edge counter
#define LJ_tmFIRMCOUNTERDEBOUNCE 6 // firmware counter with debounce
#define LJ_tmFREQOUT 7 // frequency output
#define LJ_tmQUAD 8 // Quadrature
#define LJ_tmTIMERSTOP 9 // stops another timer after n pulses
#define LJ_tmSYSTIMERLOW 10 // read lower 32-bits of system timer
#define LJ_tmSYSTIMERHIGH 11 // read upper 32-bits of system timer
#define LJ_tmRISINGEDGES16 12 // 16-bit rising to rising edge measurement
#define LJ_tmFALLINGEDGES16 13 // 16-bit falling to falling edge measurement
#endif

View File

@@ -0,0 +1,230 @@
/*
An example that shows a minimal use of Exodriver without the use of functions
hidden in header files.
You can compile this example with the following command:
$ g++ -lm -llabjackusb u6BasicConfigU6.c
It is also included in the Makefile.
*/
/* Includes */
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include "labjackusb.h"
// Defines how long the command is
#define CONFIGU6_COMMAND_LENGTH 26
// Defines how long the response is
#define CONFIGU6_RESPONSE_LENGTH 38
/* Buffer Helper Functions Protypes */
// Takes a buffer and an offset, and turns it into a 32-bit integer
int makeInt(BYTE * buffer, int offset);
// Takes a buffer and an offset, and turns it into a 16-bit integer
int makeShort(BYTE * buffer, int offset);
// Takes a buffer and calculates the checksum8 of it.
BYTE calculateChecksum8(BYTE* buffer);
// Takes a buffer and length, and calculates the checksum16 of the buffer.
int calculateChecksum16(BYTE* buffer, int len);
/* LabJack Related Helper Functions Protoypes */
// Demonstrates how to build the ConfigU6 packet.
void buildConfigU6Bytes(BYTE * sendBuffer);
// Demonstrates how to check a response for errors.
int checkResponseForErrors(BYTE * recBuffer);
// Demonstrates how to parse the response of ConfigU6.
void parseConfigU6Bytes(BYTE * recBuffer);
int main() {
// Setup the variables we will need.
int r = 0; // For checking return values
HANDLE devHandle = 0;
BYTE sendBuffer[CONFIGU6_COMMAND_LENGTH], recBuffer[CONFIGU6_RESPONSE_LENGTH];
// Open the U6
devHandle = LJUSB_OpenDevice(1, 0, U6_PRODUCT_ID);
if( devHandle == NULL ) {
printf("Couldn't open U6. Please connect one and try again.\n");
exit(-1);
}
// Builds the ConfigU6 command
buildConfigU6Bytes(sendBuffer);
// Write the command to the device.
// LJUSB_Write( handle, sendBuffer, length of sendBuffer )
r = LJUSB_Write( devHandle, sendBuffer, CONFIGU6_COMMAND_LENGTH );
if( r != CONFIGU6_COMMAND_LENGTH ) {
printf("An error occurred when trying to write the buffer. The error was: %d\n", errno);
// *Always* close the device when you error out.
LJUSB_CloseDevice(devHandle);
exit(-1);
}
// Read the result from the device.
// LJUSB_Read( handle, recBuffer, number of bytes to read)
r = LJUSB_Read( devHandle, recBuffer, CONFIGU6_RESPONSE_LENGTH );
if( r != CONFIGU6_RESPONSE_LENGTH ) {
printf("An error occurred when trying to read from the U6. The error was: %d\n", errno);
LJUSB_CloseDevice(devHandle);
exit(-1);
}
// Check the command for errors
if( checkResponseForErrors(recBuffer) != 0 ){
LJUSB_CloseDevice(devHandle);
exit(-1);
}
// Parse the response into something useful
parseConfigU6Bytes(recBuffer);
//Close the device.
LJUSB_CloseDevice(devHandle);
return 0;
}
/* ------------- LabJack Related Helper Functions Definitions ------------- */
// Uses information from section 5.2.2 of the U6 User's Guide to make a ConfigU6
// packet.
// http://labjack.com/support/u6/users-guide/5.2.2
void buildConfigU6Bytes(BYTE * sendBuffer) {
int i; // For loops
int checksum = 0;
// Build up the bytes
//sendBuffer[0] = Checksum8
sendBuffer[1] = 0xF8;
sendBuffer[2] = 0x0A;
sendBuffer[3] = 0x08;
//sendBuffer[4] = Checksum16 (LSB)
//sendBuffer[5] = Checksum16 (MSB)
// We just want to read, so we set the WriteMask to zero, and zero out the
// rest of the bytes.
sendBuffer[6] = 0;
for( i = 7; i < CONFIGU6_COMMAND_LENGTH; i++){
sendBuffer[i] = 0;
}
// Calculate and set the checksum16
checksum = calculateChecksum16(sendBuffer, CONFIGU6_COMMAND_LENGTH);
sendBuffer[4] = (BYTE)( checksum & 0xff );
sendBuffer[5] = (BYTE)( (checksum / 256) & 0xff );
// Calculate and set the checksum8
sendBuffer[0] = calculateChecksum8(sendBuffer);
// The bytes have been set, and the checksum calculated. We are ready to
// write to the U6.
}
// Checks the response for any errors.
int checkResponseForErrors(BYTE * recBuffer) {
if(recBuffer[0] == 0xB8 && recBuffer[1] == 0xB8) {
// If the packet is [ 0xB8, 0xB8 ], that's a bad checksum.
printf("The U6 detected a bad checksum. Double check your checksum calculations and try again.\n");
return -1;
}
else if (recBuffer[1] != 0xF8 || recBuffer[2] != 0x10 || recBuffer[3] != 0x08) {
// Make sure the command bytes match what we expect.
printf("Got the wrong command bytes back from the U6.\n");
return -1;
}
// Calculate the checksums.
int checksum16 = calculateChecksum16(recBuffer, CONFIGU6_RESPONSE_LENGTH);
BYTE checksum8 = calculateChecksum8(recBuffer);
if ( checksum8 != recBuffer[0] || recBuffer[4] != (BYTE)( checksum16 & 0xff ) || recBuffer[5] != (BYTE)( (checksum16 / 256) & 0xff ) ) {
// Check the checksum
printf("Response had invalid checksum.\n%d != %d, %d != %d, %d != %d\n", checksum8, recBuffer[0], (BYTE)( checksum16 & 0xff ), recBuffer[4], (BYTE)( (checksum16 / 256) & 0xff ), recBuffer[5] );
return -1;
}
else if ( recBuffer[6] != 0 ) {
// Check the error code in the packet. See section 5.3 of the U6
// User's Guide for errorcode descriptions.
printf("Command returned with an errorcode = %d\n", recBuffer[6]);
return -1;
}
return 0;
}
// Parses the ConfigU6 packet into something useful.
void parseConfigU6Bytes(BYTE * recBuffer){
printf("Results of ConfigU6:\n");
printf(" FirmwareVersion = %d.%02d\n", recBuffer[10], recBuffer[9]);
printf(" BootloaderVersion = %d.%02d\n", recBuffer[12], recBuffer[11]);
printf(" HardwareVersion = %d.%02d\n", recBuffer[14], recBuffer[13]);
printf(" SerialNumber = %d\n", makeInt(recBuffer, 15));
printf(" ProductID = %d\n", makeShort(recBuffer, 19));
printf(" LocalID = %d\n", recBuffer[21]);
printf(" VersionInfo = %d\n", recBuffer[37]);
if( recBuffer[37] == 4 ){
printf(" DeviceName = U6\n");
}
else if(recBuffer[37] == 12) {
printf(" DeviceName = U6-Pro\n");
}
}
/* ---------------- Buffer Helper Functions Definitions ---------------- */
// Takes a buffer and an offset, and turns into an 32-bit integer
int makeInt(BYTE * buffer, int offset){
return (buffer[offset+3] << 24) + (buffer[offset+2] << 16) + (buffer[offset+1] << 8) + buffer[offset];
}
// Takes a buffer and an offset, and turns into an 16-bit integer
int makeShort(BYTE * buffer, int offset) {
return (buffer[offset+1] << 8) + buffer[offset];
}
// Calculates the checksum8
BYTE calculateChecksum8(BYTE* buffer){
int i; // For loops
int temp; // For holding a value while we working.
int checksum = 0;
for( i = 1; i < 6; i++){
checksum += buffer[i];
}
temp = checksum/256;
checksum = ( checksum - 256 * temp ) + temp;
temp = checksum/256;
return (BYTE)( ( checksum - 256 * temp ) + temp );
}
// Calculates the checksum16
int calculateChecksum16(BYTE* buffer, int len){
int i;
int checksum = 0;
for( i = 6; i < len; i++){
checksum += buffer[i];
}
return checksum;
}

View File

@@ -0,0 +1,115 @@
//Author : LabJack
//April 6, 2011
//This example calls the ConfigU6 low-level function and reads back
//configuration settings.
#include "u6.h"
int configU6_example(HANDLE hDevice);
int main(int argc, char **argv)
{
HANDLE hDevice;
//Opening first found U6 over USB
if( (hDevice = openUSBConnection(-1)) == NULL )
return 1;
configU6_example(hDevice);
closeUSBConnection(hDevice);
return 0;
}
//Sends a ConfigU3 low-level command to read back configuration settings
int configU6_example(HANDLE hDevice)
{
uint8 sendBuff[26];
uint8 recBuff[38];
uint16 checksumTotal;
int sendChars, recChars, i;
sendBuff[1] = (uint8)(0xF8); //Command byte
sendBuff[2] = (uint8)(0x0A); //Number of data words
sendBuff[3] = (uint8)(0x08); //Extended command number
//Setting all bytes to zero since we only want to read back the U6
//configuration settings
for( i = 6; i < 26; i++ )
sendBuff[i] = 0;
/* The commented out code below sets the U6's local ID to 3. After setting
the local ID, reset the device for this change to take effect. */
//sendBuff[6] = 8; //WriteMask : setting bit 3
//sendBuff[8] = 3; //LocalID : setting local ID to 3
extendedChecksum(sendBuff, 26);
//Sending command to U6
if( (sendChars = LJUSB_Write(hDevice, sendBuff, 26)) < 26 )
{
if( sendChars == 0 )
printf("ConfigU6 error : write failed\n");
else
printf("ConfigU6 error : did not write all of the buffer\n");
return -1;
}
//Reading response from U6
if( (recChars = LJUSB_Read(hDevice, recBuff, 38)) < 38 )
{
if( recChars == 0 )
printf("ConfigU6 error : read failed\n");
else
printf("ConfigU6 error : did not read all of the buffer\n");
return -1;
}
checksumTotal = extendedChecksum16(recBuff, 38);
if( (uint8)((checksumTotal / 256) & 0xff) != recBuff[5] )
{
printf("ConfigU6 error : read buffer has bad checksum16(MSB)\n");
return -1;
}
if( (uint8)(checksumTotal & 0xff) != recBuff[4] )
{
printf("ConfigU6 error : read buffer has bad checksum16(LBS)\n");
return -1;
}
if( extendedChecksum8(recBuff) != recBuff[0] )
{
printf("ConfigU6 error : read buffer has bad checksum8\n");
return -1;
}
if( recBuff[1] != (uint8)(0xF8) || recBuff[2] != (uint8)(0x10) || recBuff[3] != (uint8)(0x08) )
{
printf("ConfigU6 error : read buffer has wrong command bytes\n");
return -1;
}
if( recBuff[6] != 0 )
{
printf("ConfigU6 error : read buffer received errorcode %d\n", recBuff[6]);
return -1;
}
printf("U6 Configuration Settings:\n");
printf("FirmwareVersion: %.3f\n", recBuff[10] + recBuff[9]/100.0);
printf("BootloaderVersion: %.3f\n", recBuff[12] + recBuff[11]/100.0);
printf("HardwareVersion: %.3f\n", recBuff[14] + recBuff[13]/100.0);
printf("SerialNumber: %u\n", recBuff[15] + recBuff[16]*256 + recBuff[17]*65536 + recBuff[18]*16777216);
printf("ProductID: %d\n", recBuff[19] + recBuff[20]*256);
printf("LocalID: %d\n", recBuff[21]);
printf("Version Info: %d\n", recBuff[37]);
printf(" U6 (bit 2): %d\n", ((recBuff[37]/4)&1));
printf(" U6-Pro (bit 3): %d\n", ((recBuff[37]/8)&1));
return 0;
}

View File

@@ -0,0 +1,96 @@
//Author: LabJack
//April 5, 2011
//This examples demonstrates how to read from analog inputs (AIN) and digital inputs(FIO),
//set analog outputs (DAC) and digital outputs (FIO), and how to configure and enable
//timers and counters and read input timers and counters values using the "easy" functions.
#include "u6.h"
#include <unistd.h>
int main(int argc, char **argv)
{
HANDLE hDevice;
u6CalibrationInfo caliInfo;
int localID;
long error;
//Open first found U6 over USB
localID = -1;
if( (hDevice = openUSBConnection(localID)) == NULL )
goto done;
//Get calibration information from U6
if( getCalibrationInfo(hDevice, &caliInfo) < 0 )
goto close;
//Set DAC0 to 3.1 volts.
printf("Calling eDAC to set DAC0 to 3.1 V\n");
if( (error = eDAC(hDevice, &caliInfo, 0, 3.1, 0, 0, 0)) != 0 )
goto close;
//Read the single-ended voltage from AIN3
printf("\nCalling eAIN to read voltage from AIN3\n");
double dblVoltage;
if( (error = eAIN(hDevice, &caliInfo, 3, 15, &dblVoltage, 0, 0, 0, 0, 0, 0)) != 0 )
goto close;
printf("AIN3 value = %.3f\n", dblVoltage);
//Set FIO2 to output-high
printf("\nCalling eDO to set FIO2 to output-high\n");
if( (error = eDO(hDevice, 2, 1)) != 0 )
goto close;
//Read state of FIO3
printf("\nCalling eDI to read the state of FIO3\n");
long lngState;
if( (error = eDI(hDevice, 3, &lngState)) != 0 )
goto close;
printf("FIO3 state = %ld\n", lngState);
//Enable and configure 1 output timer and 1 input timer, and enable counter0
printf("\nCalling eTCConfig to enable and configure 1 output timer (Timer0) and 1 input timer (Timer1), and enable counter0\n");
long alngEnableTimers[4] = {1, 1, 0, 0}; //Enable Timer0-Timer1
long alngTimerModes[4] = {LJ_tmPWM8, LJ_tmRISINGEDGES32, 0, 0}; //Set timer modes
double adblTimerValues[4] = {16384, 0, 0, 0}; //Set PWM8 duty-cycles to 75%
long alngEnableCounters[2] = {1, 0}; //Enable Counter0
if( (error = eTCConfig(hDevice, alngEnableTimers, alngEnableCounters, 0, LJ_tc48MHZ, 0, alngTimerModes, adblTimerValues, 0, 0)) != 0 )
goto close;
printf("\nWaiting for 1 second...\n");
sleep(1);
//Read and reset the input timer (Timer1), read and reset Counter0, and update the
//value (duty-cycle) of the output timer (Timer0)
printf("\nCalling eTCValues to read and reset the input Timer1 and Counter0, and update the value (duty-cycle) of the output Timer0\n");
long alngReadTimers[4] = {0, 1, 0, 0}; //Read Timer1
long alngUpdateResetTimers[4] = {1, 0, 0, 0}; //Update timer0
long alngReadCounters[2] = {1, 0}; //Read Counter0
long alngResetCounters[2] = {1, 0}; //Reset Counter 1
double adblCounterValues[2] = {0, 0};
adblTimerValues[0] = 32768; //Change Timer0 duty-cycle to 50%
adblTimerValues[1] = 0;
if( (error = eTCValues(hDevice, alngReadTimers, alngUpdateResetTimers, alngReadCounters, alngResetCounters, adblTimerValues, adblCounterValues, 0, 0)) != 0 )
goto close;
printf("Timer1 value = %.0f\n", adblTimerValues[1]);
printf("Counter0 value = %.0f\n", adblCounterValues[0]);
//Disable all timers and counters
alngEnableTimers[0] = 0;
alngEnableTimers[1] = 0;
alngEnableTimers[2] = 0;
alngEnableTimers[3] = 0;
alngEnableCounters[0] = 0;
alngEnableCounters[1] = 0;
if( (error = eTCConfig(hDevice, alngEnableTimers, alngEnableCounters, 0, LJ_tc48MHZ, 0, alngTimerModes, adblTimerValues, 0, 0)) != 0 )
goto close;
printf("\nCalling eTCConfig to disable all timers and counters\n");
close:
if( error > 0 )
printf("Received an error code of %ld\n", error);
closeUSBConnection(hDevice);
done:
return 0;
}

View File

@@ -0,0 +1,533 @@
//Author : LabJack
//April 5, 2011
//This example does the following:
// Sets DAC0 to 3.5 volts.
// Reads AIN0-AIN1, and AIN0 differential voltage.
// Sets FIO0 to digital input.
// Sets FIO1 and FIO2 to Timers 0 and 1 with modes PMW8 and PMW16.
// Sets and reads FIO3 as Counter 1
// Reads the temperature.
#include <unistd.h>
#include <termios.h>
#include "u6.h"
static struct termios termNew, termOrig;
static int peek = -1;
int configIO_example(HANDLE hDevice, int enable);
int configTimerClock_example(HANDLE hDevice);
int feedback_setup_example(HANDLE hDevice, u6CalibrationInfo *caliInfo);
int feedback_loop_example(HANDLE hDevice, u6CalibrationInfo *caliInfo);
void setTerm();
int kbhit();
void unsetTerm();
int main(int argc, char **argv)
{
HANDLE hDevice;
u6CalibrationInfo caliInfo;
//setting terminal settings
setTerm();
//Opening first found U6 over USB
if( (hDevice = openUSBConnection(-1)) == NULL )
goto done;
//Getting calibration information from U6
if( getCalibrationInfo(hDevice, &caliInfo) < 0 )
goto close;
if( configIO_example(hDevice, 1) != 0 )
goto close;
if( configTimerClock_example(hDevice) != 0 )
goto close;
if( feedback_setup_example(hDevice, &caliInfo) != 0 )
goto close;
if( feedback_loop_example(hDevice, &caliInfo) != 0 )
goto close;
configIO_example(hDevice, 0);
close:
closeUSBConnection(hDevice);
done:
printf("\nDone\n");
//Setting terminal settings to previous settings
unsetTerm();
return 0;
}
//Sends a ConfigIO low-level command that configures the FIOs, DAC, Timers and
//Counters for this example
int configIO_example(HANDLE hDevice, int enable)
{
uint8 sendBuff[16], recBuff[16];
uint16 checksumTotal;
int sendChars, recChars, i;
uint8 numTimers, counterEnable;
if( enable == 0 )
{
numTimers = 0; //Setting NumberTimersEnabled byte to zero to turn off all Timers
counterEnable = 0 + 0*2; //Setting CounterEnable bits 0 and 1 to zero to disabled
//Counters 0 and 1
}
else
{
numTimers = 2; //Setting NumberTimersEnabled byte to 2 to indicate we are enabling
//2 timers (Timers 0 and 1)
counterEnable = 0 + 1*2; //Setting CounterEnable bit 1 to enable Counter 1
}
sendBuff[1] = (uint8)(0xF8); //Command byte
sendBuff[2] = (uint8)(0x05); //Number of data words
sendBuff[3] = (uint8)(0x0B); //Extended command number
sendBuff[6] = 1; //Writemask : Setting writemask for timerCounterConfig (bit 0)
sendBuff[7] = numTimers; //NumberTimersEnabled
sendBuff[8] = counterEnable; //CounterEnable: Bit 0 is Counter 0, Bit 1 is Counter 1
sendBuff[9] = 1; //TimerCounterPinOffset: Setting to 1 so Timer/Counters start on FIO1
for( i = 10; i < 16; i++ )
sendBuff[i] = 0; //Reserved
extendedChecksum(sendBuff, 16);
//Sending command to U6
if( (sendChars = LJUSB_Write(hDevice, sendBuff, 16)) < 16 )
{
if(sendChars == 0)
printf("ConfigIO error : write failed\n");
else
printf("ConfigIO error : did not write all of the buffer\n");
return -1;
}
//Reading response from U6
if( (recChars = LJUSB_Read(hDevice, recBuff, 16)) < 16 )
{
if(recChars == 0)
printf("ConfigIO error : read failed\n");
else
printf("ConfigIO error : did not read all of the buffer\n");
return -1;
}
checksumTotal = extendedChecksum16(recBuff, 16);
if( (uint8)((checksumTotal / 256 ) & 0xff) != recBuff[5] )
{
printf("ConfigIO error : read buffer has bad checksum16(MSB)\n");
return -1;
}
if( (uint8)(checksumTotal & 0xff) != recBuff[4] )
{
printf("ConfigIO error : read buffer has bad checksum16(LBS)\n");
return -1;
}
if( extendedChecksum8(recBuff) != recBuff[0] )
{
printf("ConfigIO error : read buffer has bad checksum8\n");
return -1;
}
if( recBuff[1] != (uint8)(0xF8) || recBuff[2] != (uint8)(0x05) || recBuff[3] != (uint8)(0x0B) )
{
printf("ConfigIO error : read buffer has wrong command bytes\n");
return -1;
}
if( recBuff[6] != 0 )
{
printf("ConfigIO error : read buffer received errorcode %d\n", recBuff[6]);
return -1;
}
return 0;
}
//Sends a ConfigTimerClock low-level command that configures the timer clock
//for this example
int configTimerClock_example(HANDLE hDevice)
{
uint8 sendBuff[10], recBuff[10];
uint16 checksumTotal;
int sendChars, recChars;
sendBuff[1] = (uint8)(0xF8); //Command byte
sendBuff[2] = (uint8)(0x02); //Number of data words
sendBuff[3] = (uint8)(0x0A); //Extended command number
sendBuff[6] = 0; //Reserved
sendBuff[7] = 0; //Reserved
sendBuff[8] = 6 + 1*128; //TimerClockConfig : Configuring the clock (bit 7) and
//setting the TimerClockBase (bits 0-2) to
//48MHz/TimerClockDivisor
sendBuff[9] = 2; //TimerClockDivisor : Setting to 2, so the actual timer
//clock is 24 MHz
extendedChecksum(sendBuff, 10);
//Sending command to U6
if( (sendChars = LJUSB_Write(hDevice, sendBuff, 10)) < 10 )
{
if(sendChars == 0)
printf("ConfigTimerClock error : write failed\n");
else
printf("ConfigTimerClock error : did not write all of the buffer\n");
return -1;
}
//Reading response from U6
if( (recChars = LJUSB_Read(hDevice, recBuff, 10)) < 10 )
{
if( recChars == 0 )
printf("ConfigTimerClock error : read failed\n");
else
printf("ConfigTimerClock error : did not read all of the buffer\n");
return -1;
}
checksumTotal = extendedChecksum16(recBuff, 10);
if( (uint8)((checksumTotal / 256 ) & 0xff) != recBuff[5] )
{
printf("ConfigTimerClock error : read buffer has bad checksum16(MSB)\n");
return -1;
}
if( (uint8)(checksumTotal & 0xff) != recBuff[4] )
{
printf("ConfigTimerClock error : read buffer has bad checksum16(LBS)\n");
return -1;
}
if( extendedChecksum8(recBuff) != recBuff[0] )
{
printf("ConfigTimerClock error : read buffer has bad checksum8\n");
return -1;
}
if( recBuff[1] != (uint8)(0xF8) || recBuff[2] != (uint8)(0x02) || recBuff[3] != (uint8)(0x0A) )
{
printf("ConfigTimerClock error : read buffer has wrong command bytes\n");
return -1;
}
if( recBuff[6] != 0 )
{
printf("ConfigTimerClock error : read buffer received errorcode %d\n", recBuff[6]);
return -1;
}
return 0;
}
//Sends a Feedback low-level command that configures digital directions,
//states, timer modes and DAC0 for this example.
int feedback_setup_example(HANDLE hDevice, u6CalibrationInfo *caliInfo)
{
uint8 sendBuff[28], recBuff[18];
int sendChars, recChars;
uint16 binVoltage16, checksumTotal;
sendBuff[1] = (uint8)(0xF8); //Command byte
sendBuff[2] = 11; //Number of data words (.5 word for echo, 10.5
//words for IOTypes and data)
sendBuff[3] = (uint8)(0x00); //Extended command number
sendBuff[6] = 0; //Echo
sendBuff[7] = 13; //IOType is BitDirWrite
sendBuff[8] = 0 + 128*0; //IONumber (bits 0 - 4) is 0 (FIO0) and Direction (bit 7) is
//input
sendBuff[9] = 43; //IOType is Timer0Config
sendBuff[10] = 0; //TimerMode is 16 bit PWM output (mode 0)
sendBuff[11] = 0; //Value LSB
sendBuff[12] = 0; //Value MSB, Whole value is 32768
sendBuff[13] = 42; //IOType is Timer0
sendBuff[14] = 1; //UpdateReset
sendBuff[15] = 0; //Value LSB
sendBuff[16] = 128; //Value MSB, Whole Value is 32768
sendBuff[17] = 45; //IOType is Timer1Config
sendBuff[18] = 1; //TimerMode is 8 bit PWM output (mode 1)
sendBuff[19] = 0; //Value LSB
sendBuff[20] = 0; //Value MSB, Whole value is 32768
sendBuff[21] = 44; //IOType is Timer1
sendBuff[22] = 1; //UpdateReset
sendBuff[23] = 0; //Value LSB
sendBuff[24] = 128; //Value MSB, Whole Value is 32768
sendBuff[25] = 38; //IOType is DAC0 (16-bit)
//Value is 3.5 volts (in binary form)
getDacBinVoltCalibrated16Bit(caliInfo, 0, 3.5, &binVoltage16);
sendBuff[26] = (uint8)(binVoltage16&255); //Value LSB
sendBuff[27] = (uint8)((binVoltage16&65280)/256); //Value MSB
extendedChecksum(sendBuff, 28);
//Sending command to U6
if( (sendChars = LJUSB_Write(hDevice, sendBuff, 28)) < 28 )
{
if( sendChars == 0 )
printf("Feedback setup error : write failed\n");
else
printf("Feedback setup error : did not write all of the buffer\n");
return -1;
}
//Reading response from U6
if( (recChars = LJUSB_Read(hDevice, recBuff, 18)) < 18 )
{
if( recChars == 0 )
{
printf("Feedback setup error : read failed\n");
return -1;
}
else
printf("Feedback setup error : did not read all of the buffer\n");
}
checksumTotal = extendedChecksum16(recBuff, 18);
if( (uint8)((checksumTotal / 256 ) & 0xff) != recBuff[5] )
{
printf("Feedback setup error : read buffer has bad checksum16(MSB)\n");
return -1;
}
if( (uint8)(checksumTotal & 0xff) != recBuff[4] )
{
printf("Feedback setup error : read buffer has bad checksum16(LBS)\n");
return -1;
}
if( extendedChecksum8(recBuff) != recBuff[0] )
{
printf("Feedback setup error : read buffer has bad checksum8\n");
return -1;
}
if( recBuff[1] != (uint8)(0xF8) || recBuff[2] != 6 || recBuff[3] != (uint8)(0x00) )
{
printf("Feedback setup error : read buffer has wrong command bytes \n");
return -1;
}
if( recBuff[6] != 0 )
{
printf("Feedback setup error : received errorcode %d for frame %d in Feedback response. \n", recBuff[6], recBuff[7]);
return -1;
}
return 0;
}
//Calls a Feedback low-level call to read AIN0, AIN1, AIN2, AIN0 differential,
//FIO0, Counter1(FIO3) and temperature.
int feedback_loop_example(HANDLE hDevice, u6CalibrationInfo *caliInfo)
{
long count;
uint8 sendBuff[28], recBuff[26];
int sendChars, recChars;
uint16 checksumTotal;
double voltage, temperature;
sendBuff[1] = (uint8)(0xF8); //Command byte
sendBuff[2] = 11; //Number of data words (.5 word for echo, 10.5
//words for IOTypes)
sendBuff[3] = (uint8)(0x00); //Extended command number
sendBuff[6] = 0; //Echo
sendBuff[7] = 2; //IOType is AIN24
sendBuff[8] = 0; //Positive channel
sendBuff[9] = 8 + 0*16; //ResolutionIndex(Bits 0-3) = 8,
//GainIndex(Bits 4-7) = 0 (+-10V)
sendBuff[10] = 0 + 0*128; //SettlingFactor(Bits 0-2) = 0 (5 microseconds),
// Differential(Bit 7) = 0
sendBuff[11] = 2; //IOType is AIN24
sendBuff[12] = 1; //Positive channel
sendBuff[13] = 8 + 0*16; //ResolutionIndex(Bits 0-3) = 8,
//GainIndex(Bits 4-7) = 0 (+-10V)
sendBuff[14] = 0 + 0*128; //SettlingFactor(Bits 0-2) = 0 (5 microseconds),
//Differential(Bit 7) = 0
sendBuff[15] = 2; //IOType is AIN24
sendBuff[16] = 0; //Positive channel
sendBuff[17] = 8 + 0*16; //ResolutionIndex(Bits 0-3) = 8,
//GainIndex(Bits 4-7) = 0 (+-10V)
sendBuff[18] = 0 + 1*128; //SettlingFactor(Bits 0-2) = 0 (5 microseconds),
//Differential(Bit 7) = 1
sendBuff[19] = 10; //IOType is BitStateRead
sendBuff[20] = 0; //IO number is 0 (FIO0)
sendBuff[21] = 55; //IOType is Counter1
sendBuff[22] = 0; //Reset (bit 0) is not set
sendBuff[23] = 2; //IOType is AIN24
sendBuff[24] = 14; //Positive channel = 14 (temperature sensor)
sendBuff[25] = 8 + 0*16; //ResolutionIndex(Bits 0-3) = 8,
//GainIndex(Bits 4-7) = 0 (+-10V)
sendBuff[26] = 0 + 0*128; //SettlingFactor(Bits 0-2) = 0 (5 microseconds), Differential(Bit 7) = 0
sendBuff[27] = 0; //Padding byte
extendedChecksum(sendBuff, 28);
printf("Running Feedback calls in a loop\n");
count = 0;
while( !kbhit() )
{
count++;
printf("Iteration %ld\n", count);
//Sending command to U6
if( (sendChars = LJUSB_Write(hDevice, sendBuff, 28)) < 28 )
{
if(sendChars == 0)
printf("Feedback loop error : write failed\n");
else
printf("Feedback loop error : did not write all of the buffer\n");
return -1;
}
//Reading response from U6
if( (recChars = LJUSB_Read(hDevice, recBuff, 26)) < 26 )
{
if( recChars == 0 )
{
printf("Feedback loop error : read failed\n");
return -1;
}
else
printf("Feedback loop error : did not read all of the expected buffer\n");
}
if( recChars < 10 )
{
printf("Feedback loop error : response is not large enough\n");
return -1;
}
checksumTotal = extendedChecksum16(recBuff, recChars);
if( (uint8)((checksumTotal / 256 ) & 0xff) != recBuff[5] )
{
printf("Feedback loop error : read buffer has bad checksum16(MSB)\n");
return -1;
}
if( (uint8)(checksumTotal & 0xff) != recBuff[4] )
{
printf("Feedback loop error : read buffer has bad checksum16(LBS)\n");
return -1;
}
if( extendedChecksum8(recBuff) != recBuff[0] )
{
printf("Feedback loop error : read buffer has bad checksum8\n");
return -1;
}
if( recBuff[1] != (uint8)(0xF8) || recBuff[3] != (uint8)(0x00) )
{
printf("Feedback loop error : read buffer has wrong command bytes \n");
return -1;
}
if( recBuff[6] != 0 )
{
printf("Feedback loop error : received errorcode %d for frame %d ", recBuff[6], recBuff[7]);
switch( recBuff[7] )
{
case 1: printf("(AIN0(SE))\n"); break;
case 2: printf("(AIN1(SE))\n"); break;
case 3: printf("(AIN0(Diff))\n"); break;
case 4: printf("(BitStateRead for FIO7)\n"); break;
case 5: printf("(Counter1)\n"); break;
case 6: printf("(Temp. Sensor\n"); break;
default: printf("(Unknown)\n"); break;
}
return -1;
}
getAinVoltCalibrated(caliInfo, 8, 0, 1, recBuff[9] + recBuff[10]*256 + recBuff[11]*65536, &voltage);
printf("AIN0(SE) : %.3f volts\n", voltage);
getAinVoltCalibrated(caliInfo, 8, 0, 1, recBuff[12] + recBuff[13]*256 + recBuff[14]*65536, &voltage);
printf("AIN1(SE) : %.3f volts\n", voltage);
getAinVoltCalibrated(caliInfo, 8, 0, 1, recBuff[15] + recBuff[16]*256 + recBuff[17]*65536, &voltage);
printf("AIN0(Diff) : %.3f volts\n", voltage);
printf("FIO0 state : %d\n", recBuff[18]);
printf("Counter1(FIO3) : %u\n\n", recBuff[19] + recBuff[20]*256 + recBuff[21]*65536 + recBuff[22]*16777216);
getTempKCalibrated(caliInfo, 8, 0, 1, recBuff[23] + recBuff[24]*256 + recBuff[25]*65536, &temperature);
printf("Temperature : %.3f K\n\n", temperature);
sleep(1);
}
return 0;
}
void setTerm()
{
tcgetattr(0, &termOrig);
termNew = termOrig;
termNew.c_lflag &= ~ICANON;
termNew.c_lflag &= ~ECHO;
termNew.c_lflag &= ~ISIG;
termNew.c_cc[VMIN] = 1;
termNew.c_cc[VTIME] = 0;
tcsetattr(0, TCSANOW, &termNew);
}
int kbhit()
{
char ch;
int nread;
if( peek != -1 )
return 1;
termNew.c_cc[VMIN]=0;
tcsetattr(0, TCSANOW, &termNew);
nread = read(0,&ch,1);
termNew.c_cc[VMIN]=1;
tcsetattr(0, TCSANOW, &termNew);
if( nread == 1 )
{
peek = ch;
return 1;
}
return 0;
}
void unsetTerm()
{
tcsetattr(0, TCSANOW, &termOrig);
}

View File

@@ -0,0 +1,306 @@
//Author: LabJack
//April 5, 2011
//Communicates with an LJTick-DAC using low level functions. The LJTDAC should
//be plugged into FIO2/FIO3 for this example.
#include "u6.h"
#include <unistd.h>
int configIO_example(HANDLE hDevice);
int checkI2CErrorcode(uint8 errorcode);
int tdac_example(HANDLE hDevice, u6TdacCalibrationInfo *caliInfo);
int main(int argc, char **argv)
{
HANDLE hDevice;
u6TdacCalibrationInfo caliInfo;
//Opening first found U6 over USB
if( (hDevice = openUSBConnection(-1)) == NULL )
goto done;
if( configIO_example(hDevice) != 0 )
goto close;
//Getting calibration information from LJTDAC
if( getTdacCalibrationInfo(hDevice, &caliInfo, 2) < 0 )
goto close;
tdac_example(hDevice, &caliInfo);
close:
closeUSBConnection(hDevice);
done:
return 0;
}
//Sends a ConfigIO low-level command to turn off timers/counters
int configIO_example(HANDLE hDevice)
{
uint8 sendBuff[16], recBuff[16];
uint16 checksumTotal;
int sendChars, recChars, i;
sendBuff[1] = (uint8)(0xF8); //Command byte
sendBuff[2] = (uint8)(0x03); //Number of data words
sendBuff[3] = (uint8)(0x0B); //Extended command number
sendBuff[6] = 1; //Writemask : Setting writemask for TimerCounterConfig (bit 0)
sendBuff[7] = 0; //NumberTimersEnabled : Setting to zero to disable all timers.
sendBuff[8] = 0; //CounterEnable: Setting bit 0 and bit 1 to zero to disable both counters
sendBuff[9] = 0; //TimerCounterPinOffset
for( i = 10; i < 16; i++ )
sendBuff[i] = 0; //Reserved
extendedChecksum(sendBuff, 16);
//Sending command to U6
if( (sendChars = LJUSB_Write(hDevice, sendBuff, 16)) < 16 )
{
if( sendChars == 0 )
printf("ConfigIO error : write failed\n");
else
printf("ConfigIO error : did not write all of the buffer\n");
return -1;
}
//Reading response from U6
if( (recChars = LJUSB_Read(hDevice, recBuff, 16)) < 16 )
{
if( recChars == 0 )
printf("ConfigIO error : read failed\n");
else
printf("ConfigIO error : did not read all of the buffer\n");
return -1;
}
checksumTotal = extendedChecksum16(recBuff, 15);
if( (uint8)((checksumTotal / 256 ) & 0xff) != recBuff[5] )
{
printf("ConfigIO error : read buffer has bad checksum16(MSB)\n");
return -1;
}
if( (uint8)(checksumTotal & 0xff) != recBuff[4] )
{
printf("ConfigIO error : read buffer has bad checksum16(LBS)\n");
return -1;
}
if( extendedChecksum8(recBuff) != recBuff[0] )
{
printf("ConfigIO error : read buffer has bad checksum8\n");
return -1;
}
if( recBuff[1] != (uint8)(0xF8) || recBuff[2] != (uint8)(0x05) || recBuff[3] != (uint8)(0x0B) )
{
printf("ConfigIO error : read buffer has wrong command bytes\n");
return -1;
}
if( recBuff[6] != 0 )
{
printf("ConfigIO error : read buffer received errorcode %d\n", recBuff[6]);
return -1;
}
if( recBuff[8] != 0 )
{
printf("ConfigIO error : NumberTimersEnabled was not set to 0\n");
return -1;
}
if( recBuff[9] != 0 )
{
printf("ConfigIO error : CounterEnable was not set to 0\n");
return -1;
}
return 0;
}
int checkI2CErrorcode(uint8 errorcode)
{
if( errorcode != 0 )
{
printf("I2C error : received errorcode %d in response\n", errorcode);
return -1;
}
return 0;
}
int tdac_example(HANDLE hDevice, u6TdacCalibrationInfo *caliInfo)
{
int err;
uint8 options, speedAdjust, sdaPinNum, sclPinNum, address, numBytesToSend, numBytesToReceive, errorcode;
uint16 binaryVoltage;
uint8 bytesCommand[5];
uint8 bytesResponse[64];
uint8 ackArray[4];
int i;
err = 0;
//Setting up parts I2C command that will remain the same throughout this example
options = 0; //I2COptions : 0
speedAdjust = 0; //SpeedAdjust : 0 (for max communication speed of about 130 kHz)
sdaPinNum = 3; //SDAPinNum : FIO3 connected to pin DIOB
sclPinNum = 2; //SCLPinNum : FIO2 connected to pin DIOA
/* Set DACA to 1.2 volts. */
//Setting up I2C command
//Make note that the I2C command can only update 1 DAC channel at a time.
address = (uint8)(0x24); //Address : h0x24 is the address for DAC
numBytesToSend = 3; //NumI2CByteToSend : 3 bytes to specify DACA and the value
numBytesToReceive = 0; //NumI2CBytesToReceive : 0 since we are only setting the value of the DAC
bytesCommand[0] = (uint8)(0x30); //LJTDAC command byte : h0x30 (DACA)
getTdacBinVoltCalibrated(caliInfo, 0, 1.2, &binaryVoltage);
bytesCommand[1] = (uint8)(binaryVoltage/256); //value (high)
bytesCommand[2] = (uint8)(binaryVoltage & (0x00FF)); //value (low)
//Performing I2C low-level call
err = I2C(hDevice, options, speedAdjust, sdaPinNum, sclPinNum, address, numBytesToSend, numBytesToReceive, bytesCommand, &errorcode, ackArray, bytesResponse);
if( checkI2CErrorcode(errorcode) == -1 || err == -1 )
return -1;
printf("DACA set to 1.2 volts\n\n");
/* Set DACB to 2.3 volts. */
//Setting up I2C command
address = (uint8)(0x24); //Address : h0x24 is the address for DAC
numBytesToSend = 3; //NumI2CByteToSend : 3 bytes to specify DACB and the value
numBytesToReceive = 0; //NumI2CBytesToReceive : 0 since we are only setting the value of the DAC
bytesCommand[0] = (uint8)(0x31); //LJTDAC command byte : h0x31 (DACB)
getTdacBinVoltCalibrated(caliInfo, 1, 2.3, &binaryVoltage);
bytesCommand[1] = (uint8)(binaryVoltage/256); //value (high)
bytesCommand[2] = (uint8)(binaryVoltage & (0x00FF)); //value (low)
//Performing I2C low-level call
err = I2C(hDevice, options, speedAdjust, sdaPinNum, sclPinNum, address, numBytesToSend, numBytesToReceive, bytesCommand, &errorcode, ackArray, bytesResponse);
if( checkI2CErrorcode(errorcode) == -1 || err == -1 )
return -1;
printf("DACB set to 2.3 volts\n\n");
/* More advanced operations. */
/* Display LJTDAC calibration constants. Code for getting the calibration constants is in the
* getLJTDACCalibrationInfo function in the u6.c file. */
printf("DACA Slope = %.1f bits/volt\n", caliInfo->ccConstants[0]);
printf("DACA Offset = %.1f bits\n", caliInfo->ccConstants[1]);
printf("DACB Slope = %.1f bits/volt\n", caliInfo->ccConstants[2]);
printf("DACB Offset = %.1f bits\n\n", caliInfo->ccConstants[3]);
/* Read the serial number. */
//Setting up I2C command
address = (uint8)(0xA0); //Address : h0xA0 is the address for EEPROM
numBytesToSend = 1; //NumI2CByteToSend : 1 byte for the EEPROM address
numBytesToReceive = 4; //NumI2CBytesToReceive : getting 4 bytes starting at EEPROM address specified in I2CByte0
bytesCommand[0] = 96; //I2CByte0 : Memory Address (starting at address 96 (Serial Number)
//Performing I2C low-level call
err = I2C(hDevice, options, speedAdjust, sdaPinNum, sclPinNum, address, numBytesToSend, numBytesToReceive, bytesCommand, &errorcode, ackArray, bytesResponse);
if( checkI2CErrorcode(errorcode) == -1 || err == -1 )
return -1;
printf("LJTDAC Serial Number = %u\n\n", (bytesResponse[0] + bytesResponse[1]*256 + bytesResponse[2]*65536 + bytesResponse[3]*16777216));
/* User memory example. We will read the memory, update a few elements,
* and write the memory. The user memory is just stored as bytes, so almost
* any information can be put in there such as integers, doubles, or strings. */
/* Read the user memory : need to perform 2 I2C calls since command/response packets can only be 64 bytes in size */
//Setting up 1st I2C command
address = (uint8)(0xA0); //Address : h0xA0 is the address for EEPROM
numBytesToSend = 1; //NumI2CByteToSend : 1 byte for the EEPROM address
numBytesToReceive = 52; //NumI2CBytesToReceive : getting 52 bytes starting at EEPROM address specified in I2CByte0
bytesCommand[0] = 0; //I2CByte0 : Memory Address, starting at address 0 (User Area)
//Performing I2C low-level call
err = I2C(hDevice, options, speedAdjust, sdaPinNum, sclPinNum, address, numBytesToSend, numBytesToReceive, bytesCommand, &errorcode, ackArray, bytesResponse);
if( checkI2CErrorcode(errorcode) == -1 || err == -1 )
return -1;
//Setting up 2nd I2C command
numBytesToReceive = 12; //NumI2CBytesToReceive : getting 12 bytes starting at EEPROM address specified in I2CByte0
bytesCommand[0] = 52; //I2CByte0 : Memory Address, starting at address 52 (User Area)
//Performing I2C low-level call
err = I2C(hDevice, options, speedAdjust, sdaPinNum, sclPinNum, address, numBytesToSend, numBytesToReceive, bytesCommand, &errorcode, ackArray, bytesResponse + 52);
if( checkI2CErrorcode(errorcode) == -1 || err == -1 )
return -1;
//Display the first 4 elements.
printf("Read User Mem [0-3] = %d, %d, %d, %d\n", bytesResponse[0], bytesResponse[1], bytesResponse[2], bytesResponse[3]);
/* Create 4 new pseudo-random numbers to write. We will update the first
* 4 elements of user memory, but the rest will be unchanged. */
//Setting up I2C command
address = (uint8)(0xA0); //Address : h0xA0 is the address for EEPROM
numBytesToSend = 5; //NumI2CByteToSend : 1 byte for the EEPROM address and the rest for the bytes to write
numBytesToReceive = 0; //NumI2CBytesToReceive : 0 since we are only writing to memory
bytesCommand[0] = 0; //I2CByte0 : Memory Address, starting at address 0 (User Area)
srand((unsigned int)getTickCount());
for( i = 1; i < 5; i++ )
bytesCommand[i] = (uint8)(255*((float)rand()/RAND_MAX));; //I2CByte : byte in user memory
printf("Write User Mem [0-3] = %d, %d, %d, %d\n", bytesCommand[1], bytesCommand[2], bytesCommand[3], bytesCommand[4]);
//Performing I2C low-level call
err = I2C(hDevice, options, speedAdjust, sdaPinNum, sclPinNum, address, numBytesToSend, numBytesToReceive, bytesCommand, &errorcode, ackArray, bytesResponse);
if( checkI2CErrorcode(errorcode) == -1 || err == -1 )
return -1;
//Delay for 2 ms to allow the EEPROM to finish writing.
//Re-read the user memory.
usleep(2000);
//Setting up 1st I2C command
address = (uint8)(0xA0); //Address : h0xA0 is the address for EEPROM
numBytesToSend = 1; //NumI2CByteToSend : 1 byte for the EEPROM address
numBytesToReceive = 52; //NumI2CBytesToReceive : getting 52 bytes starting at EEPROM address specified in I2CByte0
bytesCommand[0] = 0; //I2CByte0 : Memory Address, starting at address 0 (User Area)
//Performing I2C low-level call
err = I2C(hDevice, options, speedAdjust, sdaPinNum, sclPinNum, address, numBytesToSend, numBytesToReceive, bytesCommand, &errorcode, ackArray, bytesResponse);
if( checkI2CErrorcode(errorcode) == -1 || err == -1 )
return -1;
//Setting up 2nd I2C command
numBytesToReceive = 12; //NumI2CBytesToReceive : getting 12 bytes starting at EEPROM address specified in I2CByte0
bytesCommand[0] = 52; //I2CByte0 : Memory Address, starting at address 52 (User Area)
//Performing I2C low-level call
err = I2C(hDevice, options, speedAdjust, sdaPinNum, sclPinNum, address, numBytesToSend, numBytesToReceive, bytesCommand, &errorcode, ackArray, bytesResponse + 52);
if( checkI2CErrorcode(errorcode) == -1 || err == -1 )
return -1;
//Display the first 4 elements.
printf("Read User Mem [0-3] = %d, %d, %d, %d\n", bytesResponse[0], bytesResponse[1], bytesResponse[2], bytesResponse[3]);
return err;
}

View File

@@ -0,0 +1,510 @@
//Author: LabJack
//April 5, 2011
//This example program reads analog inputs AI0-AI4 using stream mode.
#include "u6.h"
int ConfigIO_example(HANDLE hDevice);
int StreamConfig_example(HANDLE hDevice);
int StreamStart(HANDLE hDevice);
int StreamData_example(HANDLE hDevice, u6CalibrationInfo *caliInfo);
int StreamStop(HANDLE hDevice);
const uint8 NumChannels = 5; //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;
u6CalibrationInfo caliInfo;
//Opening first found U6 over USB
if( (hDevice = openUSBConnection(-1)) == NULL )
goto done;
//Getting calibration information from U6
if( getCalibrationInfo(hDevice, &caliInfo) < 0 )
goto close;
if( ConfigIO_example(hDevice) != 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);
StreamStop(hDevice);
close:
closeUSBConnection(hDevice);
done:
return 0;
}
//Sends a ConfigIO low-level command to turn off timers/counters
int ConfigIO_example(HANDLE hDevice)
{
uint8 sendBuff[16], recBuff[16];
uint16 checksumTotal;
int sendChars, recChars, i;
sendBuff[1] = (uint8)(0xF8); //Command byte
sendBuff[2] = (uint8)(0x03); //Number of data words
sendBuff[3] = (uint8)(0x0B); //Extended command number
sendBuff[6] = 1; //Writemask : Setting writemask for TimerCounterConfig (bit 0)
sendBuff[7] = 0; //NumberTimersEnabled : Setting to zero to disable all timers.
sendBuff[8] = 0; //CounterEnable: Setting bit 0 and bit 1 to zero to disable both counters
sendBuff[9] = 0; //TimerCounterPinOffset
for( i = 10; i < 16; i++ )
sendBuff[i] = 0; //Reserved
extendedChecksum(sendBuff, 16);
//Sending command to U6
if( (sendChars = LJUSB_Write(hDevice, sendBuff, 16)) < 16 )
{
if( sendChars == 0 )
printf("ConfigIO error : write failed\n");
else
printf("ConfigIO error : did not write all of the buffer\n");
return -1;
}
//Reading response from U6
if( (recChars = LJUSB_Read(hDevice, recBuff, 16)) < 16 )
{
if( recChars == 0 )
printf("ConfigIO error : read failed\n");
else
printf("ConfigIO error : did not read all of the buffer\n");
return -1;
}
checksumTotal = extendedChecksum16(recBuff, 15);
if( (uint8)((checksumTotal / 256 ) & 0xff) != recBuff[5] )
{
printf("ConfigIO error : read buffer has bad checksum16(MSB)\n");
return -1;
}
if( (uint8)(checksumTotal & 0xff) != recBuff[4] )
{
printf("ConfigIO error : read buffer has bad checksum16(LSB)\n");
return -1;
}
if( extendedChecksum8(recBuff) != recBuff[0] )
{
printf("ConfigIO error : read buffer has bad checksum8\n");
return -1;
}
if( recBuff[1] != (uint8)(0xF8) || recBuff[2] != (uint8)(0x05) || recBuff[3] != (uint8)(0x0B) )
{
printf("ConfigIO error : read buffer has wrong command bytes\n");
return -1;
}
if( recBuff[6] != 0 )
{
printf("ConfigIO error : read buffer received errorcode %d\n", recBuff[6]);
return -1;
}
if( recBuff[8] != 0 )
{
printf("ConfigIO error : NumberTimersEnabled was not set to 0\n");
return -1;
}
if( recBuff[9] != 0 )
{
printf("ConfigIO error : CounterEnable was not set to 0\n");
return -1;
}
return 0;
}
//Sends a StreamConfig low-level command to configure the stream.
int StreamConfig_example(HANDLE hDevice)
{
int sendBuffSize;
sendBuffSize = 14+NumChannels*2;
uint8 sendBuff[sendBuffSize], recBuff[8];
int sendChars, recChars;
uint16 checksumTotal;
uint16 scanInterval;
int i;
sendBuff[1] = (uint8)(0xF8); //Command byte
sendBuff[2] = 4 + NumChannels; //Number of data words = NumChannels + 4
sendBuff[3] = (uint8)(0x11); //Extended command number
sendBuff[6] = NumChannels; //NumChannels
sendBuff[7] = 1; //ResolutionIndex
sendBuff[8] = SamplesPerPacket; //SamplesPerPacket
sendBuff[9] = 0; //Reserved
sendBuff[10] = 0; //SettlingFactor: 0
sendBuff[11] = 0; //ScanConfig:
// Bit 3: Internal stream clock frequency = b0: 4 MHz
// Bit 1: Divide Clock by 256 = b0
scanInterval = 4000;
sendBuff[12] = (uint8)(scanInterval&(0x00FF)); //scan interval (low byte)
sendBuff[13] = (uint8)(scanInterval/256); //scan interval (high byte)
for( i = 0; i < NumChannels; i++ )
{
sendBuff[14 + i*2] = i; //ChannelNumber (Positive) = i
sendBuff[15 + i*2] = 0; //ChannelOptions:
// Bit 7: Differential = 0
// Bit 5-4: GainIndex = 0 (+-10V)
}
extendedChecksum(sendBuff, sendBuffSize);
//Sending command to U6
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;
}
for( i = 0; i < 8; i++ )
recBuff[i] = 0;
//Reading response from U6
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, %d (StreamConfig).\n", recChars);
for( i = 0; i < 8; i++)
printf("%d ", recBuff[i]);
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) || recBuff[7] != (uint8)(0x00) )
{
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 U6
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 U6
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, u6CalibrationInfo *caliInfo)
{
int recBuffSize;
recBuffSize = 14 + SamplesPerPacket*2;
int recChars, backLog;
int i, j, k, m, packetCounter, currChannel, scanNumber;
int totalPackets; //The total number of StreamData responses read
uint16 voltageBytes, checksumTotal;
long startTime, endTime;
int autoRecoveryOn;
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 = 6;
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;
printf("Reading Samples...\n");
startTime = getTickCount();
for( i = 0; i < numDisplay; i++ )
{
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 U6
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 >> 8) & 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(LSB) (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("\nU6 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;
getAinVoltCalibrated(caliInfo, 1, 0, 0, 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]);
}
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;
}
//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 U6
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 U6
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) || recBuff[3] != (uint8)(0x00) )
{
printf("Error : read buffer has wrong command bytes (StreamStop).\n");
return -1;
}
if( recBuff[2] != 0 )
{
printf("Errorcode # %d from StreamStop read.\n", (unsigned int)recBuff[2]);
return -1;
}
/*
//Reading left over data in stream endpoint. Only needs to be done with firmwares
//less than 0.94.
uint8 recBuffS[64];
int recCharsS = 64;
printf("Reading left over data from stream endpoint.\n");
while( recCharsS > 0 )
recCharsS = LJUSB_Stream(hDevice, recBuffS, 64);
*/
return 0;
}

View File

@@ -0,0 +1,273 @@
//Author : LabJack
//April 5, 2011
//This example demonstrates how to write and read some or all analog I/O.
//By default, it records the time for 1000 iterations and divides by 1000,
//to allow measurement of the basic command/response communication times. These
//times should be comparable to the Windows command/response communication
//times documented in Section 3.1 of the U6 User's Guide.
#include <stdlib.h>
#include "u6.h"
const int numIterations = 1000; //Number of Feedback calls that will be performed. Default 1000.
const uint8 numChannels = 8; //Number of AIN channels, 0-14. Default 8.
const uint8 settlingFactor = 0; //0=5us, 1=10us, 2=100us, 3=1ms, 4=10ms. Default 0.
const uint8 gainIndex = 0; //0 = +-10V, 1 = +-1V, 2 = +-100mV, 3 = +-10mV, 15=autorange. Default 0.
const uint8 resolution = 1; //1=default, 1-8 for high-speed ADC, 9-13 for high-res ADC on U6-Pro. Default 1.
const uint8 differential = 0; //Indicates whether to do differential readings. Default 0 (false).
int allIO(HANDLE hDevice, u6CalibrationInfo *caliInfo);
int main(int argc, char **argv)
{
HANDLE hDevice;
u6CalibrationInfo caliInfo;
//Opening first found U6 over USB
if( (hDevice = openUSBConnection(-1)) == NULL )
goto done;
//Getting calibration information from U6
if( getCalibrationInfo(hDevice, &caliInfo) < 0 )
goto close;
allIO(hDevice, &caliInfo);
close:
closeUSBConnection(hDevice);
done:
return 0;
}
//Calls the Feedback low-level command numIterations times and calculates the
//time per iteration.
int allIO(HANDLE hDevice, u6CalibrationInfo *caliInfo)
{
uint8 *sendBuff, *recBuff;
uint16 checksumTotal, bits16;
uint32 bits32;
int sendChars, recChars, i, j, sendSize, recSize;
double valueAIN[14];
long time;
int ret = 0;
for( i = 0; i < 14; i++ )
valueAIN[i] = 9999;
//Setting up a Feedback command that will set CIO0-3 as input, and
//set DAC0 voltage
sendBuff = (uint8 *)malloc(18*sizeof(uint8)); //Creating an array of size 18
recBuff = (uint8 *)malloc(10*sizeof(uint8)); //Creating an array of size 10
sendBuff[1] = (uint8)(0xF8); //Command byte
sendBuff[2] = 6; //Number of data words (.5 word for echo, 5.5
//words for IOTypes and data)
sendBuff[3] = (uint8)(0x00); //Extended command number
sendBuff[6] = 0; //Echo
sendBuff[7] = 29; //IOType is PortDirWrite
sendBuff[8] = 0; //Writemask (for FIO)
sendBuff[9] = 0; //Writemask (for EIO)
sendBuff[10] = 15; //Writemask (for CIO)
sendBuff[11] = 0; //Direction (for FIO)
sendBuff[12] = 0; //Direction (for EIO)
sendBuff[13] = 0; //Direction (for CIO)
//Setting DAC0 with 2.5 volt output
sendBuff[14] = 38; //IOType is DAC0(16-bit)
//Value is 2.5 volts (in binary)
getDacBinVoltCalibrated16Bit(caliInfo, 0, 2.5, &bits16);
sendBuff[15] = (uint8)(bits16&255);
sendBuff[16] = (uint8)(bits16/256);
sendBuff[17] = 0; //extra padding byte
extendedChecksum(sendBuff, 18);
//Sending command to U6
if( (sendChars = LJUSB_Write(hDevice, sendBuff, 18)) < 18 )
{
if(sendChars == 0)
printf("Feedback (CIO input) error : write failed\n");
else
printf("Feedback (CIO input) error : did not write all of the buffer\n");
ret = -1;
goto cleanmem;
}
//Reading response from U6
if( (recChars = LJUSB_Read(hDevice, recBuff, 10)) < 10 )
{
if( recChars == 0 )
{
printf("Feedback (CIO input) error : read failed\n");
ret = -1;
goto cleanmem;
}
else
printf("Feedback (CIO input) error : did not read all of the buffer\n");
}
checksumTotal = extendedChecksum16(recBuff, 10);
if( (uint8)((checksumTotal / 256) & 0xff) != recBuff[5] )
{
printf("Feedback (CIO input) error : read buffer has bad checksum16(MSB)\n");
ret = -1;
goto cleanmem;
}
if( (uint8)(checksumTotal & 0xff) != recBuff[4] )
{
printf("Feedback (CIO input) error : read buffer has bad checksum16(LBS)\n");
ret = -1;
goto cleanmem;
}
if( extendedChecksum8(recBuff) != recBuff[0] )
{
printf("Feedback (CIO input) error : read buffer has bad checksum8\n");
ret = -1;
goto cleanmem;
}
if( recBuff[1] != (uint8)(0xF8) || recBuff[3] != (uint8)(0x00) )
{
printf("Feedback (CIO input) error : read buffer has wrong command bytes \n");
ret = -1;
goto cleanmem;
}
if( recBuff[6] != 0 )
{
printf("Feedback (CIO input) error : received errorcode %d for frame %d in Feedback response. \n", recBuff[6], recBuff[7]);
ret = -1;
goto cleanmem;
}
free(sendBuff);
free(recBuff);
//Setting up Feedback command that will run numIterations times
if( ((sendSize = 7+numChannels*4) % 2) != 0 )
sendSize++;
sendBuff = malloc(sendSize*sizeof(uint8)); //Creating an array of size sendSize
if( ((recSize = 9+numChannels*3) % 2) != 0 )
recSize++;
recBuff = malloc(recSize*sizeof(uint8)); //Creating an array of size recSize
sendBuff[1] = (uint8)(0xF8); //Command byte
sendBuff[2] = (sendSize - 6)/2; //Number of data words
sendBuff[3] = (uint8)(0x00); //Extended command number
sendBuff[6] = 0; //Echo
//Setting AIN read commands
for( j = 0; j < numChannels; j++ )
{
sendBuff[7 + j*4] = 2; //IOType is AIN24
//Positive Channel (bits 0 - 4), LongSettling (bit 6) and QuickSample (bit 7)
sendBuff[8 + j*4] = j; //Positive Channel
sendBuff[9 + j*4] = (uint8)(resolution&15) + (uint8)((gainIndex&15)*16); //ResolutionIndex(Bits 0-3), GainIndex(Bits 4-7)
sendBuff[10 + j*4] = (uint8)(settlingFactor&7); //SettlingFactor(Bits 0-2)
if( j%2 == 0 )
sendBuff[10 + j*4] += (uint8)((differential&1)*128); //Differential(Bits 7)
}
extendedChecksum(sendBuff, sendSize);
time = getTickCount();
for( i = 0; i < numIterations; i++ )
{
//Sending command to U6
if( (sendChars = LJUSB_Write(hDevice, sendBuff, sendSize)) < sendSize )
{
if(sendChars == 0)
printf("Feedback error (Iteration %d): write failed\n", i);
else
printf("Feedback error (Iteration %d): did not write all of the buffer\n", i);
ret = -1;
goto cleanmem;
}
//Reading response from U6
if( (recChars = LJUSB_Read(hDevice, recBuff, recSize)) < recSize )
{
if( recChars == 0 )
{
printf("Feedback error (Iteration %d): read failed\n", i);
ret = -1;
goto cleanmem;
}
}
checksumTotal = extendedChecksum16(recBuff, recChars);
if( (uint8)((checksumTotal / 256) & 0xff) != recBuff[5] )
{
printf("Feedback error (Iteration %d): read buffer has bad checksum16(MSB)\n", i);
ret = -1;
goto cleanmem;
}
if( (uint8)(checksumTotal & 0xff) != recBuff[4] )
{
printf("Feedback error (Iteration %d): read buffer has bad checksum16(LBS)\n", i);
ret = -1;
goto cleanmem;
}
if( extendedChecksum8(recBuff) != recBuff[0] )
{
printf("Feedback error (Iteration %d): read buffer has bad checksum8\n", i);
ret = -1;
goto cleanmem;
}
if( recBuff[1] != (uint8)(0xF8) || recBuff[3] != (uint8)(0x00) )
{
printf("Feedback error (Iteration %d): read buffer has wrong command bytes \n", i);
ret = -1;
goto cleanmem;
}
if( recBuff[6] != 0 )
{
printf("Feedback error (Iteration %d): received errorcode %d for frame %d in Feedback response. \n", i, recBuff[6], recBuff[7]);
ret = -1;
goto cleanmem;
}
if( recChars != recSize )
{
printf("Feedback error (Iteration %d): received packet if %d size when expecting %d\n", i, recChars, recSize);
ret = -1;
goto cleanmem;
}
//Getting AIN voltages
for(j = 0; j < numChannels; j++)
{
bits32 = recBuff[9+j*3] + recBuff[10+j*3]*256 + recBuff[11+j*3]*65536;
getAinVoltCalibrated(caliInfo, resolution, gainIndex, 1, bits32, &valueAIN[j]);
}
}
time = getTickCount() - time;
printf("Milliseconds per iteration = %.3f\n", (double)time / (double)numIterations);
printf("\nAIN readings from last iteration:\n");
for( j = 0; j < numChannels; j++ )
printf("%.3f\n", valueAIN[j]);
cleanmem:
free(sendBuff);
free(recBuff);
sendBuff = NULL;
recBuff = NULL;
return ret;
}

View File

@@ -0,0 +1,73 @@
#
# Makefile for UE9 examples
#
UE9SINGLEIO_SRC=ue9SingleIO.c ue9.c
UE9SINGLEIO_OBJ=$(UE9SINGLEIO_SRC:.c=.o)
UE9COMMCONFIG_SRC=ue9BasicCommConfig.c
UE9COMMCONFIG_OBJ=$(UE9COMMCONFIG_SRC:.c=.o)
UE9ETHERNET_SRC=ue9EthernetExample.c
UE9ETHERNET_OBJ=$(UE9ETHERNET_SRC:.c=.o)
UE9CONTROLCONFIG_SRC=ue9ControlConfig.c ue9.c
UE9CONTROLCONFIG_OBJ=$(UE9CONTROLCONFIG_SRC:.c=.o)
UE9FEEDBACK_SRC=ue9Feedback.c ue9.c
UE9FEEDBACK_OBJ=$(UE9FEEDBACK_SRC:.c=.o)
UE9STREAM_SRC=ue9Stream.c ue9.c
UE9STREAM_OBJ=$(UE9STREAM_SRC:.c=.o)
UE9TIMERCOUNTER_SRC=ue9TimerCounter.c ue9.c
UE9TIMERCOUNTER_OBJ=$(UE9TIMERCOUNTER_SRC:.c=.o)
UE9ALLIO_SRC=ue9allio.c ue9.c
UE9ALLIO_OBJ=$(UE9ALLIO_SRC:.c=.o)
UE9EFUNCTIONS_SRC=ue9EFunctions.c ue9.c
UE9EFUNCTIONS_OBJ=$(UE9EFUNCTIONS_SRC:.c=.o)
UE9LJTDAC_SRC=ue9LJTDAC.c ue9.c
UE9LJTDAC_OBJ=$(UE9LJTDAC_SRC:.c=.o)
SRCS=$(wildcard *.c)
HDRS=$(wildcard *.h)
CFLAGS +=-Wall -g
LIBS=-lm -llabjackusb
all: ue9BasicCommConfig ue9EthernetExample ue9SingleIO ue9ControlConfig ue9Feedback ue9Stream ue9TimerCounter ue9allio ue9EFunctions ue9LJTDAC
ue9BasicCommConfig: $(UE9COMMCONFIG_OBJ) $(HDRS)
$(CC) -o ue9BasicCommConfig $(UE9COMMCONFIG_OBJ) $(LDFLAGS) $(LIBS)
ue9EthernetExample: $(UE9ETHERNET_OBJ) $(HDRS)
$(CC) -o ue9EthernetExample $(UE9ETHERNET_OBJ) $(LDFLAGS) $(LIBS)
ue9SingleIO: $(UE9SINGLEIO_OBJ) $(HDRS)
$(CC) -o ue9SingleIO $(UE9SINGLEIO_OBJ) $(LDFLAGS) $(LIBS)
ue9ControlConfig: $(UE9CONTROLCONFIG_OBJ) $(HDRS)
$(CC) -o ue9ControlConfig $(UE9CONTROLCONFIG_OBJ) $(LDFLAGS) $(LIBS)
ue9Feedback: $(UE9FEEDBACK_OBJ) $(HDRS)
$(CC) -o ue9Feedback $(UE9FEEDBACK_OBJ) $(LDFLAGS) $(LIBS)
ue9Stream: $(UE9STREAM_OBJ) $(HDRS)
$(CC) -o ue9Stream $(UE9STREAM_OBJ) $(LDFLAGS) $(LIBS)
ue9TimerCounter: $(UE9TIMERCOUNTER_OBJ) $(HDRS)
$(CC) -o ue9TimerCounter $(UE9TIMERCOUNTER_OBJ) $(LDFLAGS) $(LIBS)
ue9allio: $(UE9ALLIO_OBJ) $(HDRS)
$(CC) -o ue9allio $(UE9ALLIO_OBJ) $(LDFLAGS) $(LIBS)
ue9EFunctions: $(UE9EFUNCTIONS_OBJ) $(HDRS)
$(CC) -o ue9EFunctions $(UE9EFUNCTIONS_OBJ) $(LDFLAGS) $(LIBS)
ue9LJTDAC: $(UE9LJTDAC_OBJ) $(HDRS)
$(CC) -o ue9LJTDAC $(UE9LJTDAC_OBJ) $(LDFLAGS) $(LIBS)
clean:
rm -f *.o *~ ue9BasicCommConfig ue9SingleIO ue9ControlConfig ue9Feedback ue9Stream ue9TimerCounter ue9allio ue9EFunctions ue9LJTDAC ue9EthernetExample

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,546 @@
//Author: LabJack
//May 25, 2011
//Header for UE9 example helper functions.
//
//History
//-Added easy functions.
//-Added I2C function and LJTDAC functions and structure. (09/04/2007)
//-Fixed memory leak issue in I2C functions. (09/27/2007)
//-Fixed a bug in ehDIO_Feedback where CIO and MIO states were only being
// set. (08/08/2008)
//-Modified calibration constants structs. Modified the names and code of the
// functions that apply the calibration constants. (06/25/2009)
//-Replaced LJUSB_BulkWrite/Read with LJUSB_write/Read calls. Added serial
// support to openUSBConnection. (05/25/2011)
#ifndef _UE9_H
#define _UE9_H
#include <sys/time.h>
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#include "labjackusb.h"
typedef unsigned char uint8;
typedef unsigned short uint16;
typedef unsigned int uint32;
//Structure for storing calibration constants
struct UE9_CALIBRATION_INFORMATION {
uint8 prodID;
double ccConstants[25];
/*
Calibration constants order
0 - Slope, Ini G = 1
1 - Offset, Ini G = 1
2 - Slope, Ini G = 2
3 - Offset, Ini G = 2
4 - Slope, Ini G = 4
5 - Offset, Ini G = 4
6 - Slope, Ini G = 8
7 - Offset. Ini G = 8
8 - Slope, Bi G = 1
9 - Offset, Bi G = 1
10 - Slope, DAC0
11 - Offset, DAC0
12 - Slope, DAC1
13 - Offset, DAC1
14 - Slope, Temp (133/141)
15 - Slope, Temp (133/141, Low)
16 - Cal Temp
17 - Vref
18 - Reserved
19 - Vref/2
20 - Slope, Vs (132/140)
//Hi-Res ADC
21 - Slope, Ini G = 8
22 - Offset. Ini G = 8
23 - Slope, Bi G = 1
24 - Offset, Bi G = 1
*/
};
typedef struct UE9_CALIBRATION_INFORMATION ue9CalibrationInfo;
//Structure for storing LJTDAC calibration constants
struct UE9_TDAC_CALIBRATION_INFORMATION {
uint8 prodID;
double ccConstants[4];
/*
Calibration constants order
0 - SlopeA;
1 - OffsetA;
2 - SlopeB;
3 - OffsetB;
*/
};
typedef struct UE9_TDAC_CALIBRATION_INFORMATION ue9TdacCalibrationInfo;
/* Functions */
void normalChecksum( uint8 *b,
int n);
//Adds checksum to a data packet for normal command format.
//b = data packet for normal command
//n = size of data packet
void extendedChecksum( uint8 *b,
int n);
//Adds checksum to a data packet for extended command format.
//b = data packet for extended command
//n = size of data packet
uint8 normalChecksum8( uint8 *b,
int n);
//Returns the Checksum8 for a normal command data packet.
//b = data packet for normal command
//n = size of data packet
uint16 extendedChecksum16( uint8 *b,
int n);
//Returns the Checksum16 for a extended command data packet.
//b = data packet for extended command
//n = size of data packet
uint8 extendedChecksum8( uint8 *b);
//Returns the Checksum8 for a extended command data packet.
//b = data packet for extended command
HANDLE openUSBConnection( int localID);
//Opens a UE9 connection over USB. Returns NULL on failure, or a HANDLE
//on success.
//localID = the local ID or serial number of the UE9 you want to open
void closeUSBConnection( HANDLE hDevice);
//Closes a HANDLE to a UE9 device.
long getTickCount();
//Returns the number of milliseconds that has elasped since the system was
//started.
long getCalibrationInfo( HANDLE hDevice,
ue9CalibrationInfo *caliInfo);
//Gets calibration information from memory blocks 0-3 of a UE9. Returns the
//calibration information in a calibrationInfo structure.
//hDevice = handle to a UE9 device
//caliInfo = structure where calibration information will be stored
long getTdacCalibrationInfo( HANDLE hDevice,
ue9TdacCalibrationInfo *caliInfo,
uint8 DIOAPinNum);
//Gets calibration information from the EEPROM of a LJTick-DAC (LJTDAC).
//Returns the calibration information in a ue9TdacCalibrationInfo structure.
//hDevice = handle to a UE9 device
//caliInfo = structure where LJTDAC calibration information will be stored
//DIOAPinNum = The UE9 digital IO line where the LJTDAC DIOA pin is connected.
// The DIOB pin is assumed to be the next digital IO line.
double FPuint8ArrayToFPDouble( uint8 *buffer,
int startIndex);
//Converts a fixed point byte array (starting a startIndex) to a floating point
//double value. This function is used primarily by getCalibrationInfo.
long isCalibrationInfoValid( ue9CalibrationInfo *caliInfo);
//Performs a simple check to determine if the caliInfo struct was set up by
//getCalibrationInfo. Returns 0 if caliInfo is not valid, or 1 if it is.
//caliInfo = structure where calibrarion information is stored
long isTdacCalibrationInfoValid( ue9TdacCalibrationInfo *caliInfo);
//Performs a simple check to determine if the caliInfo struct was set up by
//getLJTDACCalibrationInfo. Returns 0 if caliInfo is not valid, or 1 if it is.
//caliInfo = structure where LJTDAC calibration information is stored
long getAinVoltCalibrated( ue9CalibrationInfo *caliInfo,
uint8 gainBip,
uint8 resolution,
uint16 bytesVolt,
double *analogVolt);
//Translates the binary AIN reading from the UE9 to a voltage value
//(calibrated). Call getCalibrationInfo first to set up caliInfo. Returns -1
//on error, 0 on success.
//caliInfo = structure where calibrarion information is stored
//gainBip = the gain option and bipolar setting. The high bit of the byte is
// the bipolar setting and the lower 3 bits is the gain option. See
// the Feedback function in Section 5.3.3 of the UE9 User's Guide for a
// table of BipGain values that can be passed.
//resolution = the resolution of the analog reading
//bytesVolt = the 2 byte voltage that will be converted to a analog value
//analogVolt = the converted analog voltage
long getDacBinVoltCalibrated( ue9CalibrationInfo *caliInfo,
int dacNumber,
double analogVolt,
uint16 *bytesVolt);
//Translates an analog output voltage to a binary 16 bit value (calibrated) that
//can be sent to a UE9. Call getCalibrationInfo first to set up caliInfo.
//Returns -1 on error, 0 on success.
//caliInfo = structure where calibrarion information is stored
//dacNumber - channel number of the DAC
//analogVolt = the analog voltage that will be converted to a 2 byte value
//bytesVolt = the converted 2 byte voltage
long getTdacBinVoltCalibrated( ue9TdacCalibrationInfo *caliInfo,
int dacNumber,
double analogVolt,
uint16 *bytesVolt);
//Translates an analog output voltage to a binary 16 bit value (calibrated) that
//can be sent to a LJTick-DAC (LJTDAC). Call getLJTDACCalibrationInfo first to
//set up caliInfo. Returns -1 on error, 0 on success.
//caliInfo = structure where LJTDAC calibrarion information is stored
//DACNumber - channel number of the DAC (0 = DACA, 1 = DACB)
//analogVolt = the analog voltage that will be converted to a 2 byte value
//bytesVolt = the converted 2 byte voltage
long getTempKCalibrated( ue9CalibrationInfo *caliInfo,
int powerLevel,
uint16 bytesTemp,
double *kelvinTemp);
//Translates the binary reading from the UE9, to a Kelvin temperature value
//(calibrated). Call getCalibrationInfo first to set up caliInfo. Returns
//-1 on error, 0 on success.
//caliInfo = structure where calibrarion information is stored
//powerLevel = the power level the UE9 is set at.
// (0x00: Fixed high, system clock = 48 MHz
// 0x01: Fixed low, system clock = 6 MHz)
//bytesTemp = the 2 byte temperature that will be converted to Kelvin
//kelvinTemp = the converted Kelvin temperature
long getAinVoltUncalibrated( uint8 gainBip,
uint8 resolution,
uint16 bytesVolt,
double *analogVolt);
//Translates the binary AIN reading from the UE9, to a voltage value
//(uncalibrated). Returns -1 on error, 0 on success.
//gainBip = the gain option and bipolar setting. The high bit of the byte is
// the bipolar setting and the lower 3 bits is the gain option. See
// the Feedback function in Section 5.3.3 of the UE9 User's Guide for a
// table of BipGain values that can be passed.
//resolution = the resolution of the analog reading
//bytesVoltage = the 2 byte voltage that will be converted to a analog value
//analogVoltage = the converted analog voltage
long getDacBinVoltUncalibrated( int dacNumber,
double analogVolt,
uint16 *bytesVolt);
//Translates an analog output voltage to a binary 16 bit value (uncalibrated)
//that can be sent to a UE9. Returns -1 on error, 0 on success.
//dacNumber - channel number of the DAC
//analogVoltage = the analog voltage that will be converted to a 2 byte value
//bytesVoltage = the converted 2 byte voltage
long getTempKUncalibrated( int powerLevel,
uint16 bytesTemp,
double *kelvinTemp);
//Translates the binary reading from the UE9, to a Kelvin temperature
//value (uncalibrated). Returns -1 on error, 0 on success.
//powerLevel = the power level the UE9 is set at.
// (0x00: Fixed high, system clock = 48 MHz
// 0x01: Fixed low, system clock = 6 MHz)
//bytesTemp = the 2 byte temperature that will be converted to Kelvin
//kelvinTemp = the converted Kelvin temperature
long I2C( HANDLE hDevice,
uint8 I2COptions,
uint8 SpeedAdjust,
uint8 SDAPinNum,
uint8 SCLPinNum,
uint8 Address,
uint8 NumI2CBytesToSend,
uint8 NumI2CBytesToReceive,
uint8 *I2CBytesCommand,
uint8 *Errorcode,
uint8 *AckArray,
uint8 *I2CBytesResponse);
//This function will perform the I2C low-level function call. Please refer to
//section 5.3.20 of the UE9 User's Guide for parameter documentation. Returns
//-1 on error, 0 on success.
//hDevice = handle to a UE9 device
//I2COptions = byte 6 of the command
//SpeedAdjust = byte 7 of the command
//SDAPinNum = byte 8 of the command
//SCLPinNum = byte 9 of the command
//Address = byte 10 of the command
//NumI2CBytesToSend = byte 12 of the command
//NumI2CBytesToReceive = byte 13 of the command
//*I2CBytesCommand = Array that holds bytes 14 and above of the command. Needs
// to be at least NumI2CBytesToSend elements in size.
//*Errorcode = returns byte 6 of the response
//*AckArray = Array that returns bytes 8 - 11 of the response. Needs to be at
// least 4 elements in size.
//*I2CBytesResponse = Array that returns bytes 12 and above of the response.
// Needs to be at least NumI2CBytesToReceive elements in
// size.
/* Easy Functions (Similar to the easy functions in the Windows UD driver) */
long eAIN( HANDLE Handle,
ue9CalibrationInfo *CalibrationInfo,
long ChannelP,
long ChannelN,
double *Voltage,
long Range,
long Resolution,
long Settling,
long Binary,
long Reserved1,
long Reserved2);
//An "easy" function that returns a reading from one analog input. Returns 0
//for no error, or -1 or >0 value (low-level errorcode) on error.
//Handle = Handle to a UE9 device.
//CalibrationInfo = Structure where calibration information is stored.
//ChannelP = The positive AIN channel to acquire.
//ChannelN = For the UE9, this parameter is ignored.
//Voltage = Returns the analog input reading, which is generally a voltage.
//Range = Pass a constant specifying the voltage range.
//Resolution = Pass 12-17 to specify the resolution of the analog input reading,
// and 18 for a high-res reading from UE9-Pro. 0-11 coresponds to
// 12-bit.
//Settling = Pass 0 for default settling. This parameter adds extra settling
// before the ADC conversion of about Settling times 5 microseconds.
//Binary = If this is nonzero (True), the Voltage parameter will return the raw
// binary value.
//Reserved (1&2) = Pass 0.
long eDAC( HANDLE Handle,
ue9CalibrationInfo *CalibrationInfo,
long Channel,
double Voltage,
long Binary,
long Reserved1,
long Reserved2);
//An "easy" function that writes a value to one analog output. Returns 0 for no
//error, or -1 or >0 value (low-level errorcode) on error.
//Handle = Handle to a UE9 device.
//CalibrationInfo = structure where calibrarion information is stored.
//Channel = The analog output channel to write to.
//Voltage = The voltage to write to the analog output.
//Binary = If this is nonzero (True), the value passed for Voltage should be
// binary.
//Reserved (1&2) = Pass 0.
long eDI( HANDLE Handle,
long Channel,
long *State);
//An "easy" function that reads the state of one digital input. This function
//does not automatically configure the specified channel as digital, unless
//ConfigIO is set as True. Returns 0 for no error, or -1 or >0 value (low-level
//errorcode) on error.
//Handle = Handle to a UE9 device.
//Channel = The channel to read. 0-22 corresponds to FIO0-MIO2.
//State = Returns the state of the digital input. 0=False=Low and 1=True=High.
long eDO( HANDLE Handle,
long Channel,
long State);
//An "easy" function that writes the state of one digital output. Returns 0 for
//no error, or -1 or >0 value (low-level errorcode) on error.
//Handle = Handle to a UE9 device.
//Channel = The channel to write to. 0-19 corresponds to FIO0-MIO2.
//State = The state to write to the digital output. 0=False=Low and
// 1=True=High.
long eTCConfig( HANDLE Handle,
long *aEnableTimers,
long *aEnableCounters,
long TCPinOffset,
long TimerClockBaseIndex,
long TimerClockDivisor,
long *aTimerModes,
double *aTimerValues,
long Reserved1,
long Reserved2);
//An "easy" function that configures and initializes all the timers and
//counters. Returns 0 for no error, or -1 or >0 value (low-level errorcode) on
//error.
//Handle = Handle to a UE9 device.
//aEnableTimers = An array where each element specifies whether that timer is
// enabled. Timers must be enabled in order starting from 0, so
// for instance, Timer1 cannot be enabled without enabling
// Timer 0 also. A nonzero for an array element specifies to
// enable that timer. For the UE9 this array must always have at
// least 6 elements.
//aEnableCounters = An array where each element specifies whether that counter
// is enabled. Counters do not have to be enabled in order
// starting from 0, so Counter1 can be enabled when Counter0 is
// disabled. A nonzero value for an array element specifies to
// enable that counter. For the UE9, this array must always
// have at least 2 elements.
//TCPinOffset = Ignored with the UE9.
//TimerClockBaseIndex = Pass a constant to set the timer base clock. The
// default is LJ_tc750KHZ.
//TimerClockDivisor = Pass a divisor from 0-255 where 0 is a divisor of 256.
//aTimerModes = An array where each element is a constant specifying the mode
// for that timer. For the UE9, this array must always have at
// least 6 elements.
//aTimerValues = An array where each element specifies the initial value for
// that timer. For the UE9, this array must always have at least
// 6 elements.
//Reserved (1&2) = Pass 0.
long eTCValues( HANDLE Handle,
long *aReadTimers,
long *aUpdateResetTimers,
long *aReadCounters,
long *aResetCounters,
double *aTimerValues,
double *aCounterValues,
long Reserved1,
long Reserved2);
//An "easy" function that updates and reads all the timers and counters.
//Returns 0 for no error, or -1 or >0 value (low-level errorcode) on error.
//Handle = Handle to a UE9 device.
//aReadTimers = An array where each element specifies whether to read that
// timer. A nonzero value for an array element specifies to read
// that timer. For the UE9, this array must always have at least 6
// elements.
//aUpdateResetTimers = An array where each element specifies whether to
// update/reset that timers. A nonzero value for an array
// element specifies to update/reset that timer. For the
// UE9, this array must always have at least 6 elements.
//aReadCounters = An array where each element specifies whether to read that
// counter. A nonzero value for an array element specifies to
// read that counter. For the UE9, this array must always have
// at least 2 elements.
//aResetCounters = An array where each element specifies whether to reset that
// counter. A nonzero value for an array element specifies to
// reset that counter. For the UE9, this array must always have
// at least 2 elements.
//aTimerValues = Input: An array where each element is the new value for that
// timer. Each value is only updated if the appropriate element
// is set in the aUpdateResetTimers array.
// Output: An array where each element is the value read from that
// timer if the appropriate element is set in the aReadTimers
// array. If the timer mode set for the timer is Quadrature
// Input, the value needs to be converted from an unsigned 32-bit
// integer to a signed 32-bit integer (2s complement). For the
// UE9, this array must always have at least 6 elements.
//aCounterValues = An array where each element is the value read from that
// counter if the appropriate element is set in the aReadTimers
// array. For the UE9, this array must always have at least 2
// elements.
//Reserved (1&2) = Pass 0.
/* Easy Function Helpers */
long ehSingleIO( HANDLE hDevice,
uint8 inIOType,
uint8 inChannel,
uint8 inDirBipGainDACL,
uint8 inStateResDACH,
uint8 inSettlingTime,
uint8 *outIOType,
uint8 *outChannel,
uint8 *outDirAINL,
uint8 *outStateAINM,
uint8 *outAINH);
//Used by the eAIN and eDAC easy functions. This function takes the SingleIO
//low-level command and response bytes (not including checksum and command
//bytes) as its parameter and performs a SingleIO call with the UE9. Returns -1
//on error, 0 on success.
long ehDIO_Feedback( HANDLE hDevice,
uint8 channel,
uint8 direction,
uint8 *state);
//Used by the eDI and eDO easy funtions. This function takes the same
//parameters as eDI and eDO (as bytes), with the additional parameter of
//channel, and will perform the Feedback low-level function call. Returns -1 on
//error, 0 on success.
long ehTimerCounter( HANDLE hDevice,
uint8 inTimerClockDivisor,
uint8 inEnableMask,
uint8 inTimerClockBase,
uint8 inUpdateReset,
uint8 *inTimerMode,
uint16 *inTimerValue,
uint8 *inCounterMode,
uint32 *outTimer,
uint32 *outCounter);
//Used by the eTCConfig and eTCValues easy functions. This function takes the
//TimerCounter low-level command and response bytes (not including checksum and
//command bytes) as its parameter and performs a TimerCounter call with the UE9.
//Returns -1 or errorcode (>1 value) on error, 0 on success.
/* Easy Functions Constants */
/* Ranges */
// -5V to +5V
#define LJ_rgBIP5V 3
// 0V to +5V
#define LJ_rgUNI5V 103
// 0V to +2.5V
#define LJ_rgUNI2P5V 105
// 0V to +1.25Vz
#define LJ_rgUNI1P25V 107
// 0V to +0.625V
#define LJ_rgUNIP625V 109
/* timer clocks: */
// 750 khz
#define LJ_tc750KHZ 0
// system clock
#define LJ_tcSYS 1
/* timer modes */
// 16 bit PWM
#define LJ_tmPWM16 0
// 8 bit PWM
#define LJ_tmPWM8 1
// 32-bit rising to rising edge measurement
#define LJ_tmRISINGEDGES32 2
// 32-bit falling to falling edge measurement
#define LJ_tmFALLINGEDGES32 3
// duty cycle measurement
#define LJ_tmDUTYCYCLE 4
// firmware based rising edge counter
#define LJ_tmFIRMCOUNTER 5
// firmware counter with debounce
#define LJ_tmFIRMCOUNTERDEBOUNCE 6
// frequency output
#define LJ_tmFREQOUT 7
// Quadrature
#define LJ_tmQUAD 8
// stops another timer after n pulses
#define LJ_tmTIMERSTOP 9
// read lower 32-bits of system timer
#define LJ_tmSYSTIMERLOW 10
// read upper 32-bits of system timer
#define LJ_tmSYSTIMERHIGH 11
// 16-bit rising to rising edge measurement
#define LJ_tmRISINGEDGES16 12
// 16-bit falling to falling edge measurement
#define LJ_tmFALLINGEDGES16 13
#endif

View File

@@ -0,0 +1,230 @@
/*
An example that shows a minimal use of Exodriver without the use of functions
hidden in header files.
You can compile this example with the following command:
$ g++ -lm -llabjackusb ue9BasicCommConfig.c
It is also included in the Makefile.
*/
/* Includes */
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include "labjackusb.h"
// Defines how long the command is
#define COMMCONFIG_COMMAND_LENGTH 38
// Defines how long the response is
#define COMMCONFIG_RESPONSE_LENGTH 38
/* Buffer Helper Functions Protypes */
// Takes a buffer and an offset, and turns it into a 32-bit integer
int makeInt(BYTE * buffer, int offset);
// Takes a buffer and an offset, and turns it into a 16-bit integer
int makeShort(BYTE * buffer, int offset);
// Takes a buffer and calculates the checksum8 of it.
BYTE calculateChecksum8(BYTE* buffer);
// Takes a buffer and length, and calculates the checksum16 of the buffer.
int calculateChecksum16(BYTE* buffer, int len);
/* LabJack Related Helper Functions Protoypes */
// Demonstrates how to build the CommConfig packet.
void buildCommConfigBytes(BYTE * sendBuffer);
// Demonstrates how to check a response for errors.
int checkResponseForErrors(BYTE * recBuffer);
// Demonstrates how to parse the response of CommConfig.
void parseCommConfigBytes(BYTE * recBuffer);
int main() {
// Setup the variables we will need.
int r = 0; // For checking return values
HANDLE devHandle = 0;
BYTE sendBuffer[COMMCONFIG_COMMAND_LENGTH], recBuffer[COMMCONFIG_RESPONSE_LENGTH];
// Open the UE9
devHandle = LJUSB_OpenDevice(1, 0, UE9_PRODUCT_ID);
if( devHandle == NULL ) {
printf("Couldn't open UE9. Please connect one and try again.\n");
exit(-1);
}
// Builds the CommConfig command
buildCommConfigBytes(sendBuffer);
// Write the command to the device.
// LJUSB_Write( handle, sendBuffer, length of sendBuffer )
r = LJUSB_Write( devHandle, sendBuffer, COMMCONFIG_COMMAND_LENGTH );
if( r != COMMCONFIG_COMMAND_LENGTH ) {
printf("An error occurred when trying to write the buffer. The error was: %d\n", errno);
// *Always* close the device when you error out.
LJUSB_CloseDevice(devHandle);
exit(-1);
}
// Read the result from the device.
// LJUSB_Read( handle, recBuffer, number of bytes to read)
r = LJUSB_Read( devHandle, recBuffer, COMMCONFIG_RESPONSE_LENGTH );
if( r != COMMCONFIG_RESPONSE_LENGTH ) {
printf("An error occurred when trying to read from the UE9. The error was: %d\n", errno);
LJUSB_CloseDevice(devHandle);
exit(-1);
}
// Check the command for errors
if( checkResponseForErrors(recBuffer) != 0 ){
LJUSB_CloseDevice(devHandle);
exit(-1);
}
// Parse the response into something useful
parseCommConfigBytes(recBuffer);
//Close the device.
LJUSB_CloseDevice(devHandle);
return 0;
}
/* ------------- LabJack Related Helper Functions Definitions ------------- */
// Uses information from section 5.2.1 of the UE9 User's Guide to make a CommConfig
// packet.
// http://labjack.com/support/ue9/users-guide/5.2.1
void buildCommConfigBytes(BYTE * sendBuffer) {
int i; // For loops
int checksum = 0;
// Build up the bytes
//sendBuffer[0] = Checksum8
sendBuffer[1] = 0x78;
sendBuffer[2] = 0x10;
sendBuffer[3] = 0x01;
//sendBuffer[4] = Checksum16 (LSB)
//sendBuffer[5] = Checksum16 (MSB)
// We just want to read, so we set the WriteMask to zero, and zero out the
// rest of the bytes.
sendBuffer[6] = 0;
for( i = 7; i < COMMCONFIG_COMMAND_LENGTH; i++){
sendBuffer[i] = 0;
}
// Calculate and set the checksum16
checksum = calculateChecksum16(sendBuffer, COMMCONFIG_COMMAND_LENGTH);
sendBuffer[4] = (BYTE)( checksum & 0xff );
sendBuffer[5] = (BYTE)( (checksum / 256) & 0xff );
// Calculate and set the checksum8
sendBuffer[0] = calculateChecksum8(sendBuffer);
// The bytes have been set, and the checksum calculated. We are ready to
// write to the UE9.
}
// Checks the response for any errors.
int checkResponseForErrors(BYTE * recBuffer) {
if(recBuffer[0] == 0xB8 && recBuffer[1] == 0xB8) {
// If the packet is [ 0xB8, 0xB8 ], that's a bad checksum.
printf("The UE9 detected a bad checksum. Double check your checksum calculations and try again.\n");
return -1;
}
else if (recBuffer[1] != 0x78 || recBuffer[2] != 0x10 || recBuffer[3] != 0x01) {
// Make sure the command bytes match what we expect.
printf("Got the wrong command bytes back from the UE9.\n");
return -1;
}
// Normally, we would check byte 6 for errorcodes. CommConfig is an
// exception to that rule.
// Calculate the checksums.
int checksum16 = calculateChecksum16(recBuffer, COMMCONFIG_RESPONSE_LENGTH);
BYTE checksum8 = calculateChecksum8(recBuffer);
if ( checksum8 != recBuffer[0] || recBuffer[4] != (BYTE)( checksum16 & 0xff ) || recBuffer[5] != (BYTE)( (checksum16 / 256) & 0xff ) ) {
// Check the checksum
printf("Response had invalid checksum.\n%d != %d, %d != %d, %d != %d\n", checksum8, recBuffer[0], (BYTE)( checksum16 & 0xff ), recBuffer[4], (BYTE)( (checksum16 / 256) & 0xff ), recBuffer[5] );
return -1;
}
return 0;
}
// Parses the CommConfig packet into something useful.
void parseCommConfigBytes(BYTE * recBuffer){
printf("Results of CommConfig:\n");
printf(" LocalID = %d\n", recBuffer[8]);
printf(" PowerLevel = %d\n", recBuffer[9]);
printf(" IPAddress = %d.%d.%d.%d\n", recBuffer[13], recBuffer[12], recBuffer[11], recBuffer[10] );
printf(" Gateway = %d.%d.%d.%d\n", recBuffer[17], recBuffer[16], recBuffer[15], recBuffer[14] );
printf(" Subnet = %d.%d.%d.%d\n", recBuffer[21], recBuffer[20], recBuffer[19], recBuffer[18] );
printf(" PortA = %d\n", makeShort(recBuffer, 22));
printf(" PortB = %d\n", makeShort(recBuffer, 24));
printf(" DHCPEnabled = %d\n", recBuffer[26]);
printf(" ProductID = %d\n", recBuffer[27]);
printf(" MACAddress = %02X:%02X:%02X:%02X:%02X:%02X\n", recBuffer[33], recBuffer[32], recBuffer[31], recBuffer[30], recBuffer[29], recBuffer[28]);
BYTE serialBytes[4];
serialBytes[0] = recBuffer[28];
serialBytes[1] = recBuffer[29];
serialBytes[2] = recBuffer[30];
serialBytes[3] = 0x10;
printf(" SerialNumber = %d\n", makeInt(serialBytes, 0));
printf(" HardwareVersion = %d.%02d\n", recBuffer[35], recBuffer[34]);
printf(" FirmwareVersion = %d.%02d\n", recBuffer[37], recBuffer[36]);
}
/* ---------------- Buffer Helper Functions Definitions ---------------- */
// Takes a buffer and an offset, and turns into an 32-bit integer
int makeInt(BYTE * buffer, int offset){
return (buffer[offset+3] << 24) + (buffer[offset+2] << 16) + (buffer[offset+1] << 8) + buffer[offset];
}
// Takes a buffer and an offset, and turns into an 16-bit integer
int makeShort(BYTE * buffer, int offset) {
return (buffer[offset+1] << 8) + buffer[offset];
}
// Calculates the checksum8
BYTE calculateChecksum8(BYTE* buffer){
int i; // For loops
int temp; // For holding a value while we working.
int checksum = 0;
for( i = 1; i < 6; i++){
checksum += buffer[i];
}
temp = checksum/256;
checksum = ( checksum - 256 * temp ) + temp;
temp = checksum/256;
return (BYTE)( ( checksum - 256 * temp ) + temp );
}
// Calculates the checksum16
int calculateChecksum16(BYTE* buffer, int len){
int i;
int checksum = 0;
for( i = 6; i < len; i++){
checksum += buffer[i];
}
return checksum;
}

View File

@@ -0,0 +1,148 @@
//Author: LabJack
//May 25, 2011
//This example program sends a ControlConfig low-level command, and reads the
//various parameters associated with the Control processor.
#include "ue9.h"
int controlConfig_example(HANDLE hDevice, ue9CalibrationInfo *caliInfo);
int main(int argc, char **argv)
{
HANDLE hDevice;
ue9CalibrationInfo caliInfo;
//Opening first found UE9 over USB
if( (hDevice = openUSBConnection(-1)) == NULL )
goto done;
//Getting calibration information from UE9
if(getCalibrationInfo(hDevice, &caliInfo) < 0)
goto close;
controlConfig_example(hDevice, &caliInfo);
close:
closeUSBConnection(hDevice);
done:
return 0;
}
//Sends a ControlConfig low-level command to read the configuration settings
//associated with the Control chip.
int controlConfig_example(HANDLE hDevice, ue9CalibrationInfo *caliInfo)
{
uint8 sendBuff[18], recBuff[24];
uint16 checksumTotal;
int sendChars, recChars, i;
double dac;
sendBuff[1] = (uint8)(0xF8); //Command byte
sendBuff[2] = (uint8)(0x06); //Number of data words
sendBuff[3] = (uint8)(0x08); //Extended command number
//WriteMask, PowerLevel, FIODir, etc. are all passed a value of zero since
//we only want to read Control configuration settings, not change them.
for( i = 6; i < 18; i++ )
sendBuff[i] = (uint8)(0x00);
extendedChecksum(sendBuff,18);
//Sending command to UE9
sendChars = LJUSB_Write(hDevice, sendBuff, 18);
if( sendChars < 18 )
{
if( sendChars == 0 )
printf("Error : write failed\n");
else
printf("Error : did not write all of the buffer\n");
return -1;
}
//Reading response from UE9
recChars = LJUSB_Read(hDevice, recBuff, 24);
if( recChars < 24 )
{
if( recChars == 0 )
printf("Error : read failed\n");
else
printf("Error : did not read all of the buffer\n");
return -1;
}
checksumTotal = extendedChecksum16(recBuff, 24);
if( (uint8)((checksumTotal >> 8) & 0xff) != recBuff[5] )
{
printf("Error : read buffer has bad checksum16(MSB)\n");
return -1;
}
if( (uint8)(checksumTotal & 0xff) != recBuff[4] )
{
printf("Error : read buffer has bad checksum16(LSB)\n");
return -1;
}
if( extendedChecksum8(recBuff) != recBuff[0] )
{
printf("Error : read buffer has bad checksum8\n");
return -1;
}
if( recBuff[1] != (uint8)(0xF8) || recBuff[2] != (uint8)(0x09) || recBuff[3] != (uint8)(0x08) )
{
printf("Error : read buffer has wrong command bytes \n");
return -1;
}
if( recBuff[6] != 0 )
{
printf("Errorcode (byte 6): %d\n", (unsigned int)recBuff[6]);
return -1;
}
printf("PowerLevel default (byte 7): %d\n", (unsigned int)recBuff[7]);
printf("ResetSource (byte 8): %d\n", (unsigned int)recBuff[8]);
printf("ControlFW Version (bytes 9 and 10): %.3f\n", (unsigned int)recBuff[10] + (double)recBuff[9]/100.0);
printf("ControlBL Version (bytes 11 and 12): %.3f\n", (unsigned int)recBuff[12] + (double)recBuff[11]/100.0);
printf("FIO default directions and states (bytes 14 and 15):\n");
for( i = 0; i < 8; i++ )
printf(" FIO%d: %d and %d\n", i,( (unsigned int)recBuff[14] << (31 - i) ) >> 31, ( (unsigned int)recBuff[15] << (31 - i) ) >> 31);
printf("EIO default directions and states (bytes 16 and 17):\n");
for( i = 0; i < 8; i++ )
printf(" EIO%d: %d and %d\n", i, ( (unsigned int)recBuff[16] << (31 - i) ) >> 31, ( (unsigned int)recBuff[17] << (31 - i) ) >> 31);
printf("CIO default directions and states (byte 18):\n");
for( i = 0; i <= 3; i++ )
printf(" CIO%d: %d and %d\n", i, ( (unsigned int)recBuff[18] << (27 - i) ) >> 31, ( (unsigned int)recBuff[18] << (31 - i) ) >> 31);
printf("MIO default directions and states (byte 19):\n");
for( i = 0; i <= 2; i++ )
printf(" MIO%d: %d and %d\n", i, ( (unsigned int)recBuff[19] << (27 - i) ) >> 31, ( (unsigned int)recBuff[19] << (31 - i) ) >> 31);
printf("DAC0 default (bytes 20 and 21):\n Enabled: %d\n Update: %d\n", ( (unsigned int)recBuff[21] << 24 ) >> 31, ( (unsigned int)recBuff[21] << 25 ) >> 31);
//Getting DAC0 binary value
dac = (double)( (unsigned int)recBuff[20] + (( (unsigned int)recBuff[21] << 28 ) >> 20) );
//Getting DAC0 analog value ( Volts = (Bits - Offset)/Slope )
dac = (dac - caliInfo->ccConstants[11])/caliInfo->ccConstants[10];
printf(" Voltage: %.3f V\n", dac);
printf("DAC1 default (bytes 22 and 23):\n Enabled: %d\n Update: %d\n", ( (unsigned int)recBuff[23] << 24 ) >> 31, ( (unsigned int)recBuff[23] << 25 ) >> 31);
//getting DAC1 binary value
dac = (double)( (unsigned int)recBuff[22] + (( (unsigned int)recBuff[23] << 28 ) >> 20) );
//getting DAC1 analog value ( Volts = (Bits - Offset)/Slope )
dac = (dac - caliInfo->ccConstants[13])/caliInfo->ccConstants[12];
printf(" Voltage: %.3f V\n", dac);
return 0;
}

View File

@@ -0,0 +1,101 @@
//Author: LabJack
//March 2, 2007
//This examples demonstrates how to read from analog inputs (AIN) and digital inputs(FIO),
//set analog outputs (DAC) and digital outputs (FIO), and how to configure and enable
//timers and counters and read input timers and counters values using the "easy" functions.
#include "ue9.h"
#include <unistd.h>
int main(int argc, char **argv)
{
HANDLE hDevice;
ue9CalibrationInfo caliInfo;
int localID, i;
long error;
//Open first found UE9 over USB
localID = -1;
if( (hDevice = openUSBConnection(localID)) == NULL )
goto done;
//Get calibration information from UE9
if( getCalibrationInfo(hDevice, &caliInfo) < 0 )
goto close;
//Set DAC0 to 3.1 volts.
printf("Calling eDAC to set DAC0 to 3.1 V\n");
if( (error = eDAC(hDevice, &caliInfo, 0, 3.1, 0, 0, 0)) != 0 )
goto close;
//Read the voltage from AIN3 using 0-5 volt range at 12 bit resolution
printf("Calling eAIN to read voltage from AIN3\n");
double dblVoltage;
if( (error = eAIN(hDevice, &caliInfo, 3, 0, &dblVoltage, LJ_rgUNI5V, 12, 0, 0, 0, 0)) != 0 )
goto close;
printf("\nAIN3 value = %.3f\n", dblVoltage);
//Set FIO3 to output-high
printf("\nCalling eDO to set FIO3 to output-high\n");
if((error = eDO(hDevice, 3, 1)) != 0)
goto close;
//Read state of FIO2
printf("\nCalling eDI to read the state of FIO2\n");
long lngState;
if( (error = eDI(hDevice, 2, &lngState)) != 0 )
goto close;
printf("FIO2 state = %ld\n", lngState);
//Enable and configure 1 output timer and 1 input timer, and enable counter0
printf("\nCalling eTCConfig to enable and configure 1 output timer (Timer0) and 1 input timer (Timer1), and enable counter0\n");
long alngEnableTimers[6] = {1, 1, 0, 0, 0, 0}; //Enable Timer0-Timer1
long alngTimerModes[6] = {LJ_tmPWM8, LJ_tmRISINGEDGES32, 0, 0, 0, 0}; //Set timer modes
double adblTimerValues[6] = {16384, 0, 0, 0, 0, 0}; //Set PWM8 duty-cycles to 75%
long alngEnableCounters[2] = {1, 0}; //Enable Counter0
if( (error = eTCConfig(hDevice, alngEnableTimers, alngEnableCounters, 0, LJ_tc750KHZ, 3, alngTimerModes, adblTimerValues, 0, 0)) != 0 )
goto close;
printf("\nWaiting for 1 second...\n");
sleep(1);
//Read and reset the input timer (Timer1), read and reset Counter0, and update the
//value (duty-cycle) of the output timer (Timer0)
printf("\nCalling eTCValues to read and reset the input Timer1 and Counter0, and update the value (duty-cycle) of the output Timer0\n");
long alngReadTimers[6] = {0, 1, 0, 0, 0, 0}; //Read Timer1
long alngUpdateResetTimers[6] = {1, 0, 0, 0, 0, 0}; //Update timer0
long alngReadCounters[2] = {1, 0}; //Read Counter0
long alngResetCounters[2] = {0, 0}; //Reset Counter0
double adblCounterValues[2] = {0, 0};
adblTimerValues[0] = 32768; //Change Timer0 duty-cycle to 50%
if( (error = eTCValues(hDevice, alngReadTimers, alngUpdateResetTimers, alngReadCounters, alngResetCounters, adblTimerValues, adblCounterValues, 0, 0)) != 0 )
goto close;
printf("Timer1 value = %.0f\n", adblTimerValues[1]);
printf("Counter0 value = %.0f\n", adblCounterValues[0]);
//Disable all timers and counters
for(i = 0; i < 6; i++)
alngEnableTimers[i] = 0;
alngEnableCounters[0] = 0;
alngEnableCounters[1] = 0;
if( (error = eTCConfig(hDevice, alngEnableTimers, alngEnableCounters, 0, 0, 0, alngTimerModes, adblTimerValues, 0, 0)) != 0 )
goto close;
printf("\nCalling eTCConfig to disable all timers and counters\n");
close:
if( error > 0 )
printf("Received an error code of %ld\n", error);
closeUSBConnection(hDevice);
done:
return 0;
}

View File

@@ -0,0 +1,269 @@
/*
An example that shows how to use sockets to talk with the UE9. You may notice
that the code is VERY similar to ue9BasicCommConfig.c. The only difference is
using socket calls instead of calls to the Exodriver.
You can compile this example with the following command:
$ g++ -o ue9EthernetExample ue9EthernetExample.c
To run it:
$ ./ue9EthernetExample <IP Address>
It is also included in the Makefile.
*/
//Because that is what an unsigned char is.
typedef unsigned char BYTE;
/* Includes */
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netdb.h>
// Defines how long the command is
#define COMMCONFIG_COMMAND_LENGTH 38
// Defines how long the response is
#define COMMCONFIG_RESPONSE_LENGTH 38
/* Buffer Helper Functions Protypes */
// Takes a buffer and an offset, and turns it into a 32-bit integer
int makeInt(BYTE * buffer, int offset);
// Takes a buffer and an offset, and turns it into a 16-bit integer
int makeShort(BYTE * buffer, int offset);
// Takes a buffer and calculates the checksum8 of it.
BYTE calculateChecksum8(BYTE* buffer);
// Takes a buffer and length, and calculates the checksum16 of the buffer.
int calculateChecksum16(BYTE* buffer, int len);
/* LabJack Related Helper Functions Protoypes */
// Demonstrates how to build the CommConfig packet.
void buildCommConfigBytes(BYTE * sendBuffer);
// Demonstrates how to check a response for errors.
int checkResponseForErrors(BYTE * recBuffer);
// Demonstrates how to parse the response of CommConfig.
void parseCommConfigBytes(BYTE * recBuffer);
int main(int argc, char *argv[]) {
// Setup the variables we will need.
int r = 0; // For checking return values
int devHandle = 0;
BYTE sendBuffer[COMMCONFIG_COMMAND_LENGTH], recBuffer[COMMCONFIG_RESPONSE_LENGTH];
struct addrinfo hints, *res;
if(argc < 2) {
fprintf(stderr,"Usage: %s <IP Address>\n", argv[0]);
exit(-1);
}
memset(&hints, 0, sizeof hints);
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
printf("Getting IP Info... ");
r = getaddrinfo(argv[1], "52360", &hints, &res);
if( r != 0 ){
perror("Couldn't parse address info. Error: ");
exit(-1);
}
printf("Done\n");
printf("Getting socket FD... ");
// Open the UE9, through a socket.
devHandle = socket(AF_INET, SOCK_STREAM, 0);
if( devHandle < 0 ) {
perror("Couldn't open socket.");
exit(-1);
}
printf("Done\n");
printf("Connecting (time out after a minute)... ");
fflush(stdout);
r = connect(devHandle, res->ai_addr, res->ai_addrlen);
if( r < 0 ){
perror("\nCouldn't connect to UE9. The error was");
close(devHandle);
exit(-1);
}
printf("Done\n");
// Builds the CommConfig command
buildCommConfigBytes(sendBuffer);
// Write the command to the device.
// LJUSB_Write( handle, sendBuffer, length of sendBuffer )
r = write( devHandle, sendBuffer, COMMCONFIG_COMMAND_LENGTH );
if( r != COMMCONFIG_COMMAND_LENGTH ) {
printf("An error occurred when trying to write the buffer. The error was: %d\n", errno);
// *Always* close the device when you error out.
close(devHandle);
exit(-1);
}
// Read the result from the device.
// LJUSB_Read( handle, recBuffer, number of bytes to read)
r = read( devHandle, recBuffer, COMMCONFIG_RESPONSE_LENGTH );
if( r != COMMCONFIG_RESPONSE_LENGTH ) {
printf("An error occurred when trying to read from the UE9. The error was: %d\n", errno);
close(devHandle);
exit(-1);
}
// Check the command for errors
if( checkResponseForErrors(recBuffer) != 0 ){
close(devHandle);
exit(-1);
}
// Parse the response into something useful
parseCommConfigBytes(recBuffer);
//Close the device.
close(devHandle);
return 0;
}
/* ------------- LabJack Related Helper Functions Definitions ------------- */
// Uses information from section 5.2.1 of the UE9 User's Guide to make a CommConfig
// packet.
// http://labjack.com/support/ue9/users-guide/5.2.1
void buildCommConfigBytes(BYTE * sendBuffer) {
int i; // For loops
int checksum = 0;
// Build up the bytes
//sendBuffer[0] = Checksum8
sendBuffer[1] = 0x78;
sendBuffer[2] = 0x10;
sendBuffer[3] = 0x01;
//sendBuffer[4] = Checksum16 (LSB)
//sendBuffer[5] = Checksum16 (MSB)
// We just want to read, so we set the WriteMask to zero, and zero out the
// rest of the bytes.
sendBuffer[6] = 0;
for( i = 7; i < COMMCONFIG_COMMAND_LENGTH; i++){
sendBuffer[i] = 0;
}
// Calculate and set the checksum16
checksum = calculateChecksum16(sendBuffer, COMMCONFIG_COMMAND_LENGTH);
sendBuffer[4] = (BYTE)( checksum & 0xff );
sendBuffer[5] = (BYTE)( (checksum / 256) & 0xff );
// Calculate and set the checksum8
sendBuffer[0] = calculateChecksum8(sendBuffer);
// The bytes have been set, and the checksum calculated. We are ready to
// write to the UE9.
}
// Checks the response for any errors.
int checkResponseForErrors(BYTE * recBuffer) {
if(recBuffer[0] == 0xB8 && recBuffer[1] == 0xB8) {
// If the packet is [ 0xB8, 0xB8 ], that's a bad checksum.
printf("The UE9 detected a bad checksum. Double check your checksum calculations and try again.\n");
return -1;
}
else if (recBuffer[1] == 0x78 && recBuffer[2] == 0x10 && recBuffer[2] == 0x01) {
// Make sure the command bytes match what we expect.
printf("Got the wrong command bytes back from the UE9.\n");
return -1;
}
// Normally, we would check byte 6 for errorcodes. CommConfig is an
// exception to that rule.
// Calculate the checksums.
int checksum16 = calculateChecksum16(recBuffer, COMMCONFIG_RESPONSE_LENGTH);
BYTE checksum8 = calculateChecksum8(recBuffer);
if ( checksum8 != recBuffer[0] || recBuffer[4] != (BYTE)( checksum16 & 0xff ) || recBuffer[5] != (BYTE)( (checksum16 / 256) & 0xff ) ) {
// Check the checksum
printf("Response had invalid checksum.\n%d != %d, %d != %d, %d != %d\n", checksum8, recBuffer[0], (BYTE)( checksum16 & 0xff ), recBuffer[4], (BYTE)( (checksum16 / 256) & 0xff ), recBuffer[5] );
return -1;
}
return 0;
}
// Parses the CommConfig packet into something useful.
void parseCommConfigBytes(BYTE * recBuffer){
printf("Results of CommConfig:\n");
printf(" LocalID = %d\n", recBuffer[8]);
printf(" PowerLevel = %d\n", recBuffer[9]);
printf(" IPAddress = %d.%d.%d.%d\n", recBuffer[13], recBuffer[12], recBuffer[11], recBuffer[10] );
printf(" Gateway = %d.%d.%d.%d\n", recBuffer[17], recBuffer[16], recBuffer[15], recBuffer[14] );
printf(" Subnet = %d.%d.%d.%d\n", recBuffer[21], recBuffer[20], recBuffer[19], recBuffer[18] );
printf(" PortA = %d\n", makeShort(recBuffer, 22));
printf(" PortB = %d\n", makeShort(recBuffer, 24));
printf(" DHCPEnabled = %d\n", recBuffer[26]);
printf(" ProductID = %d\n", recBuffer[27]);
printf(" MACAddress = %02X:%02X:%02X:%02X:%02X:%02X\n", recBuffer[33], recBuffer[32], recBuffer[31], recBuffer[30], recBuffer[29], recBuffer[28]);
BYTE serialBytes[4];
serialBytes[0] = recBuffer[28];
serialBytes[1] = recBuffer[29];
serialBytes[2] = recBuffer[30];
serialBytes[3] = 0x10;
printf(" SerialNumber = %d\n", makeInt(serialBytes, 0));
printf(" HardwareVersion = %d.%02d\n", recBuffer[35], recBuffer[34]);
printf(" FirmwareVersion = %d.%02d\n", recBuffer[37], recBuffer[36]);
}
/* ---------------- Buffer Helper Functions Definitions ---------------- */
// Takes a buffer and an offset, and turns into an 32-bit integer
int makeInt(BYTE * buffer, int offset){
return (buffer[offset+3] << 24) + (buffer[offset+2] << 16) + (buffer[offset+1] << 8) + buffer[offset];
}
// Takes a buffer and an offset, and turns into an 16-bit integer
int makeShort(BYTE * buffer, int offset) {
return (buffer[offset+1] << 8) + buffer[offset];
}
// Calculates the checksum8
BYTE calculateChecksum8(BYTE* buffer){
int i; // For loops
int temp; // For holding a value while we working.
int checksum = 0;
for( i = 1; i < 6; i++){
checksum += buffer[i];
}
temp = checksum/256;
checksum = ( checksum - 256 * temp ) + temp;
temp = checksum/256;
return (BYTE)( ( checksum - 256 * temp ) + temp );
}
// Calculates the checksum16
int calculateChecksum16(BYTE* buffer, int len){
int i;
int checksum = 0;
for( i = 6; i < len; i++){
checksum += buffer[i];
}
return checksum;
}

View File

@@ -0,0 +1,154 @@
//Author: LabJack
//May 25, 2011
//This example program calls the Feedback low-level function. DAC0 will be set
//to 2.5 volts and DAC1 will be set to 3.5 volts. The states and directions
//will be read from FIO0 - FIO3 and the voltages (calibrated) from AI0-AI3.
#include "ue9.h"
int feedback_example(HANDLE hDevice, ue9CalibrationInfo *caliInfo);
int main(int argc, char **argv)
{
HANDLE hDevice;
ue9CalibrationInfo caliInfo;
//Opening first found UE9 over USB
if( (hDevice = openUSBConnection(-1)) == NULL )
goto done;
//Getting calibration information from UE9
if( getCalibrationInfo(hDevice, &caliInfo) < 0 )
goto close;
feedback_example(hDevice, &caliInfo);
close:
closeUSBConnection(hDevice);
done:
return 0;
}
//Sends a Feedback low-level command to set DAC0, DAC1, read FIO0-FIO3 and
//AI0-AI3.
int feedback_example(HANDLE hDevice, ue9CalibrationInfo *caliInfo)
{
uint8 sendBuff[34], recBuff[64], ainResolution, gainBip;
uint16 checksumTotal, bytesVoltage;
uint32 tempDir, tempState;
int sendChars, recChars, i;
double voltage;
ainResolution = 12;
//ainResolution = 18; //high-res mode for UE9 Pro only
gainBip = 0; //(Gain = 1, Bipolar = 0)
sendBuff[1] = (uint8)(0xF8); //Command byte
sendBuff[2] = (uint8)(0x0E); //Number of data words
sendBuff[3] = (uint8)(0x00); //Extended command number
//All these bytes are set to zero since we are not changing the FIO, EIO, CIO
//and MIO directions and states
for( i = 6; i <= 15; i++ )
sendBuff[i] = (uint8)(0x00);
if( getDacBinVoltCalibrated(caliInfo, 0, 2.500, &bytesVoltage) < 0 )
return -1;
//setting the voltage of DAC0
sendBuff[16] = (uint8)( bytesVoltage & (0x00FF) ); //low bits of DAC0
sendBuff[17] = (uint8)( bytesVoltage / 256 ) + 192; //high bits of DAC0
//(bit 7 : Enable,
// bit 6: Update)
if( getDacBinVoltCalibrated(caliInfo, 1, 3.500, &bytesVoltage) < 0 )
return -1;
//setting the voltage of DAC1
sendBuff[18] = (uint8)( bytesVoltage & (0x00FF) ); //low bits of DAC1
sendBuff[19] = (uint8)( bytesVoltage / 256 ) + 192; //high bits of DAC1
//(bit 7 : Enable,
// bit 6: Update)
sendBuff[20] = (uint8)(0x0f); //AINMask - reading AIN0-AIN3, not AIN4-AIN7
sendBuff[21] = (uint8)(0x00); //AINMask - not reading AIN8-AIN15
sendBuff[22] = (uint8)(0x00); //AIN14ChannelNumber - not using
sendBuff[23] = (uint8)(0x00); //AIN15ChannelNumber - not using
sendBuff[24] = ainResolution; //Resolution = 12
//Setting BipGains
for( i = 25; i < 34; i++ )
sendBuff[i] = gainBip;
extendedChecksum(sendBuff, 34);
//Sending command to UE9
sendChars = LJUSB_Write(hDevice, sendBuff, 34);
if( sendChars < 34 )
{
if( sendChars == 0 )
printf("Error : write failed\n");
else
printf("Error : did not write all of the buffer\n");
return -1;
}
//Reading response from UE9
recChars = LJUSB_Read(hDevice, recBuff, 64);
if( recChars < 64 )
{
if( recChars == 0 )
printf("Error : read failed\n");
else
printf("Error : did not read all of the buffer\n");
return -1;
}
checksumTotal = extendedChecksum16(recBuff, 64);
if( (uint8)((checksumTotal / 256) & 0xff) != recBuff[5] )
{
printf("Error : read buffer has bad checksum16(MSB)\n");
return -1;
}
if( (uint8)(checksumTotal & 0xff) != recBuff[4])
{
printf("Error : read buffer has bad checksum16(LSB)\n");
return -1;
}
if( extendedChecksum8(recBuff) != recBuff[0] )
{
printf("Error : read buffer has bad checksum8\n");
return -1;
}
if( recBuff[1] != (uint8)(0xF8) || recBuff[2] != (uint8)(0x1D) || recBuff[3] != (uint8)(0x00) )
{
printf("Error : read buffer has wrong command bytes \n");
return -1;
}
printf("Set DAC0 to 2.500 volts and DAC1 to 3.500 volts.\n\n");
printf("Flexible digital I/O directions and states (FIO0 - FIO3):\n");
for( i = 0; i < 4; i++ )
{
tempDir = ( (uint32)(recBuff[6] / pow(2, i)) & (0x01) );
tempState = ( (uint32)(recBuff[7] / pow(2, i)) & (0x01) );
printf(" FI%d: %u and %u\n", i, tempDir, tempState);
}
printf("\nAnalog Inputs (AI0 - AI3):\n");
for( i = 0; i < 4; i++ )
{
bytesVoltage = recBuff[12 + 2*i] + recBuff[13 + 2*i]*256;
//getting analog voltage
if( getAinVoltCalibrated(caliInfo, gainBip, ainResolution, bytesVoltage, &voltage) < 0 )
return -1;
printf(" AI%d: %.4f V\n", i, voltage);
}
printf("\n");
return 0;
}

View File

@@ -0,0 +1,195 @@
//Author: LabJack
//June 23, 2009
//Communicates with an LJTick-DAC using low level functions. The LJTDAC should
//be plugged into FIO0/FIO1 for this example.
//Tested with UE9 Comm firmware V1.43 and Control firmware V1.84.
#include "ue9.h"
#include <unistd.h>
int checkI2CErrorcode(uint8 errorcode);
int LJTDAC_example(HANDLE hDevice, ue9TdacCalibrationInfo *caliInfo);
const uint8 SCLPinNum = 0;
int main(int argc, char **argv)
{
HANDLE hDevice;
ue9TdacCalibrationInfo caliInfo;
//Opening first found UE9 over USB
if( (hDevice = openUSBConnection(-1)) == NULL )
goto done;
//Getting calibration information from LJTDAC
if( getTdacCalibrationInfo(hDevice, &caliInfo, SCLPinNum) < 0 )
goto close;
LJTDAC_example(hDevice, &caliInfo);
close:
closeUSBConnection(hDevice);
done:
return 0;
}
int checkI2CErrorcode(uint8 errorcode)
{
if( errorcode != 0 )
{
printf("I2C error : received errorcode %d in response\n", errorcode);
return -1;
}
return 0;
}
int LJTDAC_example( HANDLE hDevice, ue9TdacCalibrationInfo *caliInfo )
{
uint8 options, speedAdjust, sdaPinNum, sclPinNum;
uint8 address, numBytesToSend, numBytesToReceive, errorcode;
uint8 bytesCommand[5], bytesResponse[64], ackArray[4];
uint16 binaryVoltage;
int i, err;
err = 0;
//Setting up parts I2C command that will remain the same throughout this example
options = 0; //I2COptions : 0
speedAdjust = 0; //SpeedAdjust : 0 (for max communication speed of about 130 kHz)
sdaPinNum = SCLPinNum + 1; //SDAPinNum : FIO1 connected to pin DIOB
sclPinNum = SCLPinNum; //SCLPinNum : FIO0 connected to pin DIOA
/* Set DACA to 1.2 volts. */
//Setting up I2C command
//Make note that the I2C command can only update 1 DAC channel at a time.
address = (uint8)(0x24); //Address : h0x24 is the address for DAC
numBytesToSend = 3; //NumI2CByteToSend : 3 bytes to specify DACA and the value
numBytesToReceive = 0; //NumI2CBytesToReceive : 0 since we are only setting the value of the DAC
bytesCommand[0] = (uint8)(0x30); //LJTDAC command byte : h0x30 (DACA)
getTdacBinVoltCalibrated(caliInfo, 0, 1.2, &binaryVoltage);
bytesCommand[1] = (uint8)(binaryVoltage/256); //value (high)
bytesCommand[2] = (uint8)(binaryVoltage & (0x00FF)); //value (low)
//Performing I2C low-level call
err = I2C(hDevice, options, speedAdjust, sdaPinNum, sclPinNum, address, numBytesToSend, numBytesToReceive, bytesCommand, &errorcode, ackArray, bytesResponse);
if( checkI2CErrorcode(errorcode) == -1 || err == -1 )
return -1;
printf("DACA set to 1.2 volts\n\n");
/* Set DACB to 2.3 volts. */
//Setting up I2C command
address = (uint8)(0x24); //Address : h0x24 is the address for DAC
numBytesToSend = 3; //NumI2CByteToSend : 3 bytes to specify DACB and the value
numBytesToReceive = 0; //NumI2CBytesToReceive : 0 since we are only setting the value of the DAC
bytesCommand[0] = (uint8)(0x31); //LJTDAC command byte : h0x31 (DACB)
getTdacBinVoltCalibrated(caliInfo, 1, 2.3, &binaryVoltage);
bytesCommand[1] = (uint8)(binaryVoltage/256); //value (high)
bytesCommand[2] = (uint8)(binaryVoltage & (0x00FF)); //value (low)
//Performing I2C low-level call
err = I2C(hDevice, options, speedAdjust, sdaPinNum, sclPinNum, address, numBytesToSend, numBytesToReceive, bytesCommand, &errorcode, ackArray, bytesResponse);
if( checkI2CErrorcode(errorcode) == -1 || err == -1 )
return -1;
printf("DACB set to 2.3 volts\n\n");
/* More advanced operations. */
/* Display LJTDAC calibration constants. Code for getting the calibration constants is in the
* getLJTDACCalibrationInfo function in the ue9.c file. */
printf("DACA Slope = %.1f bits/volt\n", caliInfo->ccConstants[0]);
printf("DACA Offset = %.1f bits\n", caliInfo->ccConstants[1]);
printf("DACB Slope = %.1f bits/volt\n", caliInfo->ccConstants[2]);
printf("DACB Offset = %.1f bits\n\n", caliInfo->ccConstants[3]);
/* Read the serial number. */
//Setting up I2C command
address = (uint8)(0xA0); //Address : h0xA0 is the address for EEPROM
numBytesToSend = 1; //NumI2CByteToSend : 1 byte for the EEPROM address
numBytesToReceive = 4; //NumI2CBytesToReceive : getting 4 bytes starting at EEPROM address specified in I2CByte0
bytesCommand[0] = 96; //I2CByte0 : Memory Address, starting at address 96 (Serial Number)
//Performing I2C low-level call
err = I2C(hDevice, options, speedAdjust, sdaPinNum, sclPinNum, address, numBytesToSend, numBytesToReceive, bytesCommand, &errorcode, ackArray, bytesResponse);
if( checkI2CErrorcode(errorcode) == -1 || err == -1 )
return -1;
printf("LJTDAC Serial Number = %u\n\n", (bytesResponse[0] + bytesResponse[1]*256 + bytesResponse[2]*65536 + bytesResponse[3]*16777216));
/* User memory example. We will read the memory, update a few elements,
* and write the memory. The user memory is just stored as bytes, so almost
* any information can be put in there such as integers, doubles, or strings. */
/* Read the user memory */
//Setting up I2C command
address = (uint8)(0xA0); //Address : h0xA0 is the address for EEPROM
numBytesToSend = 1; //NumI2CByteToSend : 1 byte for the EEPROM address
numBytesToReceive = 64; //NumI2CBytesToReceive : getting 64 bytes starting at EEPROM address specified in I2CByte0
bytesCommand[0] = 0; //I2CByte0 : Memory Address, starting at address 0 (User Area)
//Performing I2C low-level call
err = I2C(hDevice, options, speedAdjust, sdaPinNum, sclPinNum, address, numBytesToSend, numBytesToReceive, bytesCommand, &errorcode, ackArray, bytesResponse);
if( checkI2CErrorcode(errorcode) == -1 || err == -1 )
return -1;
//Display the first 4 elements.
printf("Read User Mem [0-3] = %d, %d, %d, %d\n", bytesResponse[0], bytesResponse[1], bytesResponse[2], bytesResponse[3]);
/* Create 4 new pseudo-random numbers to write. We will update the first
* 4 elements of user memory, but the rest will be unchanged. */
//Setting up I2C command
address = (uint8)(0xA0); //Address : h0xA0 is the address for EEPROM
numBytesToSend = 5; //NumI2CByteToSend : 1 byte for the EEPROM address and the rest for the bytes to write
numBytesToReceive = 0; //NumI2CBytesToReceive : 0 since we are only writing to memory
bytesCommand[0] = 0; //I2CByte0 : Memory Address, starting at address 0 (User Area)
srand((unsigned int)getTickCount());
for( i = 1; i < 5; i++ )
bytesCommand[i] = (uint8)(255*((float)rand()/RAND_MAX));; //I2CByte : byte in user memory
printf("Write User Mem [0-3] = %d, %d, %d, %d\n", bytesCommand[1], bytesCommand[2], bytesCommand[3], bytesCommand[4]);
//Performing I2C low-level call
err = I2C(hDevice, options, speedAdjust, sdaPinNum, sclPinNum, address, numBytesToSend, numBytesToReceive, bytesCommand, &errorcode, ackArray, bytesResponse);
if( checkI2CErrorcode(errorcode) == -1 || err == -1 )
return -1;
//Delay for 2 ms to allow the EEPROM to finish writing.
//Re-read the user memory.
usleep(2000);
//Setting up I2C command
address = (uint8)(0xA0); //Address : h0xA0 is the address for EEPROM
numBytesToSend = 1; //NumI2CByteToSend : 1 byte for the EEPROM address
numBytesToReceive = 64; //NumI2CBytesToReceive : getting 64 bytes starting at EEPROM address specified in I2CByte0
bytesCommand[0] = 0; //I2CByte0 : Memory Address, starting at address 0 (User Area)
//Performing I2C low-level call
err = I2C(hDevice, options, speedAdjust, sdaPinNum, sclPinNum, address, numBytesToSend, numBytesToReceive, bytesCommand, &errorcode, ackArray, bytesResponse);
if( checkI2CErrorcode(errorcode) == -1 || err == -1 )
return -1;
//Display the first 4 elements.
printf("Read User Mem [0-3] = %d, %d, %d, %d\n", bytesResponse[0], bytesResponse[1], bytesResponse[2], bytesResponse[3]);
return err;
}

View File

@@ -0,0 +1,223 @@
//Author: LabJack
//May 25, 2011
//This example program makes 3 SingleIO low-level function calls. One call sets
//DAC0 to 2.500 V. One call reads voltage from AIN0. One call reads the
//temperature from the internal temperature sensor. Control firmware version
//1.03 and above needed for SingleIO.
#include "ue9.h"
int singleIO_AV_example(HANDLE handle, ue9CalibrationInfo *caliInfo);
int main(int argc, char **argv)
{
HANDLE hDevice;
ue9CalibrationInfo caliInfo;
//Opening first found UE9 over USB
if( (hDevice = openUSBConnection(-1)) == NULL )
goto done;
//Getting calibration information from UE9
if( getCalibrationInfo(hDevice, &caliInfo) < 0 )
goto close;
singleIO_AV_example(hDevice, &caliInfo);
close:
closeUSBConnection(hDevice);
done:
return 0;
}
//Sends 3 SingleIO low-level commands to set DAC0, read AIN0 and read the
//temperature
int singleIO_AV_example(HANDLE hDevice, ue9CalibrationInfo *caliInfo)
{
uint8 sendBuff[8], recBuff[8], ainResolution;
uint16 bytesVoltage, bytesTemperature;
int sendChars, recChars;
double voltage;
double temperature; //in Kelvins
ainResolution = 12;
//ainResolution = 18; //high-res mode for UE9 Pro only
/* Setting voltage of DAC0 to 2.500 V */
//if( getDacBinVoltUncalibrated(0, 2.500, &bytesVoltage) < 0 )
if( getDacBinVoltCalibrated(caliInfo, 0, 2.500, &bytesVoltage) < 0 )
return -1;
sendBuff[1] = (uint8)(0xA3); //Command byte
sendBuff[2] = (uint8)(0x05); //IOType = 5 (analog out)
sendBuff[3] = (uint8)(0x00); //Channel = 0 (DAC0)
sendBuff[4] = (uint8)( bytesVoltage & (0x00FF) ); //low bits of voltage
sendBuff[5] = (uint8)( bytesVoltage /256 ) + 192; //high bits of voltage
//(bit 7 : Enable,
// bit 6: Update)
sendBuff[6] = (uint8)(0x00); //Settling time - does not apply to analog output
sendBuff[7] = (uint8)(0x00); //Reserved
sendBuff[0] = normalChecksum8(sendBuff, 8);
//Sending command to UE9
sendChars = LJUSB_Write(hDevice, sendBuff, 8);
if( sendChars < 8 )
{
if( sendChars == 0 )
goto sendError0;
else
goto sendError1;
}
//Reading response from UE9
recChars = LJUSB_Read(hDevice, recBuff, 8);
if( recChars < 8 )
{
if( recChars == 0 )
goto recvError0;
else
goto recvError1;
}
if( (uint8)(normalChecksum8(recBuff, 8)) != recBuff[0] )
goto chksumError;
if( recBuff[1] != (uint8)(0xA3) )
goto commandByteError;
if( recBuff[2] != (uint8)(0x05) )
goto IOTypeError;
if( recBuff[3] != 0 )
goto channelError;
printf("Set DAC0 voltage to 2.500 V ...\n");
/* Reading voltage from AIN0 */
sendBuff[1] = (uint8)(0xA3); //Command byte
sendBuff[2] = (uint8)(0x04); //IOType = 4 (analog in)
sendBuff[3] = (uint8)(0x00); //Channel = 0 (AIN0)
sendBuff[4] = (uint8)(0x00); //BipGain (Bip = unipolar, Gain = 1)
sendBuff[5] = ainResolution; //Resolution
sendBuff[6] = (uint8)(0x00); //SettlingTime = 0
sendBuff[7] = (uint8)(0x00); //Reserved
sendBuff[0] = normalChecksum8(sendBuff, 8);
//Sending command to UE9
sendChars = LJUSB_Write(hDevice, sendBuff, 8);
if( sendChars < 8 )
{
if( sendChars == 0 )
goto sendError0;
else
goto sendError1;
}
//Reading response from UE9
recChars = LJUSB_Read(hDevice, recBuff, 8);
if( recChars < 8 )
{
if( recChars == 0 )
goto recvError0;
else
goto recvError1;
}
if( (uint8)(normalChecksum8(recBuff, 8)) != recBuff[0] )
goto chksumError;
if( recBuff[1] != (uint8)(0xA3) )
goto commandByteError;
if( recBuff[2] != (uint8)(0x04) )
goto IOTypeError;
if( recBuff[3] != 0 )
goto channelError;
bytesVoltage = recBuff[5] + recBuff[6]*256;
//if( getAinVoltUncalibrated(sendBuff[4], ainResolution, bytesVoltage, &voltage) < 0 )
if( getAinVoltCalibrated(caliInfo, sendBuff[4], ainResolution, bytesVoltage, &voltage) < 0 )
return -1;
printf("Voltage read from AI0: %.4f V\n", voltage);
/* Reading temperature from internal temperature sensor */
sendBuff[1] = (uint8)(0xA3); //Command byte
sendBuff[2] = (uint8)(0x04); //IOType = 4 (analog in)
sendBuff[3] = (uint8)(0x85); //Channel = 133 (tempSensor)
sendBuff[4] = (uint8)(0x00); //Gain = 1 (Bip does not apply)
sendBuff[5] = (uint8)(0x0C); //Resolution = 12
sendBuff[6] = (uint8)(0x00); //SettlingTime = 0
sendBuff[7] = (uint8)(0x00); //Reserved
sendBuff[0] = normalChecksum8(sendBuff, 8);
//Sending command to UE9
sendChars = LJUSB_Write(hDevice, sendBuff, 8);
if( sendChars < 8 )
{
if( sendChars == 0 )
goto sendError0;
else
goto sendError1;
}
//Reading response from UE9
recChars = LJUSB_Read(hDevice, recBuff, 8);
if( recChars < 8 )
{
if( recChars == 0 )
goto recvError0;
else
goto recvError1;
}
if( (uint8)(normalChecksum8(recBuff, 8)) != recBuff[0] )
goto chksumError;
if( recBuff[1] != (uint8)(0xA3) )
goto commandByteError;
if( recBuff[2] != (uint8)(0x04) )
goto IOTypeError;
if( recBuff[3] != (uint8)(0x85) )
goto channelError;
bytesTemperature = recBuff[5] + recBuff[6]*256;
//Assuming high power level
//if( getTempKUncalibrated(0, bytesTemperature, &temperature) < 0 )
if( getTempKCalibrated(caliInfo, 0, bytesTemperature, &temperature) < 0 )
return -1;
printf("Temperature read internal temperature sensor (channel 133): %.1f K\n\n", temperature);
return 0;
//error printouts
sendError0:
printf("Error : write failed\n");
return -1;
sendError1:
printf("Error : did not write all of the buffer\n");
return -1;
recvError0:
printf("Error : read failed\n");
return -1;
recvError1:
printf("Error : did not read all of the buffer\n");
return -1;
chksumError:
printf("Error : read buffer has bad checksum\n");
return -1;
commandByteError:
printf("Error : read buffer has wrong command byte\n");
return -1;
IOTypeError:
printf("Error : read buffer has wrong IOType\n");
return -1;
channelError:
printf("Error : read buffer has wrong channel\n");
return -1;
}

View File

@@ -0,0 +1,466 @@
//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;
}

View File

@@ -0,0 +1,230 @@
//Author: LabJack
//May 25, 2011
//This example program calls the TimerCounter function, and reads both counters
//and enables 2 timers with PWM output. Connect FIO0/FIO1 to FIO2/FIO3 to have
//the counter read something. After 1 second the counters' counts are outputted
//to the screen.
#include <unistd.h>
#include "ue9.h"
int timerCounter_example(HANDLE hDevice);
int errorCheck(uint8 *buffer);
int main(int argc, char **argv)
{
HANDLE hDevice;
//Opening first found UE9 over USB
if( (hDevice = openUSBConnection(-1)) == NULL )
return 1;
timerCounter_example(hDevice);
closeUSBConnection(hDevice);
return 0;
}
//Sends a TimerCounter low-level command to enable and set two Timers
//(FIO0, FIO1) and two Counters (FIO2, FIO3), then sends a TimerCounter
//command a second later to read from the Counters and last sends a
//TimerCounter command to disable the Timers and Counters.
int timerCounter_example(HANDLE hDevice)
{
//Note: If using the quadrature input timer mode, the returned 32 bit
// integer is signed
uint8 sendBuff[30], recBuff[40];
uint32 cnt;
int sendChars, recChars, i;
//Enable timers and counters
sendBuff[1] = (uint8)(0xF8); //Command byte
sendBuff[2] = (uint8)(0x0C); //Number of data words
sendBuff[3] = (uint8)(0x18); //Extended command number
sendBuff[6] = (uint8)(0x03); //TimerClockDivisor = 3
sendBuff[7] = (uint8)(0x9A); //Updating: 2 Timers enabled, Counter0 and
//Counter1 enabled
sendBuff[8] = (uint8)(0x00); //TimerClockConfig = 750 kHz (if using system
//clock, call ControlConfig first and set the
//PowerLevel to a fixed state)
sendBuff[9] = (uint8)(0x00); //UpdateReset - not resetting anything
sendBuff[10] = (uint8)(0x00); //Timer0Mode = 16-Bit PWM
//Timer0Value = 32768
sendBuff[11] = (uint8)(0x00); //Timer0Value (low byte)
sendBuff[12] = (uint8)(0x80); //Timer0Value (high byte)
//Timer1Value = 32768
sendBuff[13] = (uint8)(0x01); //Timer1Mode = 8-Bit PWM
sendBuff[14] = (uint8)(0x00); //Timer1Value (low byte)
sendBuff[15] = (uint8)(0x80); //Timer1Value (high byte)
//timer modes and values for timers 2 - 5, which are not enabled
for( i = 16; i < 28; i++ )
sendBuff[i] = (uint8)(0x00);
sendBuff[28] = (uint8)(0x00); //Counter0Mode (pass 0)
sendBuff[29] = (uint8)(0x00); //Counter1Mode (pass 0)
extendedChecksum(sendBuff, 30);
//Sending command to UE9
sendChars = LJUSB_Write(hDevice, sendBuff, 30);
if( sendChars < 30 )
{
if( sendChars == 0 )
goto writeError0;
else
goto writeError1;
}
//Reading response from UE9
recChars = LJUSB_Read(hDevice, recBuff, 40);
if( recChars < 40 )
{
if( recChars == 0 )
goto readError0;
else
goto readError1;
}
if( errorCheck(recBuff) == -1 )
return -1;
//Wait 1 sec and read counters
sleep(1);
sendBuff[1] = (uint8)(0xF8); //Command bytes
sendBuff[2] = (uint8)(0x0C); //Number of data words
sendBuff[3] = (uint8)(0x18); //Extended command number
//Not updating our configuration. We only want to read the counter values.
for( i = 6; i < 30; i++ )
sendBuff[i] = (uint8)(0x00);
extendedChecksum(sendBuff, 30);
//Sending command to UE9
sendChars = LJUSB_Write(hDevice, sendBuff, 30);
if( sendChars < 30 )
{
if( sendChars == 0 )
goto writeError0;
else
goto writeError1;
}
//Reading response from UE9
recChars = LJUSB_Read(hDevice, recBuff, 40);
if( recChars < 40 )
{
if( recChars == 0 )
goto readError0;
else
goto readError1;
}
if( errorCheck(recBuff) == -1 )
return -1;
printf("Current counts from counters after 1 second:\n");
for( i = 0; i < 2; i++ )
{
cnt = (unsigned int)recBuff[32 + 4*i] + (unsigned int)recBuff[33 + 4*i]*256 +
(unsigned int)recBuff[34 + 4*i]*65536 + (unsigned int)recBuff[35 + 4*i]*16777216;
printf(" Counter%d : %u\n", i, cnt);
}
//Disable timers and counters
sendBuff[1] = (uint8)(0xF8); //Command bytes
sendBuff[2] = (uint8)(0x0C); //Number of data words
sendBuff[3] = (uint8)(0x18); //Extended command number
sendBuff[6] = (uint8)(0x00); //TimerClockDivisor = 0
sendBuff[7] = (uint8)(0x80); //Updating: 0 Timers enabled, Counter0 and
//Counter1 disabled
//Setting bytes 8 - 30 to zero since nothing is enabled
for( i = 8; i < 30; i++ )
sendBuff[i] = (uint8)(0x00);
extendedChecksum(sendBuff, 30);
//Sending command to UE9
sendChars = LJUSB_Write(hDevice, sendBuff, 30);
if( sendChars < 30 )
{
if( sendChars == 0 )
goto writeError0;
else
goto writeError1;
}
//Reading response from UE9
recChars = LJUSB_Read(hDevice, recBuff, 40);
if( recChars < 40 )
{
if( recChars == 0 )
goto readError0;
else
goto readError1;
}
if( errorCheck(recBuff) == -1 )
return -1;
return 0;
writeError0:
printf("Error : write failed\n");
return -1;
writeError1:
printf("Error : did not write all of the buffer\n");
return -1;
readError0:
printf("Error : read failed\n");
return -1;
readError1:
printf("Error : did not read all of the buffer\n");
return -1;
}
int errorCheck(uint8 *buffer)
{
uint16 checksumTotal;
checksumTotal = extendedChecksum16(buffer, 40);
if( (uint8)((checksumTotal / 256) & 0xFF) != buffer[5] )
{
printf("Error : read buffer has bad checksum16(MSB)\n");
return -1;
}
if( (uint8)(checksumTotal & 0xFF) != buffer[4] )
{
printf("Error : read buffer has bad checksum16(LSB)\n");
return -1;
}
if( extendedChecksum8(buffer) != buffer[0] )
{
printf("Error : read buffer has bad checksum8\n");
return -1;
}
if( buffer[1] != (uint8)(0xF8) || buffer[2] != (uint8)(0x11) || buffer[3] != (uint8)(0x18) )
{
printf("Error : read buffer has wrong command bytes \n");
return -1;
}
if( buffer[6] != 0 )
{
printf("Errorcode (byte 6): %d\n", (unsigned int)buffer[6]);
return -1;
}
return 0;
}

View File

@@ -0,0 +1,194 @@
//Author : LabJack
//May 25, 2011
//This example demonstrates how to write and read some or all analog and digital
//I/O. It records the time for 1000 iterations and divides by 1000, to allow
//measurement of the basic command/response communication times. These times
//should be comparable to the Windows command/response communication times
//documented in Section 3.1 of the UE9 User's Guide.
#include "ue9.h"
int allIO(HANDLE hDevice, ue9CalibrationInfo *caliInfo);
int main(int argc, char **argv)
{
HANDLE hDevice;
ue9CalibrationInfo caliInfo;
//Opening first found UE9 over USB
if( (hDevice = openUSBConnection(-1)) == NULL )
goto done;
//Getting calibration information from UE9
if( getCalibrationInfo(hDevice, &caliInfo) < 0 )
goto close;
allIO(hDevice, &caliInfo);
close:
closeUSBConnection(hDevice);
done:
return 0;
}
//Sends 1000 Feedback low-level commands to read digital IO and analog inputs.
//On the first send, the following are set: DAC0 to 2.5 volts, DAC1 to 3.5
//volts, and digital IOs to inputs.
int allIO(HANDLE hDevice, ue9CalibrationInfo *caliInfo)
{
uint8 sendBuff[34], recBuff[64], settlingTime;
uint8 numChannels; //Number of AIN channels, 0-16.
uint16 checksumTotal, bytesVoltage, ainMask;
int sendChars, recChars, i, j;
int initialize; //boolean to init. DAC and digital IO settings
int numIterations, valueDIPort;
long time, ainResolution;
double valueAIN[16];
numIterations = 1000;
initialize = 1;
time = 0;
numChannels = 8;
ainResolution = 12;
for( i = 0; i < 16; i++ )
valueAIN[i] = 9999.0;
settlingTime = 0;
ainMask = pow(2.0, numChannels) - 1;
sendBuff[1] = (uint8)(0xF8); //Command byte
sendBuff[2] = (uint8)(0x0E); //Number of data words
sendBuff[3] = (uint8)(0x00); //Extended command number
sendBuff[6] = 255; //FIOMask : setting the mask of all FIOs
sendBuff[7] = 0; //FIODir : setting all FIO directions to input
sendBuff[8] = 0; //FIOState : all FIO directions are input, so
// state writes do not apply
sendBuff[9] = 255; //EIOMask : setting the mask of all EIOs
sendBuff[10] = 0; //EIODir : setting all EIO directions to input
sendBuff[11] = 0; //EIOState : all EIO directions are input, so
// state writes do not apply
sendBuff[12] = 15; //CIOMask : setting the mask of all CIOs
sendBuff[13] = 0; //CIODirState : setting all CIO directions to input,
// state writes do not apply
sendBuff[14] = 7; //MIOMask : setting the mask of all MIOs
sendBuff[15] = 0; //MIODirState : setting all MIO directions to input,
// state writes do not apply
//Getting binary DAC0 value of 2.5 volts
if( getDacBinVoltCalibrated(caliInfo, 0, 2.500, &bytesVoltage) < 0 )
return -1;
//Setting the voltage of DAC0 to 2.5
sendBuff[16] = (uint8)(bytesVoltage & 255); //low bits of DAC0
sendBuff[17] = (uint8)(bytesVoltage/256) + 192; //high bits of DAC0
//(bit 7 : Enable,
// bit 6: Update)
//Getting binary DAC1 value of 3.5 volts
if( getDacBinVoltCalibrated(caliInfo, 1, 3.500, &bytesVoltage) < 0 )
return -1;
//Setting the voltage of DAC1 to 3.5 volts
sendBuff[18] = (uint8)(bytesVoltage & 255); //low bits of DAC1
sendBuff[19] = (uint8)(bytesVoltage/256) + 192; //high bits of DAC1
//(bit 7 : Enable,
// bit 6: Update)
//AINMask - reading the number of AINs specified by numChannels
sendBuff[20] = ainMask & 255; //AINMask (low byte)
sendBuff[21] = ainMask/256; //AINMask (high byte)
sendBuff[22] = 14; //AIN14ChannelNumber : setting to channel 14
sendBuff[23] = 15; //AIN15ChannelNumber : setting to channel 15
sendBuff[24] = ainResolution; //Resolution : Resolution specified by
// ainResolution
sendBuff[25] = settlingTime; //SettlingTime
//Setting all BipGains (Gain = 1, Bipolar = 1)
for( i = 26; i < 34; i++ )
sendBuff[i] = (uint8)(0x00);
extendedChecksum(sendBuff, 34);
time = getTickCount();
for( i = 0; i < numIterations; i++ )
{
//Sending command to UE9
sendChars = LJUSB_Write(hDevice, sendBuff, 34);
if( sendChars < 34 )
{
if( sendChars == 0 )
printf("Feedback error (Iteration %d) : write failed\n", i);
else
printf("Feedback error (Iteration %d) : did not write all of the buffer\n", i);
return -1;
}
//Reading response from UE9
recChars = LJUSB_Read(hDevice, recBuff, 64);
if( recChars < 64 )
{
if( recChars == 0 )
printf("Feedback error (Iteration %d) : read failed\n", i);
else
printf("Feedback error (Iteration %d) : did not read all of the buffer\n", i);
return -1;
}
checksumTotal = extendedChecksum16(recBuff, 64);
if( (uint8)((checksumTotal / 256) & 0xff) != recBuff[5] )
{
printf("Feedback error (Iteration %d) : read buffer has bad checksum16(MSB)\n", i);
return -1;
}
if( (uint8)(checksumTotal & 255) != recBuff[4] )
{
printf("Feedback error (Iteration %d) : read buffer has bad checksum16(LSB)\n", i);
return -1;
}
if( extendedChecksum8(recBuff) != recBuff[0] )
{
printf("Feedback error (Iteration %d) : read buffer has bad checksum8\n", i);
return -1;
}
if( recBuff[1] != (uint8)(0xF8) || recBuff[2] != (uint8)(0x1D) || recBuff[3] != (uint8)(0x00) )
{
printf("Feedback error (Iteration %d) : read buffer has wrong command bytes\n", i);
return -1;
}
for( j = 0; j < numChannels && j < 16; j++ )
getAinVoltCalibrated(caliInfo, 0x00, (uint8)ainResolution, recBuff[12 + j*2] + recBuff[13 + j*2]*256, &valueAIN[j]);
valueDIPort = recBuff[7] + recBuff[9]*256 + (recBuff[10] & 15)*65536 + (recBuff[11] & 7)*1048576;
if( initialize == 1 )
{
//Unsetting digital IO bit masks since we only want to read states now
sendBuff[6] = 0; //FIOMask
sendBuff[9] = 0; //EIOMask
sendBuff[12] = 0; //CIOMask
sendBuff[14] = 0; //MIOMask
//Turning off Update bit of DACs
sendBuff[17] = sendBuff[17] - 64; //high bits of DAC0
sendBuff[19] = sendBuff[19] - 64; //high bits of DAC1
extendedChecksum(sendBuff, 34);
initialize = 0;
}
}
time = getTickCount() - time;
printf("Milleseconds per iteration = %.3f\n", (double)time / (double)numIterations);
printf("\nDigital Input (FIO0-7, EIO0-7, CIO0-3, MIO0-2) = %d\n",valueDIPort);
printf("\nAIN readings from last iteration:\n");
for( j = 0; j < numChannels; j++ )
printf("%.3f\n", valueAIN[j]);
return 0;
}

View File

@@ -0,0 +1,197 @@
#! /bin/bash
RULES=10-labjack.rules
RULES_DEST_PRIMARY=/lib/udev/rules.d
RULES_DEST_ALTERNATE=/etc/udev/rules.d
GROUP=adm
SUPPORT_EMAIL=support@labjack.com
TRUE=1
FALSE=0
IS_SUCCESS=$TRUE
# Assume these are unneeded until otherwise
NEED_RECONNECT=$FALSE
NEED_RESTART=$FALSE
NEED_RELOG=$FALSE
NO_RULES=$FALSE
NO_RULES_ERR=2
go ()
{
$@
ret=$?
if [ $ret -ne 0 ]; then
echo "Error, please make sure you are running this script as:"
echo " $ sudo $0"
echo "If you are still having problems, please contact LabJack support: <$SUPPORT_EMAIL>"
exit $ret
fi
}
success ()
{
e=0
if [ $IS_SUCCESS -eq $TRUE ]; then
echo "Install finished. Thanks for choosing LabJack."
fi
if [ $NEED_RECONNECT -eq $TRUE ]; then
echo "If you have any LabJack devices connected, please disconnect and reconnect them now for device rule changes to take effect."
fi
if [ $NO_RULES -eq $TRUE ]; then
echo "No udev rules directory found. Searched for $RULES_DEST_PRIMARY, $RULES_DEST_ALTERNATE."
echo "Please copy $RULES to your device rules directory and reload the rules or contact LabJack support for assistence: <$SUPPORT_EMAIL>"
let e=e+$NO_RULES_ERR
fi
if [ $NEED_RESTART -eq $TRUE ]; then
echo "Please manually restart the device rules or restart your computer now."
elif [ $NEED_RELOG -eq $TRUE ]; then
echo "Please log off and log back in for the group changes to take effect. To confirm the group changes have taken effect, enter the command:"
echo " $ groups"
echo "and make sure $GROUP is in the list. (You probably have to log out of your entire account, not just your shell.)"
fi
exit $e
}
##############################
# Exodriver make and install #
##############################
go cd liblabjackusb/
echo "Making.."
go make clean
go make
echo "Installing.."
go make install
# Mac OS doesn't need rules config
if [ `uname -s` == "Darwin" ]; then
success
fi
go cd ../
#################
# LabJack Rules #
#################
if [ -d $RULES_DEST_PRIMARY ]; then
RULES_DEST=$RULES_DEST_PRIMARY
OLD_FILE_TO_REMOVE=$RULES_DEST_ALTERNATE/$RULES
if [ -f $OLD_FILE_TO_REMOVE ]; then
rm $OLD_FILE_TO_REMOVE
fi
elif [ -d $RULES_DEST_ALTERNATE ]; then
RULES_DEST=$RULES_DEST_ALTERNATE
else
NO_RULES=$TRUE
fi
if [ $NO_RULES -ne $TRUE ]; then
echo "Adding $RULES to $RULES_DEST.."
go cp -f $RULES $RULES_DEST
NEED_RECONNECT=$TRUE
fi
#####################
# Restart the Rules #
#####################
echo -n "Restarting the rules.."
udevadm control --reload-rules 2> /dev/null
ret=$?
if [ $ret -ne 0 ]; then
udevadm control --reload_rules 2> /dev/null
ret=$?
fi
if [ $ret -ne 0 ]; then
/etc/init.d/udev-post reload 2> /dev/null
ret=$?
fi
if [ $ret -ne 0 ]; then
udevstart 2> /dev/null
ret=$?
fi
if [ $ret -ne 0 ]; then
NEED_RESTART=$TRUE
echo " cound not restart the rules."
else
echo # Finishes previous echo -n
fi
#####################
# Add user to group #
#####################
user=`logname`
in_group=$FALSE
for g in `id -nG $user`; do
if [ "$g" == "$GROUP" ]; then
in_group=$TRUE
break
fi
done
if [ $in_group -eq $TRUE ]; then
# Make sure the user is logged into the adm group
current_groups=$FALSE
for g in `groups $user`; do
if [ "$g" == "$GROUP" ]; then
current_groups=$TRUE
break
fi
done
if [ $current_groups -ne $TRUE ]; then
NEED_RELOG=$TRUE
fi
success
fi
echo "Adding $user to the $GROUP group.."
NEED_RELOG=$TRUE
declare -a tasks=("add/create a group named $GROUP ($ groupadd -f $GROUP)" "add your user account to the group named $GROUP ($ usermod -a -G $GROUP $user)")
print_tasks_if_needed()
{
ret=$?
if [ $ret -ne 0 ]; then
echo
echo "It looks like this installer failed with only a few task(s) left to complete."
echo "LabJack developed this installer on Ubuntu/Debian Linux, so if you are running"
echo "Ubuntu/Debian, please contact LabJack. However, if you are running a"
echo "different distribution of Linux, it is likely that your distribution varies"
echo "enough to make these last task(s) fail."
echo
echo "You can search the internet for how to complete the following task(s) on your"
echo "distribution of Linux:"
for n in "${tasks[@]}"; do
echo " - $n"
done
echo
echo "Where the Ubuntu/Debian commands for the tasks are in parenthesis."
echo
echo "Once these tasks are complete, your installation of Exodriver will be complete."
echo
echo "If you are on a common distribution of Linux or if you are not sure how to"
echo "complete the above task(s), please contact LabJack support. If your"
echo "distribution of Linux is old, consider upgrading to see if that solves the"
echo "problem."
echo
echo "LabJack support: support@labjack.com"
echo
echo "Please also follow any following instructions."
echo
IS_SUCCESS=$FALSE
success
fi
}
groupadd -f $GROUP
print_tasks_if_needed
unset tasks[0]
usermod -a -G $GROUP $user
print_tasks_if_needed
unset tasks[1]
success

View File

@@ -0,0 +1,54 @@
#
# Makefile for liblabjackusb
#
#
UNAME = $(shell uname -s)
VERSION = 2.5.3
DESTINATION = /usr/local/lib
HEADER = labjackusb.h
HEADER_DESTINATION = /usr/local/include
LIBFLAGS = -lusb-1.0 -lc
ADD_LDCONFIG_PATH = ./add_ldconfig_path.sh
ifeq ($(UNAME),Darwin)
#Mac OS X operating system macros
TARGET = liblabjackusb.dylib
# Build for only the host architecture
ARCHFLAGS =
# Build for 32- and 64-bit Intel architectures
#ARCHFLAGS = -arch i386 -arch x86_64
# Build for multiple architectures
#ARCHFLAGS = -arch i386 -arch x86_64 -arch ppc
COMPILE = libtool -dynamic -o $(TARGET) -install_name $(TARGET) -current_version $(VERSION) -compatibility_version $(VERSION) labjackusb.o $(LIBFLAGS)
else
#Linux operating system macros
TARGET = liblabjackusb.so.$(VERSION)
# Build for only the host architecture
ARCHFLAGS =
COMPILE = $(CC) -shared -Wl,-soname,liblabjackusb.so -o $(TARGET) labjackusb.o $(LIBFLAGS)
endif
CFLAGS += -fPIC -g -Wall $(ARCHFLAGS)
%.o: %.c
$(CC) $(CFLAGS) -c $<
all: $(TARGET)
$(TARGET): labjackusb.o $(HEADER)
$(COMPILE)
install: $(TARGET)
test -z $(DESTINATION) || mkdir -p $(DESTINATION)
install $(TARGET) $(DESTINATION)
test -z $(HEADER_DESTINATION) || mkdir -p $(HEADER_DESTINATION)
install $(HEADER) $(HEADER_DESTINATION)
ifeq ($(UNAME),Linux)
@$(ADD_LDCONFIG_PATH)
ldconfig
endif
clean:
rm -f $(TARGET) *.o *~

View File

@@ -0,0 +1,18 @@
#! /bin/bash
ldconfig_file=/etc/ld.so.conf
path=/usr/local/lib
TRUE=0
path_exists=1
for line in `cat $ldconfig_file`; do
if [ $line == $path ]; then
path_exists=$TRUE
fi
done
if [ $path_exists -ne $TRUE ]; then
echo "$path >> $ldconfig_file"
echo $path >> $ldconfig_file
fi

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,311 @@
//-----------------------------------------------------------------------------
//
// labjackusb.h
//
// Header file for the labjackusb library.
//
// support@labjack.com
//
//-----------------------------------------------------------------------------
//
// Version History
//
// 0.90 - Initial release (LJUSB_AbortPipe not supported)
//
// 1.00 - Added LJUSB_SetBulkReadTimeout
//
// 1.10 - Changed the HANDLE to a void * (previously int)
// - Added LJUSB_GetLibraryVersion
// - Removed UE9_PIPE_EP2_OUT
// - Changed the values of the pipes (incremented by 1)
// - Removed function LJUSB_SetBulkReadTimeout
// - Changed LJUSB_LINUX_DRIVER_VERSION define name to
// LJUSB_LINUX_LIBRARY_VERSION
//
// 2.00 - Re-implemented library using libusb 1.0. No longer requires LabJack
// kernel module.
// - Replaced define names U3_PIPE_EP1_IN and U3_PIPE_EP2_IN with
// U3_PIPE_EP2_IN and U3_PIPE_EP3_IN
// - Added U6 support
//
// 2.01 - Added U12 support
// - Added Wireless Bridge support
//
// 2.02 - Buxfix release
//
// 2.03 - Don't print libusb timeout errors on interupt transfers
//
// 2.04 - Removed exit calls
// - Now using unique a libusb session instead of the default
// - Setting errno more often when libusb errors occur
// - Changed guard define to LABJACKUSB_H_
// - Changed LJUSB_GetDevCount return data type to unsigned int
// - Moved LJ_VENDOR_ID to the header file so it's public
//
// 2.05 - Updated Wireless bridge support for bulk transfers
// - Updated Wireless bridge product ID to 1000
// - Fixed some compiler warnings
// - Renamed LJUSB_LINUX_LIBRARY_VERSION define to LJUSB_LIBRARY_VERSION
// - Changed LJUSB_Write/Read/Stream to return 0 on error instead of -1
// - Changed LJUSB_GetDevCounts return data type unsigned int
// - Changed LJUSB_GetDevCounts to return all products counted instead
// of 0
// - Added LJUSB_WriteTO, LJUSB_ReadTO and LJUSB_StreamTO functions
// - Added LJUSB_GetDeviceDescriptorReleaseNumber function
// - Added LJUSB_GetHIDReportDescriptor function for U12
// - Now using minor versions properly in LJUSB_LIBRARY_VERSION define
// - Renamed DEBUG define to LJ_DEBUG in source
// - Made global variables static
// - Replaced LJUSB_IsHandleValid checks with LJUSB_isNullHandle to
// improve LJUSB_Write/Read/Stream speeds
// - Initial T7 support
// - Initial Digit support
// - Added LJUSB_ResetConnection function.
// 2.0503 - Fixed open calls to not steal handles from other processes on
// Linux.
// - libusb error prints are silenced when LJ_DEBUG is not enabled.
// - Added revision number to library version number. The float version
// number 2.0503 is equivalent to 2.5.3 (major.minor.revision).
//-----------------------------------------------------------------------------
//
#ifndef LABJACKUSB_H_
#define LABJACKUSB_H_
#define LJUSB_LIBRARY_VERSION 2.0503f
#include <stdbool.h>
typedef void * HANDLE;
typedef unsigned int UINT;
typedef unsigned char BYTE;
//Vendor ID
#define LJ_VENDOR_ID 0x0cd5
//Product IDs
#define UE9_PRODUCT_ID 9
#define U3_PRODUCT_ID 3
#define U6_PRODUCT_ID 6
#define U12_PRODUCT_ID 1
#define BRIDGE_PRODUCT_ID 1000
#define T7_PRODUCT_ID 7
#define DIGIT_PRODUCT_ID 200
#define UNUSED_PRODUCT_ID -1
//UE9 pipes to read/write through
#define UE9_PIPE_EP1_OUT 1
#define UE9_PIPE_EP1_IN 0x81
#define UE9_PIPE_EP2_IN 0x82 //Stream Endpoint
//U3 pipes to read/write through
#define U3_PIPE_EP1_OUT 1
#define U3_PIPE_EP2_IN 0x82
#define U3_PIPE_EP3_IN 0x83 //Stream Endpoint
//U6 pipes to read/write through
#define U6_PIPE_EP1_OUT 1
#define U6_PIPE_EP2_IN 0x82
#define U6_PIPE_EP3_IN 0x83 //Stream Endpoint
//U12 pipes to read/write through
#define U12_PIPE_EP1_IN 0x81
#define U12_PIPE_EP2_OUT 2
#define U12_PIPE_EP0 0 //Control endpoint
//Wireless bridge pipes to read/write through
#define BRIDGE_PIPE_EP1_OUT 1
#define BRIDGE_PIPE_EP2_IN 0x82
#define BRIDGE_PIPE_EP3_IN 0x83 //Spontaneous Endpoint
//T7 pipes to read/write through
#define T7_PIPE_EP1_OUT 1
#define T7_PIPE_EP2_IN 0x82
#define T7_PIPE_EP3_IN 0x83 //Stream Endpoint
//Digit pipes to read/write through
#define DIGIT_PIPE_EP1_OUT 1
#define DIGIT_PIPE_EP2_IN 0x82
#ifdef __cplusplus
extern "C"{
#endif
float LJUSB_GetLibraryVersion(void);
//Returns the labjackusb library version number.
unsigned int LJUSB_GetDevCount(unsigned long ProductID);
// Returns the total number of LabJack USB devices connected.
// ProductID = The product ID of the devices you want to get the count of.
unsigned int LJUSB_GetDevCounts(UINT *productCounts, UINT * productIds, UINT n);
// Returns the count for n products.
// productCounts = Array of size n that holds the count
// productIds = Array of size n which holds the product IDs.
// n = The size of the arrays.
// For example
// uint productCounts[10], productIds[10];
// r = LJUSB_GetDevCounts(productCounts, productIds, 10);
// would return arrays that may look like
// {1, 2, 3, 4, 5, 6, 7, 0, 0, 0}
// {3, 6, 9, 1, 1000, 7, 200, 0, 0, 0}
// which means there are
// 1 U3
// 2 U6s
// 3 UE9s
// 4 U12s
// 5 SkyMote Bridges
// 6 T7s
// 7 Digits
// connected.
int LJUSB_OpenAllDevices(HANDLE* devHandles, UINT* productIds, UINT maxDevices);
// Opens all LabJack devices up to a maximum of maxDevices.
// devHandles = An array of handles with a size of maxDevices
// productIds = An array of product IDs with a size of maxDevices
// maxDevices = Maximum number of devices to open.
// Returns the number of devices actually opened, or -1 if a tragically bad
// error occurs. The structure of the arrays is similar to that of
// LJUSB_GetDevCounts above. A simple example would be:
// {2341234, 55343, 0, 0, ...}
// {3, 1000, 0, 0, ...}
// where the return value is 2. 2341234 is the handle for a U3, and 55343 is the
// handle for a SkyMote Bridge.
HANDLE LJUSB_OpenDevice(UINT DevNum, unsigned int dwReserved, unsigned long ProductID);
// Obtains a handle for a LabJack USB device. Returns NULL if there is an
// error.
// If the device is already open, NULL is returned and errno is set to EBUSY.
// DevNum = The device number of the LabJack USB device you want to open. For
// example, if there is one device connected, set DevNum = 1. If you
// have two devices connected, then set DevNum = 1, or DevNum = 2.
// dwReserved = Not used, set to 0.
// ProductID = The product ID of the LabJack USB device. Currently the U3, U6,
// and UE9 are supported.
bool LJUSB_ResetConnection(HANDLE hDevice);
// Performs a USB port reset to reinitialize a device.
// Returns true on success, or false on error and errno is set.
// Note that this function is experimental and currently may not work.
// If this function fails, hDevice is no longer valid (you should close it)
// and you should re-open the device.
// hDevice = The handle for your device
unsigned long LJUSB_Write(HANDLE hDevice, BYTE *pBuff, unsigned long count);
// Writes to a device with a 1 second timeout. If the timeout time elapses and
// no data is transferred the USB request is aborted and the call returns.
// Returns the number of bytes written, or 0 on error and errno is set.
// hDevice = The handle for your device
// pBuff = The buffer to be written to the device.
// count = The number of bytes to write.
// This function replaces the deprecated LJUSB_BulkWrite, which required the
// endpoint.
unsigned long LJUSB_Read(HANDLE hDevice, BYTE *pBuff, unsigned long count);
// Reads from a device with a 1 second timeout. If the timeout time elapses and
// no data is transferred the USB request is aborted and the call returns.
// Returns the number of bytes read, or 0 on error and errno is set.
// hDevice = The handle for your device
// pBuff = The buffer to be filled in with bytes from the device.
// count = The number of bytes expected to be read.
// This function replaces the deprecated LJUSB_BulkRead, which required the
// endpoint.
unsigned long LJUSB_Stream(HANDLE hDevice, BYTE *pBuff, unsigned long count);
// Reads from a device's stream interface with a 1 second timeout. If the
// timeout time elapses and no data is transferred the USB request is aborted
// and the call returns. Returns the number of bytes written, or 0 on error and
// errno is set.
// hDevice = The handle for your device
// pBuff = The buffer to be filled in with bytes from the device.
// count = The number of bytes expected to be read.
// This function replaces the deprecated LJUSB_BulkRead, which required the
// (stream) endpoint.
unsigned long LJUSB_WriteTO(HANDLE hDevice, BYTE *pBuff, unsigned long count, unsigned int timeout);
// Writes to a device with a specified timeout. If the timeout time elapses and
// no data is transferred the USB request is aborted and the call returns.
// Returns the number of bytes written, or 0 on error and errno is set.
// hDevice = The handle for your device
// pBuff = The buffer to be written to the device.
// count = The number of bytes to write.
// timeout = The USB communication timeout value in milliseconds. Pass 0 for
// an unlimited timeout.
unsigned long LJUSB_ReadTO(HANDLE hDevice, BYTE *pBuff, unsigned long count, unsigned int timeout);
// Reads from a device with a specified timeout. If the timeout time elapses and
// no data is transferred the USB request is aborted and the call returns.
// Returns the number of bytes read, or 0 on error and errno is set.
// hDevice = The handle for your device
// pBuff = The buffer to be filled in with bytes from the device.
// count = The number of bytes expected to be read.
// timeout = The USB communication timeout value in milliseconds. Pass 0 for
// an unlimited timeout.
unsigned long LJUSB_StreamTO(HANDLE hDevice, BYTE *pBuff, unsigned long count, unsigned int timeout);
// Reads from a device's stream interface with a specified timeout. If the
// timeout time elapses and no data is transferred the USB request is aborted
// and the call returns. Returns the number of bytes read, or 0 on error and
// errno is set.
// hDevice = The handle for your device
// pBuff = The buffer to be filled in with bytes from the device.
// count = The number of bytes expected to be read.
// timeout = The USB communication timeout value in milliseconds. Pass 0 for
// an unlimited timeout.
void LJUSB_CloseDevice(HANDLE hDevice);
// Closes the handle of a LabJack USB device.
bool LJUSB_IsHandleValid(HANDLE hDevice);
// Returns true if the handle is valid; this is, it is still connected to a
// device on the system.
unsigned short LJUSB_GetDeviceDescriptorReleaseNumber(HANDLE hDevice);
// Returns the device's release number (binary-coded decimal) stored in the
// device descriptor.
// hDevice = The handle for your device.
unsigned long LJUSB_GetHIDReportDescriptor(HANDLE hDevice, BYTE *pBuff, unsigned long count);
// Reads the HID report descriptor bytes from a device with a 1 second timeout.
// If the timeout time elapses and no data is transferred the USB request is
// aborted and the call returns. Returns the number of bytes read, or 0 on
// error and errno is set. Only supports the U12.
// hDevice = The handle for your device.
// pBuff = The buffer to filled in with the bytes of the report descriptor.
// count = The number of bytes expected to be read.
//Note: For all function errors, use errno to retrieve system error numbers.
/* --------------- DEPRECATED Functions --------------- */
unsigned long LJUSB_BulkRead(HANDLE hDevice, unsigned char endpoint, BYTE *pBuff, unsigned long count);
// Reads from a bulk endpoint. Returns the count of the number of bytes read,
// or 0 on error (and sets errno). If there is no response within a certain
// amount of time (LJ_LIBUSB_TIMEOUT in labjackusb.c), the read will timeout.
// hDevice = Handle of the LabJack USB device.
// endpoint = The pipe you want to read your data through (xxx_PIPE_xxx_IN).
// *pBuff = Pointer a buffer that will be read from the device.
// count = The size of the buffer to be read from the device.
unsigned long LJUSB_BulkWrite(HANDLE hDevice, unsigned char endpoint, BYTE *pBuff, unsigned long count);
// Writes to a bulk endpoint. Returns the count of the number of bytes wrote,
// or 0 on error and sets errno.
// hDevice = Handle of the LabJack USB device.
// endpoint = The pipe you want to write your data through (xxx_PIPE_xxx_OUT).
// *pBuff = Pointer to the buffer that will be written to the device.
// count = The size of the buffer to be written to the device.
bool LJUSB_AbortPipe(HANDLE hDevice, unsigned long Pipe);
// No longer supported and will return false.
// Pipes will timeout after LJ_LIBUSB_TIMEOUT, which is set by default to 1
// second.
#ifdef __cplusplus
}
#endif
#endif // LABJACKUSB_H_