├── 90-labjack.rules ├── examples ├── U12 │ ├── Makefile │ └── u12AISample.c ├── Modbus │ ├── Makefile │ ├── testModbusFunctions.c │ ├── readModbusExample.c │ ├── writeModbusExample.c │ ├── modbus.c │ └── modbus.h ├── U3 │ ├── Makefile │ ├── u3EFunctions.c │ ├── u3BasicConfigU3.c │ ├── u3allio.c │ └── u3LJTDAC.c ├── U6 │ ├── Makefile │ ├── u6ConfigU6.c │ ├── u6EFunctions.c │ ├── u6BasicConfigU6.c │ ├── u6allio.c │ └── u6LJTDAC.c └── UE9 │ ├── Makefile │ ├── ue9Feedback.c │ ├── ue9ControlConfig.c │ ├── ue9EFunctions.c │ ├── ue9TimerCounter.c │ ├── ue9SingleIO.c │ ├── ue9allio.c │ ├── ue9BasicCommConfig.c │ ├── ue9LJTDAC.c │ └── ue9EthernetExample.c ├── liblabjackusb ├── add_ldconfig_path.sh └── Makefile ├── .gitignore ├── install.sh ├── README ├── INSTALL.MacOSX └── INSTALL.Linux /90-labjack.rules: -------------------------------------------------------------------------------- 1 | SUBSYSTEM!="usb_device", ACTION!="add", GOTO="labjack_rules_end" 2 | 3 | # LabJack Vendor ID 4 | ATTRS{idVendor}=="0cd5", MODE="0666", GROUP="adm" 5 | 6 | LABEL="labjack_rules_end" 7 | -------------------------------------------------------------------------------- /examples/U12/Makefile: -------------------------------------------------------------------------------- 1 | # 2 | # Makefile for U12 examples 3 | # 4 | U12AISAMPLE_SRC=u12AISample.c 5 | U12AISAMPLE_OBJ=$(U12AISAMPLE_SRC:.c=.o) 6 | 7 | SRCS=$(wildcard *.c) 8 | HDRS=$(wildcard *.h) 9 | 10 | CFLAGS+=-Wall -g 11 | LIBS=-lm -llabjackusb 12 | 13 | all: u12AISample 14 | 15 | u12AISample: $(U12AISAMPLE_OBJ) $(HDRS) 16 | $(CC) -o u12AISample $(U12AISAMPLE_OBJ) $(LDFLAGS) $(LIBS) 17 | 18 | clean: 19 | rm -f *.o *~ u12AISample 20 | -------------------------------------------------------------------------------- /liblabjackusb/add_ldconfig_path.sh: -------------------------------------------------------------------------------- 1 | #! /bin/bash 2 | # 3 | # add_ldconfig_path.sh 4 | # 5 | # Idempotently add a path to /etc/ld.so.conf 6 | 7 | set -e 8 | set -u 9 | 10 | ldconfig_file=/etc/ld.so.conf 11 | if [ $# -eq 0 ]; then 12 | path=/usr/local/lib 13 | elif [ $# -eq 1 ]; then 14 | path=$1 15 | else 16 | echo "$0 error - Invalid number of arguments" 17 | echo "Usage: $0 [LIB_DIRECTORY_PATH]" 18 | exit 1 19 | fi 20 | 21 | for line in `cat $ldconfig_file`; do 22 | if [ $line == $path ]; then 23 | # The path has already been added to the config file, 24 | # so there is nothing left to do. 25 | exit 0 26 | fi 27 | done 28 | 29 | echo "echo \"$path\" >> $ldconfig_file" 30 | echo "$path" >> $ldconfig_file 31 | 32 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.o 2 | *.dylib 3 | *.so* 4 | *~ 5 | .DS_Store 6 | readModbusExample 7 | testModbusFunctions 8 | u12AISample 9 | u3allio 10 | u3BasicConfigU3 11 | u3ConfigU3 12 | u3Easy 13 | u3EFunctions 14 | u3Feedback 15 | u3LJTDAC 16 | u3Stream 17 | u6allio 18 | u6BasicConfigU6 19 | u6ConfigU6 20 | u6Easy 21 | u6EFunctions 22 | u6Feedback 23 | u6LJTDAC 24 | u6Stream 25 | ue9allio 26 | ue9BasicCommConfig 27 | ue9CommConfig 28 | ue9ControlConfig 29 | ue9Easy 30 | ue9EFunctions 31 | ue9EthernetExample 32 | ue9Feedback 33 | ue9LJTDAC 34 | ue9SingleIO 35 | ue9Stream 36 | ue9TimerCounter 37 | ue9allio 38 | readModbusExample 39 | testModbusFunctions 40 | writeModbusExample 41 | u12AISample 42 | u3BasicConfigU3 43 | u3EFunctions 44 | u6BasicConfigU6 45 | u6EFunctions 46 | ue9BasicCommConfig 47 | ue9EFunctions 48 | ue9EthernetExample 49 | 50 | -------------------------------------------------------------------------------- /examples/Modbus/Makefile: -------------------------------------------------------------------------------- 1 | # 2 | # Makefile for Modbus examples 3 | # 4 | TESTMODBUS_SRC=testModbusFunctions.c modbus.c 5 | TESTMODBUS_OBJ=$(TESTMODBUS_SRC:.c=.o) 6 | 7 | READMODBUS_SRC=readModbusExample.c modbus.c 8 | READMODBUS_OBJ=$(READMODBUS_SRC:.c=.o) 9 | 10 | WRITEMODBUS_SRC=writeModbusExample.c modbus.c 11 | WRITEMODBUS_OBJ=$(WRITEMODBUS_SRC:.c=.o) 12 | 13 | CFLAGS+=-Wall -g 14 | LIBS=-lm -llabjackusb 15 | 16 | all: testModbusFunctions readModbusExample writeModbusExample 17 | 18 | testModbusFunctions: $(TESTMODBUS_OBJ) 19 | $(CC) -o testModbusFunctions $(TESTMODBUS_OBJ) $(LDFLAGS) $(LIBS) 20 | 21 | readModbusExample: $(READMODBUS_OBJ) 22 | $(CC) -o readModbusExample $(READMODBUS_OBJ) $(LDFLAGS) $(LIBS) 23 | 24 | writeModbusExample: $(WRITEMODBUS_OBJ) 25 | $(CC) -o writeModbusExample $(WRITEMODBUS_OBJ) $(LDFLAGS) $(LIBS) 26 | 27 | clean: 28 | rm -f *.o *~ testModbusFunctions readModbusExample writeModbusExample 29 | -------------------------------------------------------------------------------- /examples/U3/Makefile: -------------------------------------------------------------------------------- 1 | # 2 | # Makefile for U3 examples 3 | # 4 | U3FEEDBACK_SRC=u3Feedback.c u3.c 5 | U3FEEDBACK_OBJ=$(U3FEEDBACK_SRC:.c=.o) 6 | 7 | U3CONFIGU3_SRC=u3BasicConfigU3.c 8 | U3CONFIGU3_OBJ=$(U3CONFIGU3_SRC:.c=.o) 9 | 10 | U3ALLIO_SRC=u3allio.c u3.c 11 | U3ALLIO_OBJ=$(U3ALLIO_SRC:.c=.o) 12 | 13 | U3STREAM_SRC=u3Stream.c u3.c 14 | U3STREAM_OBJ=$(U3STREAM_SRC:.c=.o) 15 | 16 | U3EFUNCTIONS_SRC=u3EFunctions.c u3.c 17 | U3EFUNCTIONS_OBJ=$(U3EFUNCTIONS_SRC:.c=.o) 18 | 19 | U3LJTDAC_SRC=u3LJTDAC.c u3.c 20 | U3LJTDAC_OBJ=$(U3LJTDAC_SRC:.c=.o) 21 | 22 | SRCS=$(wildcard *.c) 23 | HDRS=$(wildcard *.h) 24 | 25 | CFLAGS +=-Wall -g 26 | LIBS=-lm -llabjackusb 27 | 28 | all: u3BasicConfigU3 u3Feedback u3allio u3Stream u3EFunctions u3LJTDAC 29 | 30 | u3BasicConfigU3: $(U3CONFIGU3_OBJ) 31 | $(CC) -o u3BasicConfigU3 $(U3CONFIGU3_OBJ) $(LDFLAGS) $(LIBS) 32 | 33 | u3Feedback: $(U3FEEDBACK_OBJ) $(HDRS) 34 | $(CC) -o u3Feedback $(U3FEEDBACK_OBJ) $(LDFLAGS) $(LIBS) 35 | 36 | u3allio: $(U3ALLIO_OBJ) $(HDRS) 37 | $(CC) -o u3allio $(U3ALLIO_OBJ) $(LDFLAGS) $(LIBS) 38 | 39 | u3Stream: $(U3STREAM_OBJ) $(HDRS) 40 | $(CC) -o u3Stream $(U3STREAM_OBJ) $(LDFLAGS) $(LIBS) 41 | 42 | u3EFunctions: $(U3EFUNCTIONS_OBJ) $(HDRS) 43 | $(CC) -o u3EFunctions $(U3EFUNCTIONS_OBJ) $(LDFLAGS) $(LIBS) 44 | 45 | u3LJTDAC: $(U3LJTDAC_OBJ) $(HDRS) 46 | $(CC) -o u3LJTDAC $(U3LJTDAC_OBJ) $(LDFLAGS) $(LIBS) 47 | 48 | clean: 49 | rm -f *.o *~ u3Feedback u3BasicConfigU3 u3allio u3Stream u3EFunctions u3LJTDAC 50 | -------------------------------------------------------------------------------- /examples/U6/Makefile: -------------------------------------------------------------------------------- 1 | # 2 | # Makefile for U6 examples 3 | # 4 | U6ALLIO_SRC=u6allio.c u6.c 5 | U6ALLIO_OBJ=$(U6ALLIO_SRC:.c=.o) 6 | 7 | U6BASICCONFIGU6_SRC=u6BasicConfigU6.c 8 | U6BASICCONFIGU6_OBJ=$(U6BASICCONFIGU6_SRC:.c=.o) 9 | 10 | U6CONFIGU6_SRC=u6ConfigU6.c u6.c 11 | U6CONFIGU6_OBJ=$(U6CONFIGU6_SRC:.c=.o) 12 | 13 | U6EASY_SRC=u6EFunctions.c u6.c 14 | U6EASY_OBJ=$(U6EASY_SRC:.c=.o) 15 | 16 | U6FEEDBACK_SRC=u6Feedback.c u6.c 17 | U6FEEDBACK_OBJ=$(U6FEEDBACK_SRC:.c=.o) 18 | 19 | U6STREAM_SRC=u6Stream.c u6.c 20 | U6STREAM_OBJ=$(U6STREAM_SRC:.c=.o) 21 | 22 | U6LJTDAC_SRC=u6LJTDAC.c u6.c 23 | U6LJTDAC_OBJ=$(U6LJTDAC_SRC:.c=.o) 24 | 25 | SRCS=$(wildcard *.c) 26 | HDRS=$(wildcard *.h) 27 | 28 | CFLAGS +=-Wall -g 29 | LIBS=-lm -llabjackusb 30 | 31 | all: u6BasicConfigU6 u6ConfigU6 u6allio u6EFunctions u6Feedback u6Stream u6LJTDAC 32 | 33 | u6BasicConfigU6: $(U6BASICCONFIGU6_OBJ) 34 | $(CC) -o u6BasicConfigU6 $(U6BASICCONFIGU6_OBJ) $(LDFLAGS) $(LIBS) 35 | 36 | u6ConfigU6: $(U6CONFIGU6_OBJ) 37 | $(CC) -o u6ConfigU6 $(U6CONFIGU6_OBJ) $(LDFLAGS) $(LIBS) 38 | 39 | u6allio: $(U6ALLIO_OBJ) $(HDRS) 40 | $(CC) -o u6allio $(U6ALLIO_OBJ) $(LDFLAGS) $(LIBS) 41 | 42 | u6EFunctions: $(U6EASY_OBJ) $(HDRS) 43 | $(CC) -o u6EFunctions $(U6EASY_OBJ) $(LDFLAGS) $(LIBS) 44 | 45 | u6Feedback: $(U6FEEDBACK_OBJ) $(HDRS) 46 | $(CC) -o u6Feedback $(U6FEEDBACK_OBJ) $(LDFLAGS) $(LIBS) 47 | 48 | u6Stream: $(U6STREAM_OBJ) $(HDRS) 49 | $(CC) -o u6Stream $(U6STREAM_OBJ) $(LDFLAGS) $(LIBS) 50 | 51 | u6LJTDAC: $(U6LJTDAC_OBJ) $(HDRS) 52 | $(CC) -o u6LJTDAC $(U6LJTDAC_OBJ) $(LDFLAGS) $(LIBS) 53 | 54 | clean: 55 | rm -f *.o *~ u6Feedback u6BasicConfigU6 u6ConfigU6 u6allio u6Stream u6EFunctions u6LJTDAC 56 | -------------------------------------------------------------------------------- /liblabjackusb/Makefile: -------------------------------------------------------------------------------- 1 | # 2 | # Makefile for liblabjackusb 3 | # 4 | # 5 | 6 | UNAME = $(shell uname -s) 7 | 8 | VERSION = 2.7.0 9 | PREFIX ?= /usr/local 10 | DESTINATION = $(DESTDIR)$(PREFIX)/lib 11 | HEADER = labjackusb.h 12 | HEADER_DESTINATION = $(DESTDIR)$(PREFIX)/include 13 | LIBFLAGS = -lusb-1.0 -lc 14 | ADD_LDCONFIG_PATH = ./add_ldconfig_path.sh 15 | 16 | ifeq ($(UNAME),Darwin) 17 | #Mac OS X operating system macros 18 | ext = dylib 19 | TARGET = liblabjackusb-$(VERSION).$(ext) 20 | 21 | # Build for only the host architecture 22 | #ARCHFLAGS = 23 | 24 | # Build for 64 bit Intel and Arm architectures 25 | #ARCHFLAGS = -arch x86_64 -arch arm64 26 | 27 | # Build for 32- and 64-bit Intel architectures 28 | #ARCHFLAGS = -arch i386 -arch x86_64 29 | 30 | # Build for multiple architectures 31 | #ARCHFLAGS = -arch i386 -arch x86_64 -arch ppc 32 | 33 | COMPILE = $(CC) -dynamiclib -o $(TARGET) -install_name $(TARGET) -current_version $(VERSION) -compatibility_version $(VERSION) labjackusb.o $(LIBFLAGS) $(ARCHFLAGS) 34 | 35 | # By default, create link from 36 | # liblabjackusb.dylib to liblabjackusb-$(VERSION).dylib 37 | # because ldconfig will not be run on Mac 38 | RUN_LDCONFIG ?= 0 39 | LINK_SO ?= 1 40 | else 41 | #Linux operating system macros 42 | ext = so 43 | TARGET = liblabjackusb.$(ext).$(VERSION) 44 | 45 | # Build for only the host architecture 46 | #ARCHFLAGS = 47 | 48 | COMPILE = $(CC) -shared -Wl,-soname,liblabjackusb.$(ext) -o $(TARGET) labjackusb.o $(LIBFLAGS) 49 | 50 | # By default, do not create link from 51 | # liblabjackusb.dylib to liblabjackusb-$(VERSION).dylib 52 | # because ldconfig will be run on Linux 53 | RUN_LDCONFIG ?= 1 54 | LINK_SO ?= 0 55 | endif 56 | 57 | CFLAGS += -fPIC -g -Wall $(ARCHFLAGS) 58 | 59 | %.o: %.c 60 | $(CC) $(CFLAGS) -c $< 61 | 62 | all: $(TARGET) 63 | 64 | $(TARGET): labjackusb.o $(HEADER) 65 | $(COMPILE) 66 | 67 | install: $(TARGET) 68 | test -z $(DESTINATION) || mkdir -p $(DESTINATION) 69 | install $(TARGET) $(DESTINATION) 70 | test -z $(HEADER_DESTINATION) || mkdir -p $(HEADER_DESTINATION) 71 | install $(HEADER) $(HEADER_DESTINATION) 72 | ifeq ($(RUN_LDCONFIG),1) 73 | @$(ADD_LDCONFIG_PATH) $(DESTINATION) 74 | ldconfig 75 | endif 76 | ifeq ($(LINK_SO),1) 77 | ln -i -s $(DESTINATION)/$(TARGET) $(DESTINATION)/liblabjackusb.$(ext) 78 | endif 79 | 80 | clean: 81 | rm -f $(TARGET) *.o *~ 82 | -------------------------------------------------------------------------------- /examples/UE9/Makefile: -------------------------------------------------------------------------------- 1 | # 2 | # Makefile for UE9 examples 3 | # 4 | UE9SINGLEIO_SRC=ue9SingleIO.c ue9.c 5 | UE9SINGLEIO_OBJ=$(UE9SINGLEIO_SRC:.c=.o) 6 | 7 | UE9COMMCONFIG_SRC=ue9BasicCommConfig.c 8 | UE9COMMCONFIG_OBJ=$(UE9COMMCONFIG_SRC:.c=.o) 9 | 10 | UE9ETHERNET_SRC=ue9EthernetExample.c 11 | UE9ETHERNET_OBJ=$(UE9ETHERNET_SRC:.c=.o) 12 | 13 | UE9CONTROLCONFIG_SRC=ue9ControlConfig.c ue9.c 14 | UE9CONTROLCONFIG_OBJ=$(UE9CONTROLCONFIG_SRC:.c=.o) 15 | 16 | UE9FEEDBACK_SRC=ue9Feedback.c ue9.c 17 | UE9FEEDBACK_OBJ=$(UE9FEEDBACK_SRC:.c=.o) 18 | 19 | UE9STREAM_SRC=ue9Stream.c ue9.c 20 | UE9STREAM_OBJ=$(UE9STREAM_SRC:.c=.o) 21 | 22 | UE9TIMERCOUNTER_SRC=ue9TimerCounter.c ue9.c 23 | UE9TIMERCOUNTER_OBJ=$(UE9TIMERCOUNTER_SRC:.c=.o) 24 | 25 | UE9ALLIO_SRC=ue9allio.c ue9.c 26 | UE9ALLIO_OBJ=$(UE9ALLIO_SRC:.c=.o) 27 | 28 | UE9EFUNCTIONS_SRC=ue9EFunctions.c ue9.c 29 | UE9EFUNCTIONS_OBJ=$(UE9EFUNCTIONS_SRC:.c=.o) 30 | 31 | UE9LJTDAC_SRC=ue9LJTDAC.c ue9.c 32 | UE9LJTDAC_OBJ=$(UE9LJTDAC_SRC:.c=.o) 33 | 34 | SRCS=$(wildcard *.c) 35 | HDRS=$(wildcard *.h) 36 | 37 | CFLAGS +=-Wall -g 38 | LIBS=-lm -llabjackusb 39 | 40 | all: ue9BasicCommConfig ue9EthernetExample ue9SingleIO ue9ControlConfig ue9Feedback ue9Stream ue9TimerCounter ue9allio ue9EFunctions ue9LJTDAC 41 | 42 | ue9BasicCommConfig: $(UE9COMMCONFIG_OBJ) $(HDRS) 43 | $(CC) -o ue9BasicCommConfig $(UE9COMMCONFIG_OBJ) $(LDFLAGS) $(LIBS) 44 | 45 | ue9EthernetExample: $(UE9ETHERNET_OBJ) $(HDRS) 46 | $(CC) -o ue9EthernetExample $(UE9ETHERNET_OBJ) $(LDFLAGS) $(LIBS) 47 | 48 | ue9SingleIO: $(UE9SINGLEIO_OBJ) $(HDRS) 49 | $(CC) -o ue9SingleIO $(UE9SINGLEIO_OBJ) $(LDFLAGS) $(LIBS) 50 | 51 | ue9ControlConfig: $(UE9CONTROLCONFIG_OBJ) $(HDRS) 52 | $(CC) -o ue9ControlConfig $(UE9CONTROLCONFIG_OBJ) $(LDFLAGS) $(LIBS) 53 | 54 | ue9Feedback: $(UE9FEEDBACK_OBJ) $(HDRS) 55 | $(CC) -o ue9Feedback $(UE9FEEDBACK_OBJ) $(LDFLAGS) $(LIBS) 56 | 57 | ue9Stream: $(UE9STREAM_OBJ) $(HDRS) 58 | $(CC) -o ue9Stream $(UE9STREAM_OBJ) $(LDFLAGS) $(LIBS) 59 | 60 | ue9TimerCounter: $(UE9TIMERCOUNTER_OBJ) $(HDRS) 61 | $(CC) -o ue9TimerCounter $(UE9TIMERCOUNTER_OBJ) $(LDFLAGS) $(LIBS) 62 | 63 | ue9allio: $(UE9ALLIO_OBJ) $(HDRS) 64 | $(CC) -o ue9allio $(UE9ALLIO_OBJ) $(LDFLAGS) $(LIBS) 65 | 66 | ue9EFunctions: $(UE9EFUNCTIONS_OBJ) $(HDRS) 67 | $(CC) -o ue9EFunctions $(UE9EFUNCTIONS_OBJ) $(LDFLAGS) $(LIBS) 68 | 69 | ue9LJTDAC: $(UE9LJTDAC_OBJ) $(HDRS) 70 | $(CC) -o ue9LJTDAC $(UE9LJTDAC_OBJ) $(LDFLAGS) $(LIBS) 71 | 72 | clean: 73 | rm -f *.o *~ ue9BasicCommConfig ue9SingleIO ue9ControlConfig ue9Feedback ue9Stream ue9TimerCounter ue9allio ue9EFunctions ue9LJTDAC ue9EthernetExample 74 | -------------------------------------------------------------------------------- /install.sh: -------------------------------------------------------------------------------- 1 | #! /bin/bash 2 | 3 | RULES=90-labjack.rules 4 | OLD_RULES=10-labjack.rules 5 | RULES_DEST_PRIMARY=/lib/udev/rules.d 6 | RULES_DEST_ALTERNATE=/etc/udev/rules.d 7 | SUPPORT_EMAIL=support@labjack.com 8 | TRUE=1 9 | FALSE=0 10 | IS_SUCCESS=$TRUE 11 | # Assume these are unneeded until otherwise 12 | NEED_RECONNECT=$FALSE 13 | NEED_RESTART=$FALSE 14 | NO_RULES=$FALSE 15 | NO_RULES_ERR=2 16 | 17 | go () 18 | { 19 | $@ 20 | ret=$? 21 | if [ $ret -ne 0 ]; then 22 | echo "Error, please make sure you are running this script as:" 23 | echo " $ sudo $0" 24 | echo "If you are still having problems, please contact LabJack support: <$SUPPORT_EMAIL>" 25 | exit $ret 26 | fi 27 | } 28 | 29 | success () 30 | { 31 | e=0 32 | if [ $IS_SUCCESS -eq $TRUE ]; then 33 | echo "Install finished. Thank you for choosing LabJack." 34 | fi 35 | if [ $NEED_RECONNECT -eq $TRUE ]; then 36 | echo "If you have any LabJack devices connected, please disconnect and reconnect them now for device rule changes to take effect." 37 | fi 38 | if [ $NO_RULES -eq $TRUE ]; then 39 | echo "No udev rules directory found. Searched for $RULES_DEST_PRIMARY, $RULES_DEST_ALTERNATE." 40 | echo "Please copy $RULES to your device rules directory and reload the rules or contact LabJack support for assistance: <$SUPPORT_EMAIL>" 41 | let e=e+$NO_RULES_ERR 42 | fi 43 | if [ $NEED_RESTART -eq $TRUE ]; then 44 | echo "Please manually restart the device rules or restart your computer now." 45 | fi 46 | exit $e 47 | } 48 | 49 | ############################## 50 | # Exodriver make and install # 51 | ############################## 52 | go cd liblabjackusb/ 53 | 54 | echo "Making.." 55 | go make clean 56 | go make 57 | 58 | echo "Installing.." 59 | go make install 60 | 61 | # Mac OS doesn't need rules config 62 | if [ `uname -s` == "Darwin" ]; then 63 | success 64 | fi 65 | 66 | go cd ../ 67 | 68 | ################# 69 | # LabJack Rules # 70 | ################# 71 | rm -f $RULES_DEST_PRIMARY/$OLD_RULES 72 | rm -f $RULES_DEST_ALTERNATE/$OLD_RULES 73 | 74 | if [ -d $RULES_DEST_PRIMARY ]; then 75 | RULES_DEST=$RULES_DEST_PRIMARY 76 | 77 | OLD_FILE_TO_REMOVE=$RULES_DEST_ALTERNATE/$RULES 78 | if [ -f $OLD_FILE_TO_REMOVE ]; then 79 | rm $OLD_FILE_TO_REMOVE 80 | fi 81 | elif [ -d $RULES_DEST_ALTERNATE ]; then 82 | RULES_DEST=$RULES_DEST_ALTERNATE 83 | else 84 | NO_RULES=$TRUE 85 | fi 86 | 87 | if [ $NO_RULES -ne $TRUE ]; then 88 | echo "Adding $RULES to $RULES_DEST.." 89 | go cp -f $RULES $RULES_DEST 90 | NEED_RECONNECT=$TRUE 91 | fi 92 | 93 | ##################### 94 | # Restart the Rules # 95 | ##################### 96 | echo -n "Restarting the rules.." 97 | udevadm control --reload-rules 2> /dev/null 98 | ret=$? 99 | if [ $ret -ne 0 ]; then 100 | udevadm control --reload_rules 2> /dev/null 101 | ret=$? 102 | fi 103 | if [ $ret -ne 0 ]; then 104 | /etc/init.d/udev-post reload 2> /dev/null 105 | ret=$? 106 | fi 107 | if [ $ret -ne 0 ]; then 108 | udevstart 2> /dev/null 109 | ret=$? 110 | fi 111 | if [ $ret -ne 0 ]; then 112 | NEED_RESTART=$TRUE 113 | echo " could not restart the rules." 114 | else 115 | echo # Finishes previous echo -n 116 | fi 117 | 118 | success 119 | -------------------------------------------------------------------------------- /examples/Modbus/testModbusFunctions.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This file shows how to uses the functions in modbus.h without requiring a 3 | * LabJack, the Exodriver, or libusb. 4 | */ 5 | #include 6 | #include "modbus.h" 7 | 8 | int main() { 9 | int i; 10 | 11 | printf("Modbus Function tests:\n\n"); 12 | 13 | // Build a packet to read register 0 (AIN0) and store it in sendBuffer 14 | unsigned char sendBuffer[14]; 15 | int startReg = 0; // Start at register 0 16 | int numRegs = 2; // AIN0 is floating point, so need to read 2 registers 17 | int unitId = 0; // For UD family devices, always 0 18 | int prependZeros = 1; // For UD family devices on USB, always 1 19 | int numBytesToRead; 20 | 21 | numBytesToRead = buildReadHoldingRegistersPacket( sendBuffer, startReg, numRegs, unitId, prependZeros ); 22 | 23 | printf("buildReadHoldingRegistersPacket:\n sendBuffer: ["); 24 | for(i = 0; i < 13; i++) { 25 | printf("0x%X, ", sendBuffer[i]); 26 | } 27 | printf("0x%X]\n numBytesToRead: %d\n\n", sendBuffer[13], numBytesToRead); 28 | 29 | 30 | // Parse a float from a byte array. 31 | unsigned char recBuffer[] = { 0x40, 0x0, 0x0, 0x0 }; 32 | float fValue = parseFPRegisterResponse(recBuffer, 0); 33 | 34 | printf("parseFPRegister: [0x40, 0x0, 0x0, 0x0] => %f\n\n", fValue); 35 | 36 | // Parse an int from a byte array. 37 | recBuffer[0] = 0x0; 38 | recBuffer[1] = 0x84; 39 | recBuffer[2] = 0x5F; 40 | recBuffer[3] = 0xED; 41 | int iValue = parseIntRegisterResponse(recBuffer, 0); 42 | printf("parseIntRegister: [0x0, 0x84, 0x5F, 0xED] => %i\n\n", iValue); 43 | 44 | // Parse a short from a byte array. 45 | recBuffer[0] = 0x2; 46 | recBuffer[1] = 0x10; 47 | short sValue = parseShortRegisterResponse(recBuffer, 0); 48 | printf("parseShortRegister: [0x2, 0x10] => %i\n\n", sValue); 49 | 50 | 51 | // Start Write Functions 52 | 53 | // Build an array of bytes to write 2.0, 8675309, and 528 starting at 0 54 | startReg = 0; // Start at register 0 55 | numRegs = 5; // 1 float (2 registers), 1 int (2 registers), 1 short (1 reg) 56 | unitId = 0; // For UD family devices, always 0 57 | prependZeros = 1; // For UD family devices on USB, always 1 58 | unsigned char writeBuffer[25]; // 13 + (2*5) + 2 = 25 59 | 60 | numBytesToRead = buildWriteHoldingRegistersPacket(writeBuffer, startReg, numRegs, unitId, prependZeros); 61 | printf("buildWriteHoldingRegistersPacket:\n writeBuffer: ["); 62 | for(i = 0; i < 24; i++) { 63 | printf("0x%X, ", writeBuffer[i]); 64 | } 65 | printf("0x%X]\n numBytesToRead: %d\n\n", writeBuffer[24], numBytesToRead); 66 | 67 | putFPIntoBuffer(writeBuffer, 15, 2.0); 68 | printf("putFPIntoBuffer: Appended 2.0 to packet.\n\n"); 69 | 70 | putIntIntoBuffer(writeBuffer, 19, 8675309); 71 | printf("putIntIntoBuffer: Appended 8675309 to packet.\n\n"); 72 | 73 | putShortIntoBuffer(writeBuffer, 23, 528); 74 | printf("putShortIntoBuffer: Appended 528 to packet.\n\n"); 75 | 76 | printf("Result:\n writeBuffer: ["); 77 | for(i = 0; i < 24; i++) { 78 | printf("0x%X, ", writeBuffer[i]); 79 | } 80 | printf("0x%X]\n\n", writeBuffer[24]); 81 | 82 | return 0; 83 | } -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | Exodriver: Linux (kernel 2.6+) and Mac OS X low-level LabJack U12, U3, U6, UE9, 2 | Digit, T4, and T7 USB library 2.07 and C examples 3 | 01/17/2022 4 | support@labjack.com 5 | 6 | This package contains the liblabjackusb 2.07 USB library for low-level U3, U6, 7 | UE9, Digit, T4, and T7 USB communications and C examples for select LabJack 8 | devices. 9 | 10 | Refer to the INSTALL.Linux or INSTALL.MacOSX file for library requirements, 11 | installation instructions, and compiling information (library and examples). 12 | Note that the Exodriver requires the libusb-1.0 library. 13 | 14 | Library source code files are located in the liblabjackusb directory. 15 | 16 | C examples are provided for the LabJack U12, U3, U6, and UE9 in the examples 17 | directory. They demonstrate basic open/write/read/close operations using 18 | the liblabjackusb library and low-level function command-response. Low-level 19 | function documentation can be found in Section 5 of the LabJack U12, U3, U6, 20 | and UE9 User Guides. The u3.h/u6.h/ue9.h, and u3.c/u6.h/ue9.c files contain 21 | helpful functions for opening/closing USB connections, calculate checksums, 22 | retrieving device analog calibration information, etc. There are 5 "easy" 23 | functions (eAIN, eDAC, eDI, eDO, eTCConfig and eTCValues) that are similar to 24 | our Windows LabJackUD driver's "easy" functions. All other .c files are 25 | examples. 26 | 27 | USB command-response times for the U3, U6 and UE9 can be found in section 3.1 28 | of their User's Guide and were tested with the Feedback low-level function. USB 29 | Stream times are in Section 3.2. These times were measured in Windows and are 30 | similar in Linux and Mac OS X. 31 | 32 | Examples are not provided for Digit, T4, or T7 devices in this package. 33 | Please refer to the LJM library package and documentation for their API. 34 | 35 | The U12 also has a high-level library, which requires this library 36 | (liblabjackusb), that provides the same API as the U12 Windows driver. It can 37 | be downloaded here: 38 | 39 | http://labjack.com/support/u12/ljacklm 40 | 41 | 42 | LICENSE 43 | 44 | All exodriver library and example source code are licensed under MIT X11. 45 | 46 | Copyright (c) 2009 LabJack Corporation 47 | 48 | Permission is hereby granted, free of charge, to any person obtaining a copy 49 | of this software and associated documentation files (the "Software"), to deal 50 | in the Software without restriction, including without limitation the rights 51 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 52 | copies of the Software, and to permit persons to whom the Software is 53 | furnished to do so, subject to the following conditions: 54 | 55 | The above copyright notice and this permission notice shall be included in 56 | all copies or substantial portions of the Software. 57 | 58 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 59 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 60 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 61 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 62 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 63 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 64 | THE SOFTWARE. 65 | -------------------------------------------------------------------------------- /examples/Modbus/readModbusExample.c: -------------------------------------------------------------------------------- 1 | /* 2 | * A simple example that shows how to used modbus.h with the Exodriver by 3 | * reading AIN0 and printing it to stdout. 4 | * 5 | * The most important thing to get right are your buffer lengths. In the case of 6 | * read register, it's easy. The command to be written is always 14 bytes. The 7 | * response is 9 + (2 * number of registers being read). So, if you are reading 8 | * three registers, your receive buffer needs to be 9 + (3 * 2), or 15 bytes. 9 | * What those bytes mean will depend on the register. Make sure to check out the 10 | * Modbus support page: 11 | * http://labjack.com/support/modbus 12 | */ 13 | 14 | #include 15 | #include "modbus.h" 16 | #include "labjackusb.h" 17 | 18 | // Set to 3 (U3), 6 (U6), or 9 (UE9). 19 | #define DEVICE_TYPE 3 20 | 21 | // Read Holding Register Packets are always 14 bytes over USB 22 | #define READ_REGISTER_SEND_LENGTH 14 23 | 24 | int main() { 25 | HANDLE devHandle; 26 | int i; 27 | int r = 0; // For checking return values 28 | 29 | int startReg = 0; // Start at register 0 30 | int numRegs = 2; // AIN0 is floating point, so need to read 2 registers 31 | int unitId = 0; // For UD family devices, always 0 32 | int prependZeros = 1; // For UD family devices on USB, always 1 33 | BYTE sendBuffer[READ_REGISTER_SEND_LENGTH]; // 2 (for extra zeros) + 12 34 | int numBytesToRead = 13; // 9 + (2*numReg) 35 | BYTE recBuffer[13]; // Same as numBytesToRead 36 | float value; // Will hold parsed result 37 | 38 | // Open the device 39 | devHandle = LJUSB_OpenDevice(1, 0, DEVICE_TYPE); 40 | 41 | if(devHandle <= 0){ 42 | printf("ERROR: Couldn't find a LabJack to open.\n"); 43 | return -1; 44 | } 45 | 46 | if(DEVICE_TYPE == 3){ 47 | printf("Opened first found U3.\n"); 48 | } 49 | else if(DEVICE_TYPE == 6) { 50 | printf("Opened first found U6.\n"); 51 | } 52 | else { 53 | printf("Opened first found UE9.\n"); 54 | } 55 | 56 | // Build the packet. 57 | numBytesToRead = buildReadHoldingRegistersPacket(sendBuffer, startReg, numRegs, unitId, prependZeros); 58 | 59 | printf("Built Read Holding Registers Packet to read register 0 (AIN0).\n"); 60 | 61 | // Send packet to the device. 62 | r = LJUSB_Write(devHandle, sendBuffer, READ_REGISTER_SEND_LENGTH); 63 | 64 | if( r != READ_REGISTER_SEND_LENGTH ){ 65 | printf("ERROR: An error occurred while writing to the device."); 66 | LJUSB_CloseDevice(devHandle); 67 | return -1; 68 | } 69 | 70 | printf("Wrote command to device.\n"); 71 | 72 | printf("Sent = ["); 73 | for( i = 0; i < READ_REGISTER_SEND_LENGTH-1; i++){ 74 | printf("0x%X, ", sendBuffer[i]); 75 | } 76 | printf("0x%X]\n\n", sendBuffer[READ_REGISTER_SEND_LENGTH-1]); 77 | 78 | // Read the response from the device. 79 | r = LJUSB_Read(devHandle, recBuffer, numBytesToRead); 80 | 81 | if( r != numBytesToRead ){ 82 | printf("ERROR: An error occurred while reading from the device."); 83 | LJUSB_CloseDevice(devHandle); 84 | return -1; 85 | } 86 | 87 | printf("Read the response.\n"); 88 | 89 | printf("Read = ["); 90 | for( i = 0; i < numBytesToRead-1; i++){ 91 | printf("0x%X, ", recBuffer[i]); 92 | } 93 | printf("0x%X]\n\n", recBuffer[numBytesToRead-1]); 94 | 95 | // Parse out the value. 96 | value = parseFPRegisterResponse(recBuffer, 9); 97 | printf("AIN0: %f\n\n", value); 98 | 99 | // Close the device. 100 | LJUSB_CloseDevice(devHandle); 101 | 102 | printf("Closed Device.\n"); 103 | 104 | return 0; 105 | } -------------------------------------------------------------------------------- /examples/U6/u6ConfigU6.c: -------------------------------------------------------------------------------- 1 | //Author : LabJack 2 | //April 6, 2011 3 | //This example calls the ConfigU6 low-level function and reads back 4 | //configuration settings. 5 | 6 | #include "u6.h" 7 | 8 | 9 | int configU6_example(HANDLE hDevice); 10 | 11 | int main(int argc, char **argv) 12 | { 13 | HANDLE hDevice; 14 | 15 | //Opening first found U6 over USB 16 | if( (hDevice = openUSBConnection(-1)) == NULL ) 17 | return 1; 18 | 19 | configU6_example(hDevice); 20 | 21 | closeUSBConnection(hDevice); 22 | 23 | return 0; 24 | } 25 | 26 | //Sends a ConfigU3 low-level command to read back configuration settings 27 | int configU6_example(HANDLE hDevice) 28 | { 29 | uint8 sendBuff[26]; 30 | uint8 recBuff[38]; 31 | uint16 checksumTotal; 32 | int sendChars, recChars, i; 33 | 34 | sendBuff[1] = (uint8)(0xF8); //Command byte 35 | sendBuff[2] = (uint8)(0x0A); //Number of data words 36 | sendBuff[3] = (uint8)(0x08); //Extended command number 37 | 38 | //Setting all bytes to zero since we only want to read back the U6 39 | //configuration settings 40 | for( i = 6; i < 26; i++ ) 41 | sendBuff[i] = 0; 42 | 43 | /* The commented out code below sets the U6's local ID to 3. After setting 44 | the local ID, reset the device for this change to take effect. */ 45 | 46 | //sendBuff[6] = 8; //WriteMask : setting bit 3 47 | //sendBuff[8] = 3; //LocalID : setting local ID to 3 48 | 49 | extendedChecksum(sendBuff, 26); 50 | 51 | //Sending command to U6 52 | if( (sendChars = LJUSB_Write(hDevice, sendBuff, 26)) < 26 ) 53 | { 54 | if( sendChars == 0 ) 55 | printf("ConfigU6 error : write failed\n"); 56 | else 57 | printf("ConfigU6 error : did not write all of the buffer\n"); 58 | return -1; 59 | } 60 | 61 | //Reading response from U6 62 | if( (recChars = LJUSB_Read(hDevice, recBuff, 38)) < 38 ) 63 | { 64 | if( recChars == 0 ) 65 | printf("ConfigU6 error : read failed\n"); 66 | else 67 | printf("ConfigU6 error : did not read all of the buffer\n"); 68 | return -1; 69 | } 70 | 71 | checksumTotal = extendedChecksum16(recBuff, 38); 72 | if( (uint8)((checksumTotal / 256) & 0xff) != recBuff[5] ) 73 | { 74 | printf("ConfigU6 error : read buffer has bad checksum16(MSB)\n"); 75 | return -1; 76 | } 77 | 78 | if( (uint8)(checksumTotal & 0xff) != recBuff[4] ) 79 | { 80 | printf("ConfigU6 error : read buffer has bad checksum16(LBS)\n"); 81 | return -1; 82 | } 83 | 84 | if( extendedChecksum8(recBuff) != recBuff[0] ) 85 | { 86 | printf("ConfigU6 error : read buffer has bad checksum8\n"); 87 | return -1; 88 | } 89 | 90 | if( recBuff[1] != (uint8)(0xF8) || recBuff[2] != (uint8)(0x10) || recBuff[3] != (uint8)(0x08) ) 91 | { 92 | printf("ConfigU6 error : read buffer has wrong command bytes\n"); 93 | return -1; 94 | } 95 | 96 | if( recBuff[6] != 0 ) 97 | { 98 | printf("ConfigU6 error : read buffer received errorcode %d\n", recBuff[6]); 99 | return -1; 100 | } 101 | 102 | printf("U6 Configuration Settings:\n"); 103 | printf("FirmwareVersion: %.3f\n", recBuff[10] + recBuff[9]/100.0); 104 | printf("BootloaderVersion: %.3f\n", recBuff[12] + recBuff[11]/100.0); 105 | printf("HardwareVersion: %.3f\n", recBuff[14] + recBuff[13]/100.0); 106 | printf("SerialNumber: %u\n", recBuff[15] + recBuff[16]*256 + recBuff[17]*65536 + recBuff[18]*16777216); 107 | printf("ProductID: %d\n", recBuff[19] + recBuff[20]*256); 108 | printf("LocalID: %d\n", recBuff[21]); 109 | 110 | printf("Version Info: %d\n", recBuff[37]); 111 | printf(" U6 (bit 2): %d\n", ((recBuff[37]/4)&1)); 112 | printf(" U6-Pro (bit 3): %d\n", ((recBuff[37]/8)&1)); 113 | 114 | return 0; 115 | } 116 | -------------------------------------------------------------------------------- /examples/Modbus/writeModbusExample.c: -------------------------------------------------------------------------------- 1 | /* 2 | * A simple example that shows how to used modbus.h with the Exodriver by 3 | * writing 2.0 to DAC0. 4 | * 5 | * The most important thing to get right are your buffer lengths. With write 6 | * register, it can be a little tricky. The base packet is 13 bytes, then 2 7 | * extra bytes for every register you're going to write to. Because of a weird 8 | * quirk with LabJacks, you need to prepend two bytes of zeros. This makes the 9 | * equation as follows: send buffer length = 2 + 13 + (2 * number of registers). 10 | * 11 | * The response is always 12 bytes, so that part is easy. 12 | * 13 | * Another possible point of confusion with writing is that you have to setup 14 | * the basic bytes with buildWriteHoldingRegistersPacket then insert the values 15 | * with put*IntoBuffer functions. Your first value should always go in offset 16 | * 15. If you are putting multiple values in one packet, the offset of the 17 | * second value will depend on the type of the first value. Floats and Integers 18 | * will both take 4 bytes, and Shorts will only take 2. So, if you are writing a 19 | * Float then a Short, the Float will go in offset 15, the Short in offset 19. 20 | * If it's a Short than a Float, the Short will have offset 15, and the Float 21 | * should be put in offset 17. 22 | * 23 | * For more information about Modbus, please see the support page: 24 | * http://labjack.com/support/modbus 25 | */ 26 | 27 | #include 28 | #include "modbus.h" 29 | #include "labjackusb.h" 30 | 31 | // Set to 3 (U3), 6 (U6), or 9 (UE9). 32 | #define DEVICE_TYPE 3 33 | 34 | // Set to what you want the DAC to output. 35 | #define DAC_VALUE 2.0f 36 | 37 | // 13 + (2*numReg) + 2 = 13 + (2*2) + 2 = 19 38 | #define WRITE_REGISTER_SEND_LENGTH 19 39 | 40 | // Write Holding Register Response Packets are always 12 bytes 41 | #define WRITE_REGISTER_REC_LENGTH 12 42 | 43 | int main() { 44 | HANDLE devHandle; 45 | int i; 46 | int r = 0; // For checking return values 47 | 48 | int startReg = 5000; // Start at register 5000 49 | int numRegs = 2; // DAC0 is floating point, so need to write 2 registers 50 | int unitId = 0; // For UD family devices, always 0 51 | int prependZeros = 1; // For UD family devices on USB, always 1 52 | int numBytesToRead = WRITE_REGISTER_REC_LENGTH; 53 | BYTE sendBuffer[WRITE_REGISTER_SEND_LENGTH]; 54 | BYTE recBuffer[WRITE_REGISTER_REC_LENGTH]; // Same as numBytesToRead 55 | 56 | // Open the device 57 | devHandle = LJUSB_OpenDevice(1, 0, DEVICE_TYPE); 58 | 59 | if(devHandle <= 0){ 60 | printf("ERROR: Couldn't find a LabJack to open."); 61 | return -1; 62 | } 63 | 64 | if(DEVICE_TYPE == 3){ 65 | printf("Opened first found U3.\n"); 66 | } 67 | else if(DEVICE_TYPE == 6) { 68 | printf("Opened first found U6.\n"); 69 | } 70 | else { 71 | printf("Opened first found UE9.\n"); 72 | } 73 | 74 | // Build the packet. 75 | numBytesToRead = buildWriteHoldingRegistersPacket(sendBuffer, startReg, numRegs, unitId, prependZeros); 76 | 77 | printf("Built Write Holding Registers Packet to write register 5000 (DAC0).\n"); 78 | 79 | // Puts DAC_VALUE into the buffer. 80 | putFPIntoBuffer(sendBuffer, 15, DAC_VALUE); 81 | 82 | printf("Added value %.2f to buffer.\n", DAC_VALUE); 83 | 84 | // Send packet to the device. 85 | r = LJUSB_Write(devHandle, sendBuffer, WRITE_REGISTER_SEND_LENGTH); 86 | 87 | if( r != WRITE_REGISTER_SEND_LENGTH ){ 88 | printf("ERROR: An error occurred while writing to the device."); 89 | LJUSB_CloseDevice(devHandle); 90 | return -1; 91 | } 92 | 93 | printf("Wrote command to device.\n"); 94 | 95 | printf("Sent = ["); 96 | for( i = 0; i < WRITE_REGISTER_SEND_LENGTH-1; i++){ 97 | printf("0x%X, ", sendBuffer[i]); 98 | } 99 | printf("0x%X]\n\n", sendBuffer[WRITE_REGISTER_SEND_LENGTH-1]); 100 | 101 | // Read the response from the device. 102 | r = LJUSB_Read(devHandle, recBuffer, numBytesToRead); 103 | 104 | if( r != numBytesToRead ){ 105 | printf("ERROR: An error occurred while reading from the device.\n r = %i", r); 106 | LJUSB_CloseDevice(devHandle); 107 | return -1; 108 | } 109 | 110 | printf("Read the response.\n"); 111 | 112 | printf("Read = ["); 113 | for( i = 0; i < numBytesToRead-1; i++){ 114 | printf("0x%X, ", recBuffer[i]); 115 | } 116 | printf("0x%X]\n\n", recBuffer[numBytesToRead-1]); 117 | 118 | // Close the device. 119 | LJUSB_CloseDevice(devHandle); 120 | 121 | printf("Closed Device.\n"); 122 | 123 | return 0; 124 | } -------------------------------------------------------------------------------- /examples/Modbus/modbus.c: -------------------------------------------------------------------------------- 1 | /* 2 | * A library to help you build modbus functions for LabJack devices. 3 | */ 4 | 5 | /* --------- Static Variables --------- */ 6 | 7 | static short nextTransactionId = 0x37; 8 | 9 | /* --------- Read Functions --------- */ 10 | 11 | int buildReadHoldingRegistersPacket( unsigned char* sendBuffer, int startReg, int numRegs, int unitId, int prependZeros ) { 12 | int offset = 0; 13 | 14 | if(prependZeros != 0){ 15 | sendBuffer[0] = 0; 16 | sendBuffer[1] = 0; 17 | offset = 2; 18 | } 19 | 20 | // Bytes 0 and 1 are TransID 21 | sendBuffer[0+offset] = (unsigned char)((nextTransactionId >> 8) & 0xff); 22 | sendBuffer[1+offset] = (unsigned char)(nextTransactionId & 0xff); 23 | nextTransactionId++; 24 | 25 | // Bytes 2 and 3 are ProtocolID, set to 0 26 | sendBuffer[2+offset] = 0; 27 | sendBuffer[3+offset] = 0; 28 | 29 | // Bytes 4 and 5 are length. 30 | sendBuffer[4+offset] = 0; 31 | sendBuffer[5+offset] = 6; 32 | 33 | // Byte 6 is Unit ID. 34 | sendBuffer[6+offset] = unitId; 35 | 36 | // Byte 7 is Read Holding Registers ( function # 3 ) 37 | sendBuffer[7+offset] = 3; 38 | 39 | // Bytes 8 and 9 are Address 40 | sendBuffer[8+offset] = (unsigned char)((startReg >> 8) & 0xff); 41 | sendBuffer[9+offset] = (unsigned char)(startReg & 0xff); 42 | 43 | //Bytes 10 and 11 are NumRegs 44 | sendBuffer[10+offset] = (unsigned char)((numRegs >> 8) & 0xff); 45 | sendBuffer[11+offset] = (unsigned char)(numRegs & 0xff); 46 | 47 | return 9+(numRegs*2); 48 | 49 | } 50 | 51 | float parseFPRegisterResponse(unsigned char* recBuffer, int offset) { 52 | unsigned char fBuffer[4]; 53 | float* fPointer; 54 | 55 | fBuffer[0] = recBuffer[offset + 3]; 56 | fBuffer[1] = recBuffer[offset + 2]; 57 | fBuffer[2] = recBuffer[offset + 1]; 58 | fBuffer[3] = recBuffer[offset]; 59 | 60 | fPointer = (float*)fBuffer; 61 | 62 | return *fPointer; 63 | } 64 | 65 | int parseIntRegisterResponse(unsigned char* recBuffer, int offset) { 66 | unsigned char iBuffer[4]; 67 | int* iPointer; 68 | 69 | iBuffer[0] = recBuffer[offset + 3]; 70 | iBuffer[1] = recBuffer[offset + 2]; 71 | iBuffer[2] = recBuffer[offset + 1]; 72 | iBuffer[3] = recBuffer[offset]; 73 | 74 | iPointer = (int*)iBuffer; 75 | 76 | return *iPointer; 77 | } 78 | 79 | short parseShortRegisterResponse(unsigned char* recBuffer, int offset) { 80 | unsigned char sBuffer[4]; 81 | short* sPointer; 82 | 83 | sBuffer[0] = recBuffer[offset + 1]; 84 | sBuffer[1] = recBuffer[offset]; 85 | 86 | sPointer = (short*)sBuffer; 87 | 88 | return *sPointer; 89 | } 90 | 91 | int buildWriteHoldingRegistersPacket(unsigned char* sendBuffer, int startReg, int numRegs, int unitId, int prependZeros) { 92 | int offset = 0; 93 | 94 | if(prependZeros != 0){ 95 | sendBuffer[0] = 0; 96 | sendBuffer[1] = 0; 97 | offset = 2; 98 | } 99 | 100 | // Bytes 0 and 1 are TransID 101 | sendBuffer[0+offset] = (unsigned char)((nextTransactionId >> 8) & 0xff); 102 | sendBuffer[1+offset] = (unsigned char)(nextTransactionId & 0xff); 103 | nextTransactionId++; 104 | 105 | // Bytes 2 and 3 are ProtocolID, set to 0 106 | sendBuffer[2+offset] = 0; 107 | sendBuffer[3+offset] = 0; 108 | 109 | // Bytes 4 and 5 are length. 110 | sendBuffer[4+offset] = 0; 111 | sendBuffer[5+offset] = 7 + (numRegs * 2); 112 | 113 | // Byte 6 is Unit ID. 114 | sendBuffer[6+offset] = unitId; 115 | 116 | // Byte 7 is Read Holding Registers ( function # 3 ) 117 | sendBuffer[7+offset] = 16; 118 | 119 | // Bytes 8 and 9 are Address 120 | sendBuffer[8+offset] = (unsigned char)((startReg >> 8) & 0xff); 121 | sendBuffer[9+offset] = (unsigned char)(startReg & 0xff); 122 | 123 | // Bytes 10 and 11 are NumRegs 124 | sendBuffer[10+offset] = (unsigned char)((numRegs >> 8) & 0xff); 125 | sendBuffer[11+offset] = (unsigned char)(numRegs & 0xff); 126 | 127 | // Byte 12 is Byte Count, or 2 * numReg 128 | sendBuffer[12+offset] = (unsigned char)((numRegs * 2) & 0xff); 129 | 130 | // The rest of the bytes are up to the user. 131 | 132 | return 12; // Write Registers always return 12 bytes. 133 | 134 | } 135 | 136 | int putFPIntoBuffer( unsigned char* sendBuffer, int offset, float value) { 137 | unsigned char* bPointer; 138 | 139 | bPointer = (unsigned char*)&value; 140 | 141 | sendBuffer[offset] = bPointer[3]; 142 | sendBuffer[offset+1] = bPointer[2]; 143 | sendBuffer[offset+2] = bPointer[1]; 144 | sendBuffer[offset+3] = bPointer[0]; 145 | 146 | return 0; 147 | } 148 | 149 | int putIntIntoBuffer( unsigned char* sendBuffer, int offset, int value ) { 150 | unsigned char* bPointer; 151 | 152 | bPointer = (unsigned char*)&value; 153 | 154 | sendBuffer[offset] = bPointer[3]; 155 | sendBuffer[offset+1] = bPointer[2]; 156 | sendBuffer[offset+2] = bPointer[1]; 157 | sendBuffer[offset+3] = bPointer[0]; 158 | 159 | return 0; 160 | } 161 | 162 | int putShortIntoBuffer( unsigned char* sendBuffer, int offset, short value ) { 163 | unsigned char* bPointer; 164 | 165 | bPointer = (unsigned char*)&value; 166 | 167 | sendBuffer[offset] = bPointer[1]; 168 | sendBuffer[offset+1] = bPointer[0]; 169 | 170 | return 0; 171 | } -------------------------------------------------------------------------------- /examples/U12/u12AISample.c: -------------------------------------------------------------------------------- 1 | /* 2 | An example that shows a minimal use of Exodriver without the use of functions 3 | hidden in header files. 4 | 5 | You can compile this example with the following command: 6 | $ g++ -lm -llabjackusb u12AISample.c 7 | 8 | It is also included in the Makefile. 9 | 10 | */ 11 | 12 | /* Includes */ 13 | #include 14 | #include 15 | #include 16 | #include "labjackusb.h" 17 | #include 18 | 19 | // All U12 commands are 8 bytes. 20 | #define U12_COMMAND_LENGTH 8 21 | 22 | /* LabJack Related Helper Functions Protoypes */ 23 | 24 | int writeRead(HANDLE devHandle, BYTE * sendBuffer, BYTE * recBuffer ); 25 | 26 | // Demonstrates how to build the AIStream packet. 27 | void buildAISampleBytes(BYTE * sendBuffer); 28 | 29 | // Demonstrates how to parse the response of AIStream. 30 | void parseAISampleBytes(BYTE * recBuffer); 31 | 32 | int main() { 33 | // Setup the variables we will need. 34 | int r = 0; // For checking return values 35 | HANDLE devHandle = 0; 36 | BYTE sendBuffer[U12_COMMAND_LENGTH], recBuffer[U12_COMMAND_LENGTH]; 37 | 38 | // Open the U12 39 | devHandle = LJUSB_OpenDevice(1, 0, U12_PRODUCT_ID); 40 | 41 | if( devHandle == NULL ) { 42 | printf("Couldn't open U12. Please connect one and try again.\n"); 43 | exit(-1); 44 | } 45 | 46 | // Builds the AISample command 47 | buildAISampleBytes(sendBuffer); 48 | 49 | // Write the command, and read the response. 50 | r = writeRead(devHandle, sendBuffer, recBuffer ); 51 | 52 | // If the U12 is freshly plugged in, then it will not respond to the 53 | // first command. Write it again. 54 | if( r == -1){ 55 | r = writeRead(devHandle, sendBuffer, recBuffer ); 56 | 57 | if(r != 0){ 58 | // If you still have errors after the first try, then you have 59 | // bigger problems. 60 | printf("Command timed out twice. Exiting..."); 61 | LJUSB_CloseDevice(devHandle); 62 | exit(-1); 63 | } 64 | } 65 | 66 | // Parse the response into something useful 67 | parseAISampleBytes(recBuffer); 68 | 69 | //Close the device. 70 | LJUSB_CloseDevice(devHandle); 71 | 72 | return 0; 73 | } 74 | 75 | /* ------------- LabJack Related Helper Functions Definitions ------------- */ 76 | 77 | int writeRead(HANDLE devHandle, BYTE * sendBuffer, BYTE * recBuffer ) { 78 | int r = 0; 79 | 80 | // Write the command to the device. 81 | // LJUSB_Write( handle, sendBuffer, length of sendBuffer ) 82 | r = LJUSB_Write( devHandle, sendBuffer, U12_COMMAND_LENGTH ); 83 | 84 | if( r != U12_COMMAND_LENGTH ) { 85 | printf("An error occurred when trying to write the buffer. The error was: %d\n", errno); 86 | // *Always* close the device when you error out. 87 | LJUSB_CloseDevice(devHandle); 88 | exit(-1); 89 | } 90 | 91 | // Read the result from the device. 92 | // LJUSB_Read( handle, recBuffer, number of bytes to read) 93 | r = LJUSB_Read( devHandle, recBuffer, U12_COMMAND_LENGTH ); 94 | 95 | if( r != U12_COMMAND_LENGTH ) { 96 | if(errno == LIBUSB_ERROR_TIMEOUT) { 97 | return -1; 98 | } 99 | 100 | printf("An error occurred when trying to read from the U12. The error was: %d\n", errno); 101 | LJUSB_CloseDevice(devHandle); 102 | exit(-1); 103 | } 104 | 105 | return 0; 106 | } 107 | 108 | 109 | // Uses information from section 5.1 of the U12 User's Guide to make a AISample 110 | // packet. 111 | // http://labjack.com/support/u12/users-guide/5.1 112 | void buildAISampleBytes(BYTE * sendBuffer) { 113 | // Build up the bytes 114 | sendBuffer[0] = 8; // Set PGAMUX for single-ended AI0 115 | sendBuffer[1] = 9; // Set PGAMUX for single-ended AI1 116 | sendBuffer[2] = 10; // Set PGAMUX for single-ended AI2 117 | sendBuffer[3] = 11; // Set PGAMUX for single-ended AI3 118 | sendBuffer[4] = 1; // UpdateIO = 0, LEDState = 1 119 | sendBuffer[5] = 192; // 0b11000000 = (AISample) 120 | sendBuffer[6] = 0; // XXXXXXXX 121 | sendBuffer[7] = 0; // Echo Value 122 | 123 | // The bytes have been set. We are ready to write to the U12. 124 | } 125 | 126 | // Parses the AISample packet into something useful. 127 | void parseAISampleBytes(BYTE * recBuffer){ 128 | int temp; 129 | double ai0, ai1, ai2, ai3; 130 | 131 | // Apply the single-ended conversion to results 132 | temp = (recBuffer[2] >> 4) & 0xf; 133 | temp = (temp << 8) + recBuffer[3]; 134 | ai0 = ((double)temp * 20.0 / 4096.0) - 10; 135 | 136 | temp = recBuffer[2] & 0xf; 137 | temp = (temp << 8) + recBuffer[4]; 138 | ai1 = ((double)temp * 20.0 / 4096.0) - 10; 139 | 140 | temp = (recBuffer[5] >> 4) & 0xf; 141 | temp = (temp << 8) + recBuffer[6]; 142 | ai2 = ((double)temp * 20.0 / 4096.0) - 10; 143 | 144 | temp = recBuffer[5] & 0xf; 145 | temp = (temp << 8) + recBuffer[7]; 146 | ai3 = ((double)temp * 20.0 / 4096.0) - 10; 147 | 148 | printf("Results of AISample:\n"); 149 | printf(" AI0 = %f\n", ai0); 150 | printf(" AI1 = %f\n", ai1); 151 | printf(" AI2 = %f\n", ai2); 152 | printf(" AI3 = %f\n", ai3); 153 | printf(" PGA Overvoltage = %d\n", (recBuffer[0] >> 4) & 1); 154 | printf(" IO3 to IO0 States = %d\n", recBuffer[0] & 15); 155 | printf(" TimerCounterMask = %d\n", recBuffer[22]); 156 | 157 | } -------------------------------------------------------------------------------- /examples/UE9/ue9Feedback.c: -------------------------------------------------------------------------------- 1 | //Author: LabJack 2 | //May 25, 2011 3 | //This example program calls the Feedback low-level function. DAC0 will be set 4 | //to 2.5 volts and DAC1 will be set to 3.5 volts. The states and directions 5 | //will be read from FIO0 - FIO3 and the voltages (calibrated) from AI0-AI3. 6 | 7 | #include "ue9.h" 8 | 9 | 10 | int feedback_example(HANDLE hDevice, ue9CalibrationInfo *caliInfo); 11 | 12 | int main(int argc, char **argv) 13 | { 14 | HANDLE hDevice; 15 | ue9CalibrationInfo caliInfo; 16 | 17 | //Opening first found UE9 over USB 18 | if( (hDevice = openUSBConnection(-1)) == NULL ) 19 | goto done; 20 | 21 | //Getting calibration information from UE9 22 | if( getCalibrationInfo(hDevice, &caliInfo) < 0 ) 23 | goto close; 24 | 25 | feedback_example(hDevice, &caliInfo); 26 | 27 | close: 28 | closeUSBConnection(hDevice); 29 | done: 30 | return 0; 31 | } 32 | 33 | //Sends a Feedback low-level command to set DAC0, DAC1, read FIO0-FIO3 and 34 | //AI0-AI3. 35 | int feedback_example(HANDLE hDevice, ue9CalibrationInfo *caliInfo) 36 | { 37 | uint8 sendBuff[34], recBuff[64], ainResolution, gainBip; 38 | uint16 checksumTotal, bytesVoltage; 39 | uint32 tempDir, tempState; 40 | int sendChars, recChars, i; 41 | double voltage; 42 | 43 | ainResolution = 12; 44 | //ainResolution = 18; //high-res mode for UE9 Pro only 45 | gainBip = 0; //(Gain = 1, Bipolar = 0) 46 | 47 | sendBuff[1] = (uint8)(0xF8); //Command byte 48 | sendBuff[2] = (uint8)(0x0E); //Number of data words 49 | sendBuff[3] = (uint8)(0x00); //Extended command number 50 | 51 | //All these bytes are set to zero since we are not changing the FIO, EIO, CIO 52 | //and MIO directions and states 53 | for( i = 6; i <= 15; i++ ) 54 | sendBuff[i] = (uint8)(0x00); 55 | 56 | if( getDacBinVoltCalibrated(caliInfo, 0, 2.500, &bytesVoltage) < 0 ) 57 | return -1; 58 | 59 | //setting the voltage of DAC0 60 | sendBuff[16] = (uint8)( bytesVoltage & (0x00FF) ); //low bits of DAC0 61 | sendBuff[17] = (uint8)( bytesVoltage / 256 ) + 192; //high bits of DAC0 62 | //(bit 7 : Enable, 63 | // bit 6: Update) 64 | if( getDacBinVoltCalibrated(caliInfo, 1, 3.500, &bytesVoltage) < 0 ) 65 | return -1; 66 | 67 | //setting the voltage of DAC1 68 | sendBuff[18] = (uint8)( bytesVoltage & (0x00FF) ); //low bits of DAC1 69 | sendBuff[19] = (uint8)( bytesVoltage / 256 ) + 192; //high bits of DAC1 70 | //(bit 7 : Enable, 71 | // bit 6: Update) 72 | sendBuff[20] = (uint8)(0x0f); //AINMask - reading AIN0-AIN3, not AIN4-AIN7 73 | sendBuff[21] = (uint8)(0x00); //AINMask - not reading AIN8-AIN15 74 | sendBuff[22] = (uint8)(0x00); //AIN14ChannelNumber - not using 75 | sendBuff[23] = (uint8)(0x00); //AIN15ChannelNumber - not using 76 | sendBuff[24] = ainResolution; //Resolution = 12 77 | 78 | //Setting BipGains 79 | for( i = 25; i < 34; i++ ) 80 | sendBuff[i] = gainBip; 81 | 82 | extendedChecksum(sendBuff, 34); 83 | 84 | //Sending command to UE9 85 | sendChars = LJUSB_Write(hDevice, sendBuff, 34); 86 | if( sendChars < 34 ) 87 | { 88 | if( sendChars == 0 ) 89 | printf("Error : write failed\n"); 90 | else 91 | printf("Error : did not write all of the buffer\n"); 92 | return -1; 93 | } 94 | 95 | //Reading response from UE9 96 | recChars = LJUSB_Read(hDevice, recBuff, 64); 97 | if( recChars < 64 ) 98 | { 99 | if( recChars == 0 ) 100 | printf("Error : read failed\n"); 101 | else 102 | printf("Error : did not read all of the buffer\n"); 103 | return -1; 104 | } 105 | 106 | checksumTotal = extendedChecksum16(recBuff, 64); 107 | if( (uint8)((checksumTotal / 256) & 0xff) != recBuff[5] ) 108 | { 109 | printf("Error : read buffer has bad checksum16(MSB)\n"); 110 | return -1; 111 | } 112 | 113 | if( (uint8)(checksumTotal & 0xff) != recBuff[4]) 114 | { 115 | printf("Error : read buffer has bad checksum16(LSB)\n"); 116 | return -1; 117 | } 118 | 119 | if( extendedChecksum8(recBuff) != recBuff[0] ) 120 | { 121 | printf("Error : read buffer has bad checksum8\n"); 122 | return -1; 123 | } 124 | 125 | if( recBuff[1] != (uint8)(0xF8) || recBuff[2] != (uint8)(0x1D) || recBuff[3] != (uint8)(0x00) ) 126 | { 127 | printf("Error : read buffer has wrong command bytes \n"); 128 | return -1; 129 | } 130 | 131 | printf("Set DAC0 to 2.500 volts and DAC1 to 3.500 volts.\n\n"); 132 | printf("Flexible digital I/O directions and states (FIO0 - FIO3):\n"); 133 | for( i = 0; i < 4; i++ ) 134 | { 135 | tempDir = ( (uint32)(recBuff[6] / pow(2, i)) & (0x01) ); 136 | tempState = ( (uint32)(recBuff[7] / pow(2, i)) & (0x01) ); 137 | printf(" FI%d: %u and %u\n", i, tempDir, tempState); 138 | } 139 | 140 | printf("\nAnalog Inputs (AI0 - AI3):\n"); 141 | for( i = 0; i < 4; i++ ) 142 | { 143 | bytesVoltage = recBuff[12 + 2*i] + recBuff[13 + 2*i]*256; 144 | 145 | //getting analog voltage 146 | if( getAinVoltCalibrated(caliInfo, gainBip, ainResolution, bytesVoltage, &voltage) < 0 ) 147 | return -1; 148 | 149 | printf(" AI%d: %.4f V\n", i, voltage); 150 | } 151 | printf("\n"); 152 | 153 | return 0; 154 | } 155 | -------------------------------------------------------------------------------- /examples/UE9/ue9ControlConfig.c: -------------------------------------------------------------------------------- 1 | //Author: LabJack 2 | //May 25, 2011 3 | //This example program sends a ControlConfig low-level command, and reads the 4 | //various parameters associated with the Control processor. 5 | 6 | #include "ue9.h" 7 | 8 | 9 | int controlConfig_example(HANDLE hDevice, ue9CalibrationInfo *caliInfo); 10 | 11 | int main(int argc, char **argv) 12 | { 13 | HANDLE hDevice; 14 | ue9CalibrationInfo caliInfo; 15 | 16 | //Opening first found UE9 over USB 17 | if( (hDevice = openUSBConnection(-1)) == NULL ) 18 | goto done; 19 | 20 | //Getting calibration information from UE9 21 | if(getCalibrationInfo(hDevice, &caliInfo) < 0) 22 | goto close; 23 | 24 | controlConfig_example(hDevice, &caliInfo); 25 | 26 | close: 27 | closeUSBConnection(hDevice); 28 | done: 29 | return 0; 30 | } 31 | 32 | //Sends a ControlConfig low-level command to read the configuration settings 33 | //associated with the Control chip. 34 | int controlConfig_example(HANDLE hDevice, ue9CalibrationInfo *caliInfo) 35 | { 36 | uint8 sendBuff[18], recBuff[24]; 37 | uint16 checksumTotal; 38 | int sendChars, recChars, i; 39 | double dac; 40 | 41 | sendBuff[1] = (uint8)(0xF8); //Command byte 42 | sendBuff[2] = (uint8)(0x06); //Number of data words 43 | sendBuff[3] = (uint8)(0x08); //Extended command number 44 | 45 | //WriteMask, PowerLevel, FIODir, etc. are all passed a value of zero since 46 | //we only want to read Control configuration settings, not change them. 47 | for( i = 6; i < 18; i++ ) 48 | sendBuff[i] = (uint8)(0x00); 49 | 50 | extendedChecksum(sendBuff,18); 51 | 52 | //Sending command to UE9 53 | sendChars = LJUSB_Write(hDevice, sendBuff, 18); 54 | if( sendChars < 18 ) 55 | { 56 | if( sendChars == 0 ) 57 | printf("Error : write failed\n"); 58 | else 59 | printf("Error : did not write all of the buffer\n"); 60 | return -1; 61 | } 62 | 63 | //Reading response from UE9 64 | recChars = LJUSB_Read(hDevice, recBuff, 24); 65 | if( recChars < 24 ) 66 | { 67 | if( recChars == 0 ) 68 | printf("Error : read failed\n"); 69 | else 70 | printf("Error : did not read all of the buffer\n"); 71 | return -1; 72 | } 73 | 74 | checksumTotal = extendedChecksum16(recBuff, 24); 75 | if( (uint8)((checksumTotal >> 8) & 0xff) != recBuff[5] ) 76 | { 77 | printf("Error : read buffer has bad checksum16(MSB)\n"); 78 | return -1; 79 | } 80 | 81 | if( (uint8)(checksumTotal & 0xff) != recBuff[4] ) 82 | { 83 | printf("Error : read buffer has bad checksum16(LSB)\n"); 84 | return -1; 85 | } 86 | 87 | if( extendedChecksum8(recBuff) != recBuff[0] ) 88 | { 89 | printf("Error : read buffer has bad checksum8\n"); 90 | return -1; 91 | } 92 | 93 | if( recBuff[1] != (uint8)(0xF8) || recBuff[2] != (uint8)(0x09) || recBuff[3] != (uint8)(0x08) ) 94 | { 95 | printf("Error : read buffer has wrong command bytes \n"); 96 | return -1; 97 | } 98 | 99 | if( recBuff[6] != 0 ) 100 | { 101 | printf("Errorcode (byte 6): %d\n", (unsigned int)recBuff[6]); 102 | return -1; 103 | } 104 | 105 | printf("PowerLevel default (byte 7): %d\n", (unsigned int)recBuff[7]); 106 | printf("ResetSource (byte 8): %d\n", (unsigned int)recBuff[8]); 107 | printf("ControlFW Version (bytes 9 and 10): %.3f\n", (unsigned int)recBuff[10] + (double)recBuff[9]/100.0); 108 | printf("ControlBL Version (bytes 11 and 12): %.3f\n", (unsigned int)recBuff[12] + (double)recBuff[11]/100.0); 109 | printf("FIO default directions and states (bytes 14 and 15):\n"); 110 | 111 | for( i = 0; i < 8; i++ ) 112 | printf(" FIO%d: %d and %d\n", i,( (unsigned int)recBuff[14] << (31 - i) ) >> 31, ( (unsigned int)recBuff[15] << (31 - i) ) >> 31); 113 | 114 | printf("EIO default directions and states (bytes 16 and 17):\n"); 115 | 116 | for( i = 0; i < 8; i++ ) 117 | printf(" EIO%d: %d and %d\n", i, ( (unsigned int)recBuff[16] << (31 - i) ) >> 31, ( (unsigned int)recBuff[17] << (31 - i) ) >> 31); 118 | 119 | printf("CIO default directions and states (byte 18):\n"); 120 | 121 | for( i = 0; i <= 3; i++ ) 122 | printf(" CIO%d: %d and %d\n", i, ( (unsigned int)recBuff[18] << (27 - i) ) >> 31, ( (unsigned int)recBuff[18] << (31 - i) ) >> 31); 123 | 124 | printf("MIO default directions and states (byte 19):\n"); 125 | 126 | for( i = 0; i <= 2; i++ ) 127 | printf(" MIO%d: %d and %d\n", i, ( (unsigned int)recBuff[19] << (27 - i) ) >> 31, ( (unsigned int)recBuff[19] << (31 - i) ) >> 31); 128 | 129 | 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); 130 | 131 | //Getting DAC0 binary value 132 | dac = (double)( (unsigned int)recBuff[20] + (( (unsigned int)recBuff[21] << 28 ) >> 20) ); 133 | 134 | //Getting DAC0 analog value ( Volts = (Bits - Offset)/Slope ) 135 | dac = (dac - caliInfo->ccConstants[11])/caliInfo->ccConstants[10]; 136 | printf(" Voltage: %.3f V\n", dac); 137 | 138 | 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); 139 | 140 | //getting DAC1 binary value 141 | dac = (double)( (unsigned int)recBuff[22] + (( (unsigned int)recBuff[23] << 28 ) >> 20) ); 142 | 143 | //getting DAC1 analog value ( Volts = (Bits - Offset)/Slope ) 144 | dac = (dac - caliInfo->ccConstants[13])/caliInfo->ccConstants[12]; 145 | printf(" Voltage: %.3f V\n", dac); 146 | 147 | return 0; 148 | } 149 | -------------------------------------------------------------------------------- /examples/U6/u6EFunctions.c: -------------------------------------------------------------------------------- 1 | //Author: LabJack 2 | //April 12, 2016 3 | //This example demonstrates with the "easy" functions how to set an analog 4 | //output (DAC), read an analog input (AIN), set a digital output, read a 5 | //digital input, and configure/update/read timers and counters. 6 | 7 | #include "u6.h" 8 | #include 9 | 10 | int main(int argc, char **argv) 11 | { 12 | HANDLE hDevice; 13 | u6CalibrationInfo caliInfo; 14 | int localID; 15 | long error; 16 | double dblVoltage; 17 | long lngState; 18 | long lngTCPinOffset; 19 | long lngTimerClockBaseIndex; 20 | long lngTimerClockDivisor; 21 | long alngEnableTimers[4]; 22 | long alngTimerModes[4]; 23 | double adblTimerValues[4]; 24 | long alngEnableCounters[2]; 25 | long alngReadTimers[4]; 26 | long alngUpdateResetTimers[4]; 27 | long alngReadCounters[2]; 28 | long alngResetCounters[2]; 29 | double adblCounterValues[2]; 30 | double highTime; 31 | double lowTime; 32 | double dutyCycle; 33 | 34 | //Open first found U6 over USB 35 | localID = -1; 36 | hDevice = openUSBConnection(localID); 37 | if( hDevice == NULL ) 38 | goto done; 39 | 40 | //Get calibration information from U6 41 | error = getCalibrationInfo(hDevice, &caliInfo); 42 | if( error < 0 ) 43 | goto close; 44 | 45 | 46 | //Set DAC0 to 3.1 volts. 47 | printf("Calling eDAC to set DAC0 to 3.1 V\n"); 48 | error = eDAC(hDevice, &caliInfo, 0, 3.1, 0, 0, 0); 49 | if( error != 0 ) 50 | goto close; 51 | 52 | 53 | //Read AIN3 single-ended voltage. +/-10 volt range and default resolution (0). 54 | printf("\nCalling eAIN to read AIN3 voltage\n"); 55 | dblVoltage = 0.0; 56 | error = eAIN(hDevice, &caliInfo, 3, 15, &dblVoltage, LJ_rgBIP10V, 0, 0, 0, 0, 0); 57 | if( error != 0 ) 58 | goto close; 59 | printf("AIN3 value = %.3f\n", dblVoltage); 60 | 61 | 62 | //Set FIO2 to output-high 63 | printf("\nCalling eDO to set FIO2 to output-high\n"); 64 | error = eDO(hDevice, 2, 1); 65 | if( error != 0 ) 66 | goto close; 67 | 68 | 69 | //Read FIO3 state 70 | printf("\nCalling eDI to read FIO3 state\n"); 71 | lngState = 0; 72 | error = eDI(hDevice, 3, &lngState); 73 | if( error != 0 ) 74 | goto close; 75 | printf("FIO3 state = %ld\n", lngState); 76 | 77 | 78 | //Enable and configure 1 output timer, 1 input timer, and 79 | //1 counter 80 | printf("\nCalling eTCConfig to enable and configure 1 output timer (Timer0), 1 input timer (Timer1), and 1 counter (Counter1)\n"); 81 | alngEnableTimers[0] = 1; //Enable Timer0 (uses FIO0) 82 | alngEnableTimers[1] = 1; //Enable Timer1 (uses FIO1) 83 | alngEnableTimers[2] = 0; //Disable Timer2 84 | alngEnableTimers[3] = 0; //Disable Timer3 85 | alngEnableCounters[0] = 0; //Disable Counter0 86 | alngEnableCounters[1] = 1; //Enable Counter1 (uses FIO3) 87 | lngTCPinOffset = 0; //Offset is 0, so timers/counters start at FIO0 88 | lngTimerClockBaseIndex = LJ_tc48MHZ_DIV; //Base clock is 48 MHz with divisor support, so Counter0 is disabled 89 | lngTimerClockDivisor = 48; //Base clock divisor. Makes the clock 1 MHz. 90 | alngTimerModes[0] = LJ_tmPWM8; //Timer0 is 8-bit PWM output. Frequency is 1M/256 = 3906. 91 | alngTimerModes[1] = LJ_tmDUTYCYCLE; //Timer1 is duty cycle 92 | alngTimerModes[2] = 0; 93 | alngTimerModes[3] = 0; 94 | adblTimerValues[0] = 16384; //Set PWM8 duty-cycle to 75%. 95 | adblTimerValues[1] = 0; 96 | adblTimerValues[2] = 0; 97 | adblTimerValues[3] = 0; 98 | error = eTCConfig(hDevice, alngEnableTimers, alngEnableCounters, lngTCPinOffset, lngTimerClockBaseIndex, lngTimerClockDivisor, alngTimerModes, adblTimerValues, 0, 0); 99 | if( error != 0 ) 100 | goto close; 101 | 102 | printf("\nWaiting for 1 second...\n"); 103 | sleep(1); 104 | 105 | //Update the value (duty-cycle) of output timer (Timer0), 106 | //read and reset the input timer (Timer1), and 107 | //read and reset the counter (Counter1). 108 | printf("\nCalling eTCValues to update the value (duty-cycle) of output Timer0, read/reset input Timer1, and read/reset Counter1\n"); 109 | alngReadTimers[0] = 0; //Don't read Timer0 (output timer) 110 | alngReadTimers[1] = 1; //Read Timer1 111 | alngReadTimers[2] = 0; 112 | alngReadTimers[3] = 0; 113 | alngUpdateResetTimers[0] = 1; //Update Timer0 114 | alngUpdateResetTimers[1] = 1; //Reset Timer1 115 | alngUpdateResetTimers[2] = 0; 116 | alngUpdateResetTimers[3] = 0; 117 | alngReadCounters[0] = 0; 118 | alngReadCounters[1] = 1; //Read Counter1 119 | alngResetCounters[0] = 0; 120 | alngResetCounters[1] = 1; //Reset Counter1 121 | adblTimerValues[0] = 32768; //Change Timer0 duty-cycle to 50% 122 | adblTimerValues[1] = 0; 123 | adblTimerValues[2] = 0; 124 | adblTimerValues[3] = 0; 125 | adblCounterValues[0] = 0; 126 | adblCounterValues[1] = 0; 127 | error = eTCValues(hDevice, alngReadTimers, alngUpdateResetTimers, alngReadCounters, alngResetCounters, adblTimerValues, adblCounterValues, 0, 0); 128 | if( error != 0 ) 129 | goto close; 130 | 131 | //Convert Timer1 value to duty-cycle percentage 132 | //High time is LSW 133 | highTime = (double)((unsigned long)adblTimerValues[1]%65536); 134 | //Low time is MSW 135 | lowTime = (double)((unsigned long)adblTimerValues[1]/65536); 136 | //Duty cycle percentage 137 | dutyCycle = 100*highTime/(highTime + lowTime); 138 | printf("Timer1 value = %.0f\n", adblTimerValues[1]); 139 | printf(" High Clicks = %.0f\n", highTime); 140 | printf(" Low Clicks = %.0f\n", lowTime); 141 | printf(" Duty Cycle = %.1f%%\n", dutyCycle); 142 | printf("Counter1 value = %.0f\n", adblCounterValues[1]); 143 | 144 | //Disable all timers and counters 145 | alngEnableTimers[0] = 0; 146 | alngEnableTimers[1] = 0; 147 | alngEnableTimers[2] = 0; 148 | alngEnableTimers[3] = 0; 149 | alngEnableCounters[0] = 0; 150 | alngEnableCounters[1] = 0; 151 | error = eTCConfig(hDevice, alngEnableTimers, alngEnableCounters, 0, LJ_tc48MHZ, 0, alngTimerModes, adblTimerValues, 0, 0); 152 | if( error != 0 ) 153 | goto close; 154 | printf("\nCalling eTCConfig to disable all timers and counters\n"); 155 | 156 | close: 157 | if( error > 0 ) 158 | printf("Received an error code of %ld\n", error); 159 | closeUSBConnection(hDevice); 160 | 161 | done: 162 | return 0; 163 | } 164 | 165 | -------------------------------------------------------------------------------- /examples/UE9/ue9EFunctions.c: -------------------------------------------------------------------------------- 1 | //Author: LabJack 2 | //April 12, 2016 3 | //This example demonstrates with the "easy" functions how to set an analog 4 | //output (DAC), read an analog input (AIN), set a digital output, read a 5 | //digital input, and configure/update/read timers and counters. 6 | 7 | #include "ue9.h" 8 | #include 9 | 10 | int main(int argc, char **argv) 11 | { 12 | HANDLE hDevice; 13 | ue9CalibrationInfo caliInfo; 14 | int localID; 15 | int i; 16 | long error; 17 | double dblVoltage; 18 | long lngState; 19 | long lngTimerClockBaseIndex; 20 | long lngTimerClockDivisor; 21 | long alngEnableTimers[6]; 22 | long alngTimerModes[6]; 23 | double adblTimerValues[6]; 24 | long alngEnableCounters[2]; 25 | long alngReadTimers[6]; 26 | long alngUpdateResetTimers[6]; 27 | long alngReadCounters[2]; 28 | long alngResetCounters[2]; 29 | double adblCounterValues[2]; 30 | double highTime; 31 | double lowTime; 32 | double dutyCycle; 33 | 34 | //Open first found UE9 over USB 35 | localID = -1; 36 | hDevice = openUSBConnection(localID); 37 | if( hDevice == NULL ) 38 | goto done; 39 | 40 | //Get calibration information from UE9 41 | error = getCalibrationInfo(hDevice, &caliInfo); 42 | if( error < 0 ) 43 | goto close; 44 | 45 | 46 | //Set DAC0 to 3.1 volts. 47 | printf("Calling eDAC to set DAC0 to 3.1 V\n"); 48 | error = eDAC(hDevice, &caliInfo, 0, 3.1, 0, 0, 0); 49 | if( error != 0 ) 50 | goto close; 51 | 52 | 53 | //Read AIN3 voltage. 0-5 volt range and 12-bit resolution. 54 | printf("\nCalling eAIN to read AIN3 voltage\n"); 55 | dblVoltage = 0.0; 56 | error = eAIN(hDevice, &caliInfo, 3, 0, &dblVoltage, LJ_rgUNI5V, 12, 0, 0, 0, 0); 57 | if( error != 0 ) 58 | goto close; 59 | printf("\nAIN3 value = %.3f\n", dblVoltage); 60 | 61 | 62 | //Set FIO2 to output-high 63 | printf("\nCalling eDO to set FIO2 to output-high\n"); 64 | error = eDO(hDevice, 2, 1); 65 | if( error != 0 ) 66 | goto close; 67 | 68 | 69 | //Read state of FIO3 70 | printf("\nCalling eDI to read FIO3 state\n"); 71 | lngState = 0; 72 | error = eDI(hDevice, 3, &lngState); 73 | if( error != 0 ) 74 | goto close; 75 | printf("FIO3 state = %ld\n", lngState); 76 | 77 | 78 | //Enable and configure 1 output timer, 1 input timer, and 79 | //1 counter 80 | printf("\nCalling eTCConfig to enable and configure 1 output timer (Timer0), 1 input timer (Timer1), and 1 counter (Counter1)\n"); 81 | alngEnableTimers[0] = 1; //Enable Timer0 (uses FIO0) 82 | alngEnableTimers[1] = 1; //Enable Timer1 (uses FIO1) 83 | alngEnableTimers[2] = 0; //Disable Timer2 84 | alngEnableTimers[3] = 0; //Disable Timer3 85 | alngEnableTimers[4] = 0; //Disable Timer4 86 | alngEnableTimers[5] = 0; //Disable Timer5 87 | alngEnableCounters[0] = 0; //Disable Counter0 88 | alngEnableCounters[1] = 1; //Enable Counter1 (uses FIO3) 89 | lngTimerClockBaseIndex = LJ_tcSYS; //Base clock is System (48 MHz) 90 | lngTimerClockDivisor = 48; //Base clock divisor. Makes the clock 1 MHz. 91 | alngTimerModes[0] = LJ_tmPWM8; //Timer0 is 8-bit PWM output. Frequency is 1M/256 = 3906. 92 | alngTimerModes[1] = LJ_tmDUTYCYCLE; //Timer1 is duty cycle 93 | alngTimerModes[2] = 0; 94 | alngTimerModes[3] = 0; 95 | alngTimerModes[4] = 0; 96 | alngTimerModes[5] = 0; 97 | adblTimerValues[0] = 16384; //Set PWM8 duty-cycle to 75%. 98 | adblTimerValues[1] = 0; 99 | adblTimerValues[2] = 0; 100 | adblTimerValues[3] = 0; 101 | adblTimerValues[4] = 0; 102 | adblTimerValues[5] = 0; 103 | error = eTCConfig(hDevice, alngEnableTimers, alngEnableCounters, 0, lngTimerClockBaseIndex, lngTimerClockDivisor, alngTimerModes, adblTimerValues, 0, 0); 104 | if( error != 0 ) 105 | goto close; 106 | 107 | printf("\nWaiting for 1 second...\n"); 108 | sleep(1); 109 | 110 | //Update the value (duty-cycle) of output timer (Timer0), 111 | //read and reset the input timer (Timer1), and 112 | //read and reset the counter (Counter1). 113 | printf("\nCalling eTCValues to update the value (duty-cycle) of output Timer0, read/reset input Timer1, and read/reset Counter1\n"); 114 | alngReadTimers[0] = 0; //Don't read Timer0 (output timer) 115 | alngReadTimers[1] = 1; //Read Timer1 116 | alngReadTimers[2] = 0; 117 | alngReadTimers[3] = 0; 118 | alngReadTimers[4] = 0; 119 | alngReadTimers[5] = 0; 120 | alngUpdateResetTimers[0] = 1; //Update Timer0 121 | alngUpdateResetTimers[1] = 1; //Reset Timer1 122 | alngUpdateResetTimers[2] = 0; 123 | alngUpdateResetTimers[3] = 0; 124 | alngUpdateResetTimers[4] = 0; 125 | alngUpdateResetTimers[5] = 0; 126 | alngReadCounters[0] = 0; 127 | alngReadCounters[1] = 1; //Read Counter1 128 | alngResetCounters[0] = 0; 129 | alngResetCounters[1] = 1; //Reset Counter1 130 | adblTimerValues[0] = 32768; //Change Timer0 duty-cycle to 50% 131 | adblTimerValues[1] = 0; 132 | adblTimerValues[2] = 0; 133 | adblTimerValues[3] = 0; 134 | adblTimerValues[4] = 0; 135 | adblTimerValues[5] = 0; 136 | adblCounterValues[0] = 0; 137 | adblCounterValues[1] = 0; 138 | error = eTCValues(hDevice, alngReadTimers, alngUpdateResetTimers, alngReadCounters, alngResetCounters, adblTimerValues, adblCounterValues, 0, 0); 139 | if( error != 0 ) 140 | goto close; 141 | 142 | //Convert Timer1 value to duty-cycle percentage 143 | //High time is LSW 144 | highTime = (double)((unsigned long)adblTimerValues[1]%65536); 145 | //Low time is MSW 146 | lowTime = (double)((unsigned long)adblTimerValues[1]/65536); 147 | //Duty cycle percentage 148 | dutyCycle = 100*highTime/(highTime + lowTime); 149 | printf("Timer1 value = %.0f\n", adblTimerValues[1]); 150 | printf(" High Clicks = %.0f\n", highTime); 151 | printf(" Low Clicks = %.0f\n", lowTime); 152 | printf(" Duty Cycle = %.1f%%\n", dutyCycle); 153 | printf("Counter1 value = %.0f\n", adblCounterValues[1]); 154 | 155 | //Disable all timers and counters 156 | for(i = 0; i < 6; i++) 157 | alngEnableTimers[i] = 0; 158 | alngEnableCounters[0] = 0; 159 | alngEnableCounters[1] = 0; 160 | error = eTCConfig(hDevice, alngEnableTimers, alngEnableCounters, 0, LJ_tcSYS, 1, alngTimerModes, adblTimerValues, 0, 0); 161 | if( error != 0 ) 162 | goto close; 163 | printf("\nCalling eTCConfig to disable all timers and counters\n"); 164 | 165 | close: 166 | if( error > 0 ) 167 | printf("Received an error code of %ld\n", error); 168 | closeUSBConnection(hDevice); 169 | 170 | done: 171 | return 0; 172 | } 173 | 174 | -------------------------------------------------------------------------------- /examples/U3/u3EFunctions.c: -------------------------------------------------------------------------------- 1 | //Author: LabJack 2 | //April 12, 2016 3 | //This example demonstrates with the "easy" functions how to set an analog 4 | //output (DAC), read an analog input (AIN), set a digital output, read a 5 | //digital input, and configure/update/read timers and counters. 6 | 7 | #include "u3.h" 8 | #include 9 | 10 | int main(int argc, char **argv) 11 | { 12 | HANDLE hDevice; 13 | u3CalibrationInfo caliInfo; 14 | int localID; 15 | long DAC1Enable; 16 | long error; 17 | double dblVoltage; 18 | long lngState; 19 | long lngTCPinOffset; 20 | long lngTimerClockBaseIndex; 21 | long lngTimerClockDivisor; 22 | long alngEnableTimers[2]; 23 | long alngTimerModes[2]; 24 | double adblTimerValues[2]; 25 | long alngEnableCounters[2]; 26 | long alngReadTimers[2]; 27 | long alngUpdateResetTimers[2]; 28 | long alngReadCounters[2]; 29 | long alngResetCounters[2]; 30 | double adblCounterValues[2]; 31 | double highTime; 32 | double lowTime; 33 | double dutyCycle; 34 | 35 | //Open first found U3 over USB 36 | localID = -1; 37 | hDevice = openUSBConnection(localID); 38 | if( hDevice == NULL ) 39 | goto done; 40 | 41 | //Get calibration information from U3 42 | error = getCalibrationInfo(hDevice, &caliInfo); 43 | if( error < 0 ) 44 | goto close; 45 | 46 | 47 | /* Note: The eAIN, eDAC, eDI, and eDO "easy" functions have the ConfigIO 48 | * parameter. If calling, for example, eAIN multiple times to read AIN5, 49 | * in your first call set the ConfigIO parameter to 1 (True) so the channel 50 | * is configured to an analog input. This adds an additional one or two U3 51 | * command/responses in the call. In following calls, set the ConfigIO 52 | * parameter to 0 (False) since the channel is already configured. For the 53 | * U3-HV, ConfigIO is ignored for dedicated analog inputs AIN0-AIN3. 54 | */ 55 | 56 | 57 | //Set DAC0 to 2.1 volts 58 | printf("Calling eDAC to set DAC0 to 2.1 V\n"); 59 | error = eDAC(hDevice, &caliInfo, 0, 0, 2.1, 0, 0, 0); 60 | if( error != 0 ) 61 | goto close; 62 | 63 | sleep(1); 64 | 65 | 66 | /* Note for U3 hardware versions older than 1.30 (does not include the 67 | * U3-HV or LV): 68 | * The eAIN "easy" function has the DAC1Enable parameter that is used to 69 | * calculate the correct voltage. In addition to the previous note, set 70 | * ConfigIO to 1 (True) on the first eAIN call for it to read/return the 71 | * DAC1Enable setting from the U3. For following eAIN calls, set ConfigIO 72 | * to 0 (False) and use the returned DAC1Enable value. If DAC1 is 73 | * enabled/disabled in a later eDAC or ConfigIO low-level call, change the 74 | * DAC1Enable value accordingly or make another eAIN call with the ConfigIO 75 | * parameter set to 1. 76 | */ 77 | 78 | //Read AIN3 single-ended voltage 79 | printf("\nCalling eAIN to read AIN3 voltage\n"); 80 | dblVoltage = 0.0; 81 | error = eAIN(hDevice, &caliInfo, 1, &DAC1Enable, 3, 31, &dblVoltage, 0, 0, 0, 0, 0, 0); 82 | if( error != 0 ) 83 | goto close; 84 | printf("AIN3 value = %.3f\n", dblVoltage); 85 | 86 | 87 | //Set FIO5 to output-high 88 | printf("\nCalling eDO to set FIO5 to output-high\n"); 89 | error = eDO(hDevice, 1, 5, 1); 90 | if( error != 0 ) 91 | goto close; 92 | 93 | 94 | //Read FIO4 state 95 | printf("\nCalling eDI to read FIO4 state\n"); 96 | lngState = 0; 97 | error = eDI(hDevice, 1, 4, &lngState); 98 | if( error != 0 ) 99 | goto close; 100 | printf("FIO4 state = %ld\n", lngState); 101 | 102 | 103 | //Enable and configure 1 output timer, 1 input timer, and 104 | //1 counter 105 | printf("\nCalling eTCConfig to enable and configure 1 output timer (Timer0), 1 input timer (Timer1), and 1 counter (Counter1)\n"); 106 | alngEnableTimers[0] = 1; //Enable Timer0 (uses FIO4) 107 | alngEnableTimers[1] = 1; //Enable Timer1 (uses FIO5) 108 | alngEnableCounters[0] = 0; //Disable Counter0 109 | alngEnableCounters[1] = 1; //Enable Counter1 (uses FIO6) 110 | lngTCPinOffset = 4; //Offset is 4, so timers/counters start at FIO4 111 | lngTimerClockBaseIndex = LJ_tc48MHZ_DIV; //Base clock is 48 MHz with divisor support, so Counter0 is disabled 112 | lngTimerClockDivisor = 48; //Base clock divisor. Makes the clock 1 MHz. 113 | alngTimerModes[0] = LJ_tmPWM8; //Timer0 is 8-bit PWM output. Frequency is 1M/256 = 3906. 114 | alngTimerModes[1] = LJ_tmDUTYCYCLE; //Timer1 is duty cycle 115 | adblTimerValues[0] = 16384; //Set PWM8 duty-cycle to 75%. 116 | adblTimerValues[1] = 0; 117 | error = eTCConfig(hDevice, alngEnableTimers, alngEnableCounters, lngTCPinOffset, lngTimerClockBaseIndex, lngTimerClockDivisor, alngTimerModes, adblTimerValues, 0, 0); 118 | if( error != 0 ) 119 | goto close; 120 | 121 | printf("\nWaiting for 1 second...\n"); 122 | sleep(1); 123 | 124 | //Update the value (duty-cycle) of output timer (Timer0), 125 | //read and reset the input timer (Timer1), and 126 | //read and reset the counter (Counter1). 127 | printf("\nCalling eTCValues to update the value (duty-cycle) of output Timer0, read/reset input Timer1, and read/reset Counter1\n"); 128 | alngReadTimers[0] = 0; //Don't read Timer0 (output timer) 129 | alngReadTimers[1] = 1; //Read Timer1 130 | alngUpdateResetTimers[0] = 1; //Update Timer0 131 | alngUpdateResetTimers[1] = 1; //Reset Timer1 132 | alngReadCounters[0] = 0; 133 | alngReadCounters[1] = 1; //Read Counter1 134 | alngResetCounters[0] = 0; 135 | alngResetCounters[1] = 1; //Reset Counter1 136 | adblCounterValues[0] = 0; 137 | adblCounterValues[1] = 0; 138 | adblTimerValues[0] = 32768; //Change Timer0 duty-cycle to 50% 139 | adblTimerValues[1] = 0; 140 | error = eTCValues(hDevice, alngReadTimers, alngUpdateResetTimers, alngReadCounters, alngResetCounters, adblTimerValues, adblCounterValues, 0, 0); 141 | if( error != 0 ) 142 | goto close; 143 | 144 | //Convert Timer1 value to duty-cycle percentage 145 | //High time is LSW 146 | highTime = (double)((unsigned long)adblTimerValues[1]%65536); 147 | //Low time is MSW 148 | lowTime = (double)((unsigned long)adblTimerValues[1]/65536); 149 | //Duty cycle percentage 150 | dutyCycle = 100*highTime/(highTime + lowTime); 151 | printf("Timer1 value = %.0f\n", adblTimerValues[1]); 152 | printf(" High Clicks = %.0f\n", highTime); 153 | printf(" Low Clicks = %.0f\n", lowTime); 154 | printf(" Duty Cycle = %.1f%%\n", dutyCycle); 155 | printf("Counter1 value = %.0f\n", adblCounterValues[1]); 156 | 157 | //Disable all timers and counters 158 | alngEnableTimers[0] = 0; 159 | alngEnableTimers[1] = 0; 160 | alngEnableCounters[0] = 0; 161 | alngEnableCounters[1] = 0; 162 | error = eTCConfig(hDevice, alngEnableTimers, alngEnableCounters, 4, LJ_tc48MHZ, 0, alngTimerModes, adblTimerValues, 0, 0); 163 | if( error != 0 ) 164 | goto close; 165 | printf("\nCalling eTCConfig to disable all timers and counters\n"); 166 | 167 | close: 168 | if( error > 0 ) 169 | printf("Received an error code of %ld\n", error); 170 | closeUSBConnection(hDevice); 171 | 172 | done: 173 | return 0; 174 | } 175 | 176 | -------------------------------------------------------------------------------- /examples/UE9/ue9TimerCounter.c: -------------------------------------------------------------------------------- 1 | //Author: LabJack 2 | //May 25, 2011 3 | //This example program calls the TimerCounter function, and reads both counters 4 | //and enables 2 timers with PWM output. Connect FIO0/FIO1 to FIO2/FIO3 to have 5 | //the counter read something. After 1 second the counters' counts are outputted 6 | //to the screen. 7 | 8 | #include 9 | #include "ue9.h" 10 | 11 | 12 | int timerCounter_example(HANDLE hDevice); 13 | int errorCheck(uint8 *buffer); 14 | 15 | int main(int argc, char **argv) 16 | { 17 | HANDLE hDevice; 18 | 19 | //Opening first found UE9 over USB 20 | if( (hDevice = openUSBConnection(-1)) == NULL ) 21 | return 1; 22 | 23 | timerCounter_example(hDevice); 24 | closeUSBConnection(hDevice); 25 | return 0; 26 | } 27 | 28 | //Sends a TimerCounter low-level command to enable and set two Timers 29 | //(FIO0, FIO1) and two Counters (FIO2, FIO3), then sends a TimerCounter 30 | //command a second later to read from the Counters and last sends a 31 | //TimerCounter command to disable the Timers and Counters. 32 | int timerCounter_example(HANDLE hDevice) 33 | { 34 | //Note: If using the quadrature input timer mode, the returned 32 bit 35 | // integer is signed 36 | uint8 sendBuff[30], recBuff[40]; 37 | uint32 cnt; 38 | int sendChars, recChars, i; 39 | 40 | //Enable timers and counters 41 | sendBuff[1] = (uint8)(0xF8); //Command byte 42 | sendBuff[2] = (uint8)(0x0C); //Number of data words 43 | sendBuff[3] = (uint8)(0x18); //Extended command number 44 | sendBuff[6] = (uint8)(0x03); //TimerClockDivisor = 3 45 | sendBuff[7] = (uint8)(0x9A); //Updating: 2 Timers enabled, Counter0 and 46 | //Counter1 enabled 47 | sendBuff[8] = (uint8)(0x00); //TimerClockConfig = 750 kHz (if using system 48 | //clock, call ControlConfig first and set the 49 | //PowerLevel to a fixed state) 50 | sendBuff[9] = (uint8)(0x00); //UpdateReset - not resetting anything 51 | sendBuff[10] = (uint8)(0x00); //Timer0Mode = 16-Bit PWM 52 | 53 | //Timer0Value = 32768 54 | sendBuff[11] = (uint8)(0x00); //Timer0Value (low byte) 55 | sendBuff[12] = (uint8)(0x80); //Timer0Value (high byte) 56 | 57 | //Timer1Value = 32768 58 | sendBuff[13] = (uint8)(0x01); //Timer1Mode = 8-Bit PWM 59 | sendBuff[14] = (uint8)(0x00); //Timer1Value (low byte) 60 | sendBuff[15] = (uint8)(0x80); //Timer1Value (high byte) 61 | 62 | //timer modes and values for timers 2 - 5, which are not enabled 63 | for( i = 16; i < 28; i++ ) 64 | sendBuff[i] = (uint8)(0x00); 65 | 66 | sendBuff[28] = (uint8)(0x00); //Counter0Mode (pass 0) 67 | sendBuff[29] = (uint8)(0x00); //Counter1Mode (pass 0) 68 | 69 | extendedChecksum(sendBuff, 30); 70 | 71 | //Sending command to UE9 72 | sendChars = LJUSB_Write(hDevice, sendBuff, 30); 73 | if( sendChars < 30 ) 74 | { 75 | if( sendChars == 0 ) 76 | goto writeError0; 77 | else 78 | goto writeError1; 79 | } 80 | 81 | //Reading response from UE9 82 | recChars = LJUSB_Read(hDevice, recBuff, 40); 83 | if( recChars < 40 ) 84 | { 85 | if( recChars == 0 ) 86 | goto readError0; 87 | else 88 | goto readError1; 89 | } 90 | 91 | if( errorCheck(recBuff) == -1 ) 92 | return -1; 93 | 94 | //Wait 1 sec and read counters 95 | sleep(1); 96 | 97 | sendBuff[1] = (uint8)(0xF8); //Command bytes 98 | sendBuff[2] = (uint8)(0x0C); //Number of data words 99 | sendBuff[3] = (uint8)(0x18); //Extended command number 100 | 101 | //Not updating our configuration. We only want to read the counter values. 102 | for( i = 6; i < 30; i++ ) 103 | sendBuff[i] = (uint8)(0x00); 104 | 105 | extendedChecksum(sendBuff, 30); 106 | 107 | //Sending command to UE9 108 | sendChars = LJUSB_Write(hDevice, sendBuff, 30); 109 | if( sendChars < 30 ) 110 | { 111 | if( sendChars == 0 ) 112 | goto writeError0; 113 | else 114 | goto writeError1; 115 | } 116 | 117 | //Reading response from UE9 118 | recChars = LJUSB_Read(hDevice, recBuff, 40); 119 | if( recChars < 40 ) 120 | { 121 | if( recChars == 0 ) 122 | goto readError0; 123 | else 124 | goto readError1; 125 | } 126 | 127 | if( errorCheck(recBuff) == -1 ) 128 | return -1; 129 | 130 | printf("Current counts from counters after 1 second:\n"); 131 | for( i = 0; i < 2; i++ ) 132 | { 133 | cnt = (unsigned int)recBuff[32 + 4*i] + (unsigned int)recBuff[33 + 4*i]*256 + 134 | (unsigned int)recBuff[34 + 4*i]*65536 + (unsigned int)recBuff[35 + 4*i]*16777216; 135 | printf(" Counter%d : %u\n", i, cnt); 136 | } 137 | 138 | //Disable timers and counters 139 | sendBuff[1] = (uint8)(0xF8); //Command bytes 140 | sendBuff[2] = (uint8)(0x0C); //Number of data words 141 | sendBuff[3] = (uint8)(0x18); //Extended command number 142 | sendBuff[6] = (uint8)(0x00); //TimerClockDivisor = 0 143 | sendBuff[7] = (uint8)(0x80); //Updating: 0 Timers enabled, Counter0 and 144 | //Counter1 disabled 145 | 146 | //Setting bytes 8 - 30 to zero since nothing is enabled 147 | for( i = 8; i < 30; i++ ) 148 | sendBuff[i] = (uint8)(0x00); 149 | 150 | extendedChecksum(sendBuff, 30); 151 | 152 | //Sending command to UE9 153 | sendChars = LJUSB_Write(hDevice, sendBuff, 30); 154 | if( sendChars < 30 ) 155 | { 156 | if( sendChars == 0 ) 157 | goto writeError0; 158 | else 159 | goto writeError1; 160 | } 161 | 162 | //Reading response from UE9 163 | recChars = LJUSB_Read(hDevice, recBuff, 40); 164 | if( recChars < 40 ) 165 | { 166 | if( recChars == 0 ) 167 | goto readError0; 168 | else 169 | goto readError1; 170 | } 171 | 172 | if( errorCheck(recBuff) == -1 ) 173 | return -1; 174 | 175 | return 0; 176 | 177 | writeError0: 178 | printf("Error : write failed\n"); 179 | return -1; 180 | 181 | writeError1: 182 | printf("Error : did not write all of the buffer\n"); 183 | return -1; 184 | 185 | readError0: 186 | printf("Error : read failed\n"); 187 | return -1; 188 | 189 | readError1: 190 | printf("Error : did not read all of the buffer\n"); 191 | return -1; 192 | } 193 | 194 | int errorCheck(uint8 *buffer) 195 | { 196 | uint16 checksumTotal; 197 | 198 | checksumTotal = extendedChecksum16(buffer, 40); 199 | if( (uint8)((checksumTotal / 256) & 0xFF) != buffer[5] ) 200 | { 201 | printf("Error : read buffer has bad checksum16(MSB)\n"); 202 | return -1; 203 | } 204 | 205 | if( (uint8)(checksumTotal & 0xFF) != buffer[4] ) 206 | { 207 | printf("Error : read buffer has bad checksum16(LSB)\n"); 208 | return -1; 209 | } 210 | 211 | if( extendedChecksum8(buffer) != buffer[0] ) 212 | { 213 | printf("Error : read buffer has bad checksum8\n"); 214 | return -1; 215 | } 216 | 217 | if( buffer[1] != (uint8)(0xF8) || buffer[2] != (uint8)(0x11) || buffer[3] != (uint8)(0x18) ) 218 | { 219 | printf("Error : read buffer has wrong command bytes \n"); 220 | return -1; 221 | } 222 | 223 | if( buffer[6] != 0 ) 224 | { 225 | printf("Errorcode (byte 6): %d\n", (unsigned int)buffer[6]); 226 | return -1; 227 | } 228 | 229 | return 0; 230 | } 231 | -------------------------------------------------------------------------------- /examples/UE9/ue9SingleIO.c: -------------------------------------------------------------------------------- 1 | //Author: LabJack 2 | //May 25, 2011 3 | //This example program makes 3 SingleIO low-level function calls. One call sets 4 | //DAC0 to 2.500 V. One call reads voltage from AIN0. One call reads the 5 | //temperature from the internal temperature sensor. Control firmware version 6 | //1.03 and above needed for SingleIO. 7 | #include "ue9.h" 8 | 9 | 10 | int singleIO_AV_example(HANDLE handle, ue9CalibrationInfo *caliInfo); 11 | 12 | int main(int argc, char **argv) 13 | { 14 | HANDLE hDevice; 15 | ue9CalibrationInfo caliInfo; 16 | 17 | //Opening first found UE9 over USB 18 | if( (hDevice = openUSBConnection(-1)) == NULL ) 19 | goto done; 20 | 21 | //Getting calibration information from UE9 22 | if( getCalibrationInfo(hDevice, &caliInfo) < 0 ) 23 | goto close; 24 | 25 | singleIO_AV_example(hDevice, &caliInfo); 26 | 27 | close: 28 | closeUSBConnection(hDevice); 29 | done: 30 | return 0; 31 | } 32 | 33 | //Sends 3 SingleIO low-level commands to set DAC0, read AIN0 and read the 34 | //temperature 35 | int singleIO_AV_example(HANDLE hDevice, ue9CalibrationInfo *caliInfo) 36 | { 37 | uint8 sendBuff[8], recBuff[8], ainResolution; 38 | uint16 bytesVoltage, bytesTemperature; 39 | int sendChars, recChars; 40 | double voltage; 41 | double temperature; //in Kelvins 42 | 43 | ainResolution = 12; 44 | //ainResolution = 18; //high-res mode for UE9 Pro only 45 | 46 | /* Setting voltage of DAC0 to 2.500 V */ 47 | //if( getDacBinVoltUncalibrated(0, 2.500, &bytesVoltage) < 0 ) 48 | if( getDacBinVoltCalibrated(caliInfo, 0, 2.500, &bytesVoltage) < 0 ) 49 | return -1; 50 | 51 | sendBuff[1] = (uint8)(0xA3); //Command byte 52 | sendBuff[2] = (uint8)(0x05); //IOType = 5 (analog out) 53 | sendBuff[3] = (uint8)(0x00); //Channel = 0 (DAC0) 54 | sendBuff[4] = (uint8)( bytesVoltage & (0x00FF) ); //low bits of voltage 55 | sendBuff[5] = (uint8)( bytesVoltage /256 ) + 192; //high bits of voltage 56 | //(bit 7 : Enable, 57 | // bit 6: Update) 58 | sendBuff[6] = (uint8)(0x00); //Settling time - does not apply to analog output 59 | sendBuff[7] = (uint8)(0x00); //Reserved 60 | sendBuff[0] = normalChecksum8(sendBuff, 8); 61 | 62 | //Sending command to UE9 63 | sendChars = LJUSB_Write(hDevice, sendBuff, 8); 64 | if( sendChars < 8 ) 65 | { 66 | if( sendChars == 0 ) 67 | goto sendError0; 68 | else 69 | goto sendError1; 70 | } 71 | 72 | //Reading response from UE9 73 | recChars = LJUSB_Read(hDevice, recBuff, 8); 74 | if( recChars < 8 ) 75 | { 76 | if( recChars == 0 ) 77 | goto recvError0; 78 | else 79 | goto recvError1; 80 | } 81 | 82 | if( (uint8)(normalChecksum8(recBuff, 8)) != recBuff[0] ) 83 | goto chksumError; 84 | 85 | if( recBuff[1] != (uint8)(0xA3) ) 86 | goto commandByteError; 87 | 88 | if( recBuff[2] != (uint8)(0x05) ) 89 | goto IOTypeError; 90 | 91 | if( recBuff[3] != 0 ) 92 | goto channelError; 93 | 94 | printf("Set DAC0 voltage to 2.500 V ...\n"); 95 | 96 | /* Reading voltage from AIN0 */ 97 | sendBuff[1] = (uint8)(0xA3); //Command byte 98 | sendBuff[2] = (uint8)(0x04); //IOType = 4 (analog in) 99 | sendBuff[3] = (uint8)(0x00); //Channel = 0 (AIN0) 100 | sendBuff[4] = (uint8)(0x00); //BipGain (Bip = unipolar, Gain = 1) 101 | sendBuff[5] = ainResolution; //Resolution 102 | sendBuff[6] = (uint8)(0x00); //SettlingTime = 0 103 | sendBuff[7] = (uint8)(0x00); //Reserved 104 | sendBuff[0] = normalChecksum8(sendBuff, 8); 105 | 106 | //Sending command to UE9 107 | sendChars = LJUSB_Write(hDevice, sendBuff, 8); 108 | if( sendChars < 8 ) 109 | { 110 | if( sendChars == 0 ) 111 | goto sendError0; 112 | else 113 | goto sendError1; 114 | } 115 | 116 | //Reading response from UE9 117 | recChars = LJUSB_Read(hDevice, recBuff, 8); 118 | if( recChars < 8 ) 119 | { 120 | if( recChars == 0 ) 121 | goto recvError0; 122 | else 123 | goto recvError1; 124 | } 125 | 126 | if( (uint8)(normalChecksum8(recBuff, 8)) != recBuff[0] ) 127 | goto chksumError; 128 | 129 | if( recBuff[1] != (uint8)(0xA3) ) 130 | goto commandByteError; 131 | 132 | if( recBuff[2] != (uint8)(0x04) ) 133 | goto IOTypeError; 134 | 135 | if( recBuff[3] != 0 ) 136 | goto channelError; 137 | 138 | bytesVoltage = recBuff[5] + recBuff[6]*256; 139 | 140 | //if( getAinVoltUncalibrated(sendBuff[4], ainResolution, bytesVoltage, &voltage) < 0 ) 141 | if( getAinVoltCalibrated(caliInfo, sendBuff[4], ainResolution, bytesVoltage, &voltage) < 0 ) 142 | return -1; 143 | 144 | printf("Voltage read from AI0: %.4f V\n", voltage); 145 | 146 | /* Reading temperature from internal temperature sensor */ 147 | sendBuff[1] = (uint8)(0xA3); //Command byte 148 | sendBuff[2] = (uint8)(0x04); //IOType = 4 (analog in) 149 | sendBuff[3] = (uint8)(0x85); //Channel = 133 (tempSensor) 150 | sendBuff[4] = (uint8)(0x00); //Gain = 1 (Bip does not apply) 151 | sendBuff[5] = (uint8)(0x0C); //Resolution = 12 152 | sendBuff[6] = (uint8)(0x00); //SettlingTime = 0 153 | sendBuff[7] = (uint8)(0x00); //Reserved 154 | sendBuff[0] = normalChecksum8(sendBuff, 8); 155 | 156 | //Sending command to UE9 157 | sendChars = LJUSB_Write(hDevice, sendBuff, 8); 158 | if( sendChars < 8 ) 159 | { 160 | if( sendChars == 0 ) 161 | goto sendError0; 162 | else 163 | goto sendError1; 164 | } 165 | 166 | //Reading response from UE9 167 | recChars = LJUSB_Read(hDevice, recBuff, 8); 168 | if( recChars < 8 ) 169 | { 170 | if( recChars == 0 ) 171 | goto recvError0; 172 | else 173 | goto recvError1; 174 | } 175 | 176 | if( (uint8)(normalChecksum8(recBuff, 8)) != recBuff[0] ) 177 | goto chksumError; 178 | 179 | if( recBuff[1] != (uint8)(0xA3) ) 180 | goto commandByteError; 181 | 182 | if( recBuff[2] != (uint8)(0x04) ) 183 | goto IOTypeError; 184 | 185 | if( recBuff[3] != (uint8)(0x85) ) 186 | goto channelError; 187 | 188 | bytesTemperature = recBuff[5] + recBuff[6]*256; 189 | 190 | //Assuming high power level 191 | //if( getTempKUncalibrated(0, bytesTemperature, &temperature) < 0 ) 192 | if( getTempKCalibrated(caliInfo, 0, bytesTemperature, &temperature) < 0 ) 193 | return -1; 194 | 195 | printf("Temperature read internal temperature sensor (channel 133): %.1f K\n\n", temperature); 196 | return 0; 197 | 198 | //error printouts 199 | sendError0: 200 | printf("Error : write failed\n"); 201 | return -1; 202 | sendError1: 203 | printf("Error : did not write all of the buffer\n"); 204 | return -1; 205 | recvError0: 206 | printf("Error : read failed\n"); 207 | return -1; 208 | recvError1: 209 | printf("Error : did not read all of the buffer\n"); 210 | return -1; 211 | chksumError: 212 | printf("Error : read buffer has bad checksum\n"); 213 | return -1; 214 | commandByteError: 215 | printf("Error : read buffer has wrong command byte\n"); 216 | return -1; 217 | IOTypeError: 218 | printf("Error : read buffer has wrong IOType\n"); 219 | return -1; 220 | channelError: 221 | printf("Error : read buffer has wrong channel\n"); 222 | return -1; 223 | } 224 | -------------------------------------------------------------------------------- /examples/Modbus/modbus.h: -------------------------------------------------------------------------------- 1 | /* 2 | * A library to help you build Modbus functions for LabJack devices. For more 3 | * information on Modbus, please see: 4 | * 5 | * http://labjack.com/support/modbus 6 | * 7 | * The flow for working with a LabJack device should go like this: 8 | * 1. Open the device (LJUSB_OpenDevice) 9 | * 2. Build the packet to write using buildReadHoldingRegistersPacket 10 | * 3. Write the packet to the device (LJUSB_Write) 11 | * 4. Read the result (LJUSB_Read) 12 | * 5. Parse the result using a parse*RegisterResponse function 13 | * 6. Close the device (LJUSB_CloseDevice) 14 | * 15 | * For writing to registers, the flow goes like this: 16 | * 1. Open the device (LJUSB_OpenDevice) 17 | * 2. Build the packet to write using buildWriteHoldingRegistersPacket 18 | * 3. Insert the values to write to packet with put*ToBuffer functions 19 | * 4. Write the packet to the device (LJUSB_Write) 20 | * 5. Read the result (LJUSB_Read) 21 | * 6. Close the device (LJUSB_CloseDevice) 22 | */ 23 | 24 | #ifndef _MODBUS_H_ 25 | #define _MODBUS_H_ 26 | 27 | #ifdef __cplusplus 28 | extern "C"{ 29 | #endif 30 | 31 | /* --------- Read Functions --------- */ 32 | 33 | int buildReadHoldingRegistersPacket( unsigned char* sendBuffer, int startReg, int numRegs, int unitId, int prependZeros ); 34 | /* buildReadHoldingRegistersPacket takes a byte array and sets the bytes to be a 35 | * Modbus packet to read a register. It returns the number of bytes to read. 36 | * 37 | * Args: 38 | * - sendBuffer: an array of length 12 or 14 (if prependZeros != 0 ) 39 | * - startReg: The starting register. 40 | * - numReg: The number of registers to read starting at startReg. 41 | * - unitId: For U3/U6/UE9, always pass 0. 42 | * - prependZeros: If this packet is going to be sent over USB, the UD family of 43 | * devices require that the Modbus packet start with 2 extra 44 | * bytes of zeros. 45 | * 46 | * Example Usage to read register 0 (AIN0): 47 | unsigned char sendBuffer[14]; 48 | int startReg = 0; // Start at register 0 49 | int numRegs = 2; // AIN0 is a floating point value, so need to read 2 registers 50 | int unitId = 0; // For UD family devices, always 0 51 | int prependZeros = 1; // For UD family devices on USB, always 1 52 | int numBytesToRead; 53 | 54 | numBytesToRead = buildReadHoldingRegistersPacket( 55 | sendBuffer, startReg, numRegs, unitId, prependZeros ); 56 | */ 57 | 58 | float parseFPRegisterResponse(unsigned char* recBuffer, int offset); 59 | /* 60 | * parseFPRegisterResponse takes the recBuffer and an offset, and returns the 61 | * floating point value. recBuffer must have a length equal to offset+3. 62 | * 63 | * Args: 64 | * - recBuffer: the buffer that was read from the device. 65 | * - offset: the offset to start reading from. Usually, 9. 66 | * 67 | * Example Usage: 68 | unsigned char recBuffer = { 0x40, 0x0, 0x0, 0x0 }; 69 | float value = parseFPRegisterResponse(recBuffer, 0); 70 | // value -> 2.0 71 | */ 72 | 73 | int parseIntRegisterResponse(unsigned char* recBuffer, int offset); 74 | /* 75 | * parseIntRegisterResponse takes the recBuffer and an offset, and returns the 76 | * integer value. recBuffer must have a length equal to offset+4. 77 | * 78 | * Args: 79 | * - recBuffer: the buffer that was read from the device. 80 | * - offset: the offset to start reading from. Usually, 9. 81 | * 82 | * Example Usage: 83 | unsigned char recBuffer = { 0x0, 0x84, 0x5F, 0xED }; 84 | int value = parseIntRegisterResponse(recBuffer, 0); 85 | // value -> 8675309 86 | */ 87 | 88 | short parseShortRegisterResponse(unsigned char* recBuffer, int offset); 89 | /* 90 | * parseShortRegisterResponse takes the recBuffer and an offset, and returns the 91 | * short value. recBuffer must have a length equal to offset+2. 92 | * 93 | * Args: 94 | * - recBuffer: the buffer that was read from the device. 95 | * - offset: the offset to start reading from. Usually, 9. 96 | * 97 | * Example Usage: 98 | unsigned char recBuffer = { 0x2, 0x10 }; 99 | short value = parseShortRegisterResponse(recBuffer, 0); 100 | // value -> 528 101 | */ 102 | 103 | /* --------- Write Functions --------- */ 104 | 105 | int buildWriteHoldingRegistersPacket(unsigned char* sendBuffer, int startReg, int numReg, int unitId, int prependZeros); 106 | /* buildReadHoldingRegistersPacket takes a byte array and sets the bytes to be a 107 | * Modbus packet to write registers. It returns the number of bytes to read. 108 | * After calling this function, you must use the put*ToBuffer functions to set 109 | * the values on the end. 110 | * 111 | * Args: 112 | * - sendBuffer: an array of length 13+(2*numReg) (+2 if prependZeros != 0 ) 113 | * - startReg: The starting register. 114 | * - numReg: The number of registers to write starting at startReg. 115 | * - unitId: For U3/U6/UE9, always pass 0. 116 | * - prependZeros: If this packet is going to be sent over USB, the UD family of 117 | * devices require that the Modbus packet start with 2 extra 118 | * bytes of zeros. 119 | * 120 | * Example Usage to write 2.0 to register 5000 (DAC0): 121 | int startReg = 0; // Start at register 0 122 | int numRegs = 2; // DAC0 is a floating point value, so need to read 2 registers 123 | int unitId = 0; // For UD family devices, always 0 124 | int prependZeros = 1; // For UD family devices on USB, always 1 125 | unsigned char sendBuffer[19]; // 13 + (2*2) + 2 = 19 126 | int numBytesToRead; 127 | 128 | numBytesToRead = buildWriteHoldingRegistersPacket( 129 | sendBuffer, startReg, numRegs, unitId, prependZeros ); 130 | putFPIntoBuffer(sendBuffer, 15, 2.0); 131 | //sendBuffer => [0x0, 0x0, 0x0, 0x38, 0x0, 0x0, 0x0, 0xB, 0x0, 0x10, 0x0, 0x0, 132 | // 0x0, 0x2, 0x4, 0x40, 0x0, 0x0, 0x0] 133 | */ 134 | 135 | int putFPIntoBuffer( unsigned char* sendBuffer, int offset, float value); 136 | /* 137 | * putFPIntoBuffer writes the bytes of value into sendBuffer at offset. 138 | * sendBuffer must have a length equal to offset+4. Returns zero for success. 139 | * 140 | * Args: 141 | * - sendBuffer: the buffer to be written to the device. 142 | * - offset: the offset to start overwriting. Usually, 15. 143 | * - value: a float of the value to write. 144 | * 145 | * Example Usage: 146 | unsigned char sendBuffer[4]; 147 | putFPIntoBuffer(sendBuffer, 0, 2.0); 148 | // sendBuffer -> [0x40, 0x0, 0x0, 0x0] 149 | */ 150 | 151 | int putIntIntoBuffer( unsigned char* sendBuffer, int offset, int value ); 152 | /* 153 | * putIntIntoBuffer writes the bytes of value into sendBuffer at offset. 154 | * sendBuffer must have a length equal to offset+4. Returns zero for success. 155 | * 156 | * Args: 157 | * - sendBuffer: the buffer to be written to the device. 158 | * - offset: the offset to start overwriting. Usually, 15. 159 | * - value: an int of the value to write. 160 | * 161 | * Example Usage: 162 | unsigned char sendBuffer[4]; 163 | putIntIntoBuffer(sendBuffer, 0, 8675309); 164 | // sendBuffer -> [0x0, 0x84, 0x5F, 0xED] 165 | */ 166 | 167 | int putShortIntoBuffer( unsigned char* sendBuffer, int offset, short value ); 168 | /* 169 | * putShortIntoBuffer inserts the bytes of value into sendBuffer at offset. 170 | * sendBuffer must have a length equal to offset+2. Returns zero for success. 171 | * 172 | * Args: 173 | * - sendBuffer: the buffer to be written to the device. 174 | * - offset: the offset to start overwriting. Usually, 15. 175 | * - value: an int of the value to write. 176 | * 177 | * Example Usage: 178 | unsigned char sendBuffer[2]; 179 | putShortIntoBuffer(sendBuffer, 0, (short)528); 180 | // sendBuffer -> [0x2, 0x10] 181 | */ 182 | 183 | #ifdef __cplusplus 184 | } 185 | #endif 186 | 187 | #endif // _MODBUS_H_ 188 | -------------------------------------------------------------------------------- /examples/UE9/ue9allio.c: -------------------------------------------------------------------------------- 1 | //Author : LabJack 2 | //May 25, 2011 3 | //This example demonstrates how to write and read some or all analog and digital 4 | //I/O. It records the time for 1000 iterations and divides by 1000, to allow 5 | //measurement of the basic command/response communication times. These times 6 | //should be comparable to the Windows command/response communication times 7 | //documented in Section 3.1 of the UE9 User's Guide. 8 | 9 | #include "ue9.h" 10 | 11 | 12 | int allIO(HANDLE hDevice, ue9CalibrationInfo *caliInfo); 13 | 14 | int main(int argc, char **argv) 15 | { 16 | HANDLE hDevice; 17 | ue9CalibrationInfo caliInfo; 18 | 19 | //Opening first found UE9 over USB 20 | if( (hDevice = openUSBConnection(-1)) == NULL ) 21 | goto done; 22 | 23 | //Getting calibration information from UE9 24 | if( getCalibrationInfo(hDevice, &caliInfo) < 0 ) 25 | goto close; 26 | 27 | allIO(hDevice, &caliInfo); 28 | 29 | close: 30 | closeUSBConnection(hDevice); 31 | done: 32 | return 0; 33 | } 34 | 35 | //Sends 1000 Feedback low-level commands to read digital IO and analog inputs. 36 | //On the first send, the following are set: DAC0 to 2.5 volts, DAC1 to 3.5 37 | //volts, and digital IOs to inputs. 38 | int allIO(HANDLE hDevice, ue9CalibrationInfo *caliInfo) 39 | { 40 | uint8 sendBuff[34], recBuff[64], settlingTime; 41 | uint8 numChannels; //Number of AIN channels, 0-16. 42 | uint16 checksumTotal, bytesVoltage, ainMask; 43 | int sendChars, recChars, i, j; 44 | int initialize; //boolean to init. DAC and digital IO settings 45 | int numIterations, valueDIPort; 46 | long time, ainResolution; 47 | double valueAIN[16]; 48 | 49 | numIterations = 1000; 50 | initialize = 1; 51 | time = 0; 52 | numChannels = 8; 53 | ainResolution = 12; 54 | for( i = 0; i < 16; i++ ) 55 | valueAIN[i] = 9999.0; 56 | settlingTime = 0; 57 | ainMask = pow(2.0, numChannels) - 1; 58 | 59 | sendBuff[1] = (uint8)(0xF8); //Command byte 60 | sendBuff[2] = (uint8)(0x0E); //Number of data words 61 | sendBuff[3] = (uint8)(0x00); //Extended command number 62 | 63 | sendBuff[6] = 255; //FIOMask : setting the mask of all FIOs 64 | sendBuff[7] = 0; //FIODir : setting all FIO directions to input 65 | sendBuff[8] = 0; //FIOState : all FIO directions are input, so 66 | // state writes do not apply 67 | sendBuff[9] = 255; //EIOMask : setting the mask of all EIOs 68 | sendBuff[10] = 0; //EIODir : setting all EIO directions to input 69 | sendBuff[11] = 0; //EIOState : all EIO directions are input, so 70 | // state writes do not apply 71 | sendBuff[12] = 15; //CIOMask : setting the mask of all CIOs 72 | sendBuff[13] = 0; //CIODirState : setting all CIO directions to input, 73 | // state writes do not apply 74 | 75 | sendBuff[14] = 7; //MIOMask : setting the mask of all MIOs 76 | sendBuff[15] = 0; //MIODirState : setting all MIO directions to input, 77 | // state writes do not apply 78 | 79 | //Getting binary DAC0 value of 2.5 volts 80 | if( getDacBinVoltCalibrated(caliInfo, 0, 2.500, &bytesVoltage) < 0 ) 81 | return -1; 82 | //Setting the voltage of DAC0 to 2.5 83 | sendBuff[16] = (uint8)(bytesVoltage & 255); //low bits of DAC0 84 | sendBuff[17] = (uint8)(bytesVoltage/256) + 192; //high bits of DAC0 85 | //(bit 7 : Enable, 86 | // bit 6: Update) 87 | //Getting binary DAC1 value of 3.5 volts 88 | if( getDacBinVoltCalibrated(caliInfo, 1, 3.500, &bytesVoltage) < 0 ) 89 | return -1; 90 | //Setting the voltage of DAC1 to 3.5 volts 91 | sendBuff[18] = (uint8)(bytesVoltage & 255); //low bits of DAC1 92 | sendBuff[19] = (uint8)(bytesVoltage/256) + 192; //high bits of DAC1 93 | //(bit 7 : Enable, 94 | // bit 6: Update) 95 | 96 | //AINMask - reading the number of AINs specified by numChannels 97 | sendBuff[20] = ainMask & 255; //AINMask (low byte) 98 | sendBuff[21] = ainMask/256; //AINMask (high byte) 99 | sendBuff[22] = 14; //AIN14ChannelNumber : setting to channel 14 100 | sendBuff[23] = 15; //AIN15ChannelNumber : setting to channel 15 101 | sendBuff[24] = ainResolution; //Resolution : Resolution specified by 102 | // ainResolution 103 | sendBuff[25] = settlingTime; //SettlingTime 104 | 105 | //Setting all BipGains (Gain = 1, Bipolar = 1) 106 | for( i = 26; i < 34; i++ ) 107 | sendBuff[i] = (uint8)(0x00); 108 | 109 | extendedChecksum(sendBuff, 34); 110 | 111 | time = getTickCount(); 112 | 113 | for( i = 0; i < numIterations; i++ ) 114 | { 115 | //Sending command to UE9 116 | sendChars = LJUSB_Write(hDevice, sendBuff, 34); 117 | if( sendChars < 34 ) 118 | { 119 | if( sendChars == 0 ) 120 | printf("Feedback error (Iteration %d) : write failed\n", i); 121 | else 122 | printf("Feedback error (Iteration %d) : did not write all of the buffer\n", i); 123 | return -1; 124 | } 125 | 126 | //Reading response from UE9 127 | recChars = LJUSB_Read(hDevice, recBuff, 64); 128 | if( recChars < 64 ) 129 | { 130 | if( recChars == 0 ) 131 | printf("Feedback error (Iteration %d) : read failed\n", i); 132 | else 133 | printf("Feedback error (Iteration %d) : did not read all of the buffer\n", i); 134 | return -1; 135 | } 136 | 137 | checksumTotal = extendedChecksum16(recBuff, 64); 138 | if( (uint8)((checksumTotal / 256) & 0xff) != recBuff[5] ) 139 | { 140 | printf("Feedback error (Iteration %d) : read buffer has bad checksum16(MSB)\n", i); 141 | return -1; 142 | } 143 | 144 | if( (uint8)(checksumTotal & 255) != recBuff[4] ) 145 | { 146 | printf("Feedback error (Iteration %d) : read buffer has bad checksum16(LSB)\n", i); 147 | return -1; 148 | } 149 | 150 | if( extendedChecksum8(recBuff) != recBuff[0] ) 151 | { 152 | printf("Feedback error (Iteration %d) : read buffer has bad checksum8\n", i); 153 | return -1; 154 | } 155 | 156 | if( recBuff[1] != (uint8)(0xF8) || recBuff[2] != (uint8)(0x1D) || recBuff[3] != (uint8)(0x00) ) 157 | { 158 | printf("Feedback error (Iteration %d) : read buffer has wrong command bytes\n", i); 159 | return -1; 160 | } 161 | 162 | for( j = 0; j < numChannels && j < 16; j++ ) 163 | getAinVoltCalibrated(caliInfo, 0x00, (uint8)ainResolution, recBuff[12 + j*2] + recBuff[13 + j*2]*256, &valueAIN[j]); 164 | 165 | valueDIPort = recBuff[7] + recBuff[9]*256 + (recBuff[10] & 15)*65536 + (recBuff[11] & 7)*1048576; 166 | 167 | if( initialize == 1 ) 168 | { 169 | //Unsetting digital IO bit masks since we only want to read states now 170 | sendBuff[6] = 0; //FIOMask 171 | sendBuff[9] = 0; //EIOMask 172 | sendBuff[12] = 0; //CIOMask 173 | sendBuff[14] = 0; //MIOMask 174 | 175 | //Turning off Update bit of DACs 176 | sendBuff[17] = sendBuff[17] - 64; //high bits of DAC0 177 | sendBuff[19] = sendBuff[19] - 64; //high bits of DAC1 178 | 179 | extendedChecksum(sendBuff, 34); 180 | 181 | initialize = 0; 182 | } 183 | } 184 | 185 | time = getTickCount() - time; 186 | 187 | printf("Milleseconds per iteration = %.3f\n", (double)time / (double)numIterations); 188 | printf("\nDigital Input (FIO0-7, EIO0-7, CIO0-3, MIO0-2) = %d\n",valueDIPort); 189 | printf("\nAIN readings from last iteration:\n"); 190 | for( j = 0; j < numChannels; j++ ) 191 | printf("%.3f\n", valueAIN[j]); 192 | 193 | return 0; 194 | } 195 | -------------------------------------------------------------------------------- /INSTALL.MacOSX: -------------------------------------------------------------------------------- 1 | Exodriver (liblabjackusb) Library Installation Instructions 2 | ============================================================ 3 | 4 | 5 | Table of Contents 6 | ----------------- 7 | 8 | Installation From Installer 9 | 10 | Installation from Source Code 11 | 12 | Mac OS X Requirements 13 | 14 | About These Instructions 15 | 16 | Installing libusb-1.0 17 | 18 | liblabjackusb Library Script Installation 19 | 20 | Compiling and Running the Example Programs 21 | 22 | Optional: Build a combined 32-/64-bit Exodriver on Mac OS X 23 | 24 | Uninstalling the Old U3 and UE9 Driver 25 | 26 | 27 | Installation From Installer 28 | ============================ 29 | 30 | First, download the installer online here: 31 | 32 | http://labjack.com/support/linux-and-mac-os-x-drivers 33 | 34 | Next, unzip the downloaded file (if not done automatically) and run the 35 | Exodriver_NativeUSB_Setup.pkg package installer. Follow the instructions 36 | from the installer to install the Exodriver and required libusb-1.0 libraries. 37 | 38 | Note that the installed libraries are both 32 and 64-bit binaries. The 39 | installer does not have the source code installation requirements mentioned 40 | below. 41 | 42 | To install the latest Exodriver from source code instead, use the instructions 43 | in the "Installation from Source Code" section below. 44 | 45 | 46 | Installation from Source Code 47 | ============================== 48 | 49 | Mac OS X Requirements 50 | --------------------- 51 | 52 | 1. Xcode developer tools 53 | 54 | 2. The libusb-1.0 library. See the "Installing libusb-1.0" for the libusb-1.0 55 | download and installation instructions. 56 | 57 | 3. Mac OS X 10.5 Leopard or later. 58 | 59 | 4. Uninstall any MacOSX_C_NativeUSB based drivers. The old driver conflicts 60 | with the current liblabjackusb library. See the "Uninstalling the Old U3 and 61 | UE9 Driver" section for more information. 62 | 63 | 64 | About These Instructions 65 | ------------------------ 66 | All lines that start with a dollar sign ($) are commands and need to be run 67 | from a terminal. For example, the Terminal application is usually located in 68 | the Applications folder. 69 | 70 | 71 | Installing libusb-1.0 72 | --------------------- 73 | 74 | Mac OS X requires libusb-1.0 to be built from the source. Download the source 75 | from the libusb project page: 76 | 77 | http://libusb.info 78 | 79 | Version 1.0.21 is the latest as of 2017. From the directory containing 80 | the libusb source download, build it in the standard way: 81 | 82 | $ tar xvfj libusb-1.0.21.tar.bz2 83 | $ cd libusb-1.0.21/ 84 | $ ./configure 85 | $ make 86 | $ sudo make install 87 | 88 | For building a combined 32/64-bit libusb-1.0 library, refer to the 89 | "Optional: Build a combined 32-/64-bit Exodriver on Mac OS X" section. 90 | 91 | 92 | liblabjackusb Library Script Installation 93 | ----------------------------------- 94 | 95 | First, go to the Exodriver directory. 96 | 97 | To install by script, run the following command: 98 | 99 | $ sudo ./install.sh 100 | 101 | This script will attempt to build, install, and make any necessary 102 | system configurations. 103 | 104 | Alternatively, without using the script go to the liblabjackusb/ 105 | directory and run the following commands: 106 | 107 | $ cd liblabjackusb/ 108 | $ make 109 | $ sudo make install 110 | 111 | For building a combined 32/64-bit liblabjackusb library, refer to the 112 | "Optional: Build a combined 32-/64-bit Exodriver on Mac OS X" section. 113 | 114 | 115 | Compiling and Running the Example Programs 116 | ------------------------------------------ 117 | 118 | The example code/programs use the liblabjackusb library and the labjackusb.h 119 | header files in the liblabjackusb/ directory. 120 | 121 | The examples are located in the U3, U6, and UE9 subdirectories in the examples/ 122 | directory. To compile the programs go to your device's directory and run 123 | 124 | $ cd examples/U6/ 125 | $ make 126 | 127 | Run one of example programs like this: 128 | 129 | $ ./u6BasicConfigU6 130 | 131 | 132 | Optional: Build a combined 32-/64-bit Exodriver on Mac OS X 133 | ----------------------------------------------------------- 134 | 135 | These steps are generally not needed, but there are circumstances that require 136 | a combined 32-bit and 64-bit Exodriver. You need both architectures when you 137 | get error messages like the one in "this LabJack forum 138 | topic":http://forums.labjack.com/index.php?showtopic=4983 139 | 140 | dlopen(liblabjackusb.dylib, 6): no suitable image found. Did find: 141 | /usr/local/lib/liblabjackusb.dylib: mach-o, but wrong architecture 142 | 143 | In this case, a 32-bit process tried to load a 64-bit Exodriver. Here's how it 144 | happened: When following the instructions in the Quickstart, the compiler built 145 | a copy of the Exodriver for its native architecture. On modern Mac OS X 146 | systems, that's x86_64 (64-bit). Verify this by running: 147 | 148 | $ file /usr/local/lib/liblabjackusb.dylib 149 | /usr/local/lib/liblabjackusb.dylib: Mach-O 64-bit dynamically linked shared library x86_64 150 | 151 | Normally, this is what you want. The programs you will use to call the 152 | Exodriver will also be 64-bit. The built-in Python on Mac OS X, for example, is 153 | compiled for three architectures, including x86_64: 154 | 155 | $ file /usr/bin/python 156 | /usr/bin/python: Mach-O universal binary with 3 architectures 157 | /usr/bin/python (for architecture x86_64): Mach-O 64-bit executable x86_64 158 | /usr/bin/python (for architecture i386): Mach-O executable i386 159 | /usr/bin/python (for architecture ppc7400): Mach-O executable ppc 160 | 161 | There are some programs on Mac OS X, though, that are not 64-bit (they're i368 162 | only), and they can't load a 64-bit Exodriver. The Python download from 163 | python.org, for example, is 32-bit at the time of this writing. We recommend 164 | using the built-in Python on Mac OS X. 165 | 166 | When you must load the Exodriver from a 32-bit process, you must compile 167 | libusb-1.0 and the Exodriver to be combined 32-/64-bit libraries. Start with 168 | libusb-1.0: 169 | 170 | $ tar xvfj libusb-1.0.21.tar.bz2 171 | $ cd libusb-1.0.21/ 172 | $ export CFLAGS="-arch i386 -arch x86_64" 173 | $ ./configure --disable-dependency-tracking 174 | $ make 175 | $ sudo make install 176 | 177 | Confirm it worked by running: 178 | 179 | $ file /usr/local/lib/libusb-1.0.dylib 180 | /usr/local/lib/libusb-1.0.dylib: Mach-O universal binary with 2 architectures 181 | /usr/local/lib/libusb-1.0.dylib (for architecture i386): Mach-O dynamically linked shared library i386 182 | /usr/local/lib/libusb-1.0.dylib (for architecture x86_64): Mach-O 64-bit dynamically linked shared library x86_64 183 | 184 | After libusb-1.0 is installed correctly, move on to the Exodriver. Find the 185 | Exodriver download directory 186 | 187 | $ cd path/to/exodriver 188 | $ cd liblabjackusb/ 189 | 190 | Now edit the Makefile in a text editor to comment out (put a # sign in front 191 | of) this ARCHFLAGS line: 192 | 193 | #ARCHFLAGS = 194 | 195 | and uncomment (remove the # sign from) this ARCHFLAGS line two lines below it: 196 | 197 | ARCHFLAGS = -arch i386 -arch x86_64 198 | 199 | Now build and install the software 200 | 201 | $ make clean 202 | $ make 203 | $ sudo make install 204 | 205 | Verify that it worked by running: 206 | 207 | $ file /usr/local/lib/liblabjackusb.dylib 208 | /usr/local/lib/liblabjackusb.dylib: Mach-O universal binary with 2 architectures 209 | /usr/local/lib/liblabjackusb.dylib (for architecture i386): Mach-O dynamically linked shared library i386 210 | /usr/local/lib/liblabjackusb.dylib (for architecture x86_64): Mach-O 64-bit dynamically linked shared library x86_64 211 | 212 | Because libusb-1.0 and the Exodriver are built for the i386 architecture, 213 | 32-bit applications can load them. 214 | 215 | 216 | Uninstalling the Old U3 and UE9 Driver 217 | -------------------------------------- 218 | 219 | The old U3 and UE9 driver, previous to the libusb 1.0 requirement, used custom 220 | kernel modules, and will conflict with with the current liblabjackusb library. 221 | To uninstall the old driver, delete the liblabjackusb.dylib: 222 | 223 | $ sudo rm -f /usr/lib/liblabjackusb.dylib 224 | -------------------------------------------------------------------------------- /examples/U6/u6BasicConfigU6.c: -------------------------------------------------------------------------------- 1 | /* 2 | An example that shows a minimal use of Exodriver without the use of functions 3 | hidden in header files. 4 | 5 | You can compile this example with the following command: 6 | $ g++ -lm -llabjackusb u6BasicConfigU6.c 7 | 8 | It is also included in the Makefile. 9 | 10 | */ 11 | 12 | /* Includes */ 13 | #include 14 | #include 15 | #include 16 | #include "labjackusb.h" 17 | 18 | // Defines how long the command is 19 | #define CONFIGU6_COMMAND_LENGTH 26 20 | 21 | // Defines how long the response is 22 | #define CONFIGU6_RESPONSE_LENGTH 38 23 | 24 | /* Buffer Helper Functions Protypes */ 25 | // Takes a buffer and an offset, and turns it into a 32-bit integer 26 | int makeInt(BYTE * buffer, int offset); 27 | 28 | // Takes a buffer and an offset, and turns it into a 16-bit integer 29 | int makeShort(BYTE * buffer, int offset); 30 | 31 | // Takes a buffer and calculates the checksum8 of it. 32 | BYTE calculateChecksum8(BYTE* buffer); 33 | 34 | // Takes a buffer and length, and calculates the checksum16 of the buffer. 35 | int calculateChecksum16(BYTE* buffer, int len); 36 | 37 | /* LabJack Related Helper Functions Protoypes */ 38 | 39 | // Demonstrates how to build the ConfigU6 packet. 40 | void buildConfigU6Bytes(BYTE * sendBuffer); 41 | 42 | // Demonstrates how to check a response for errors. 43 | int checkResponseForErrors(BYTE * recBuffer); 44 | 45 | // Demonstrates how to parse the response of ConfigU6. 46 | void parseConfigU6Bytes(BYTE * recBuffer); 47 | 48 | int main() { 49 | // Setup the variables we will need. 50 | int r = 0; // For checking return values 51 | HANDLE devHandle = 0; 52 | BYTE sendBuffer[CONFIGU6_COMMAND_LENGTH], recBuffer[CONFIGU6_RESPONSE_LENGTH]; 53 | 54 | // Open the U6 55 | devHandle = LJUSB_OpenDevice(1, 0, U6_PRODUCT_ID); 56 | 57 | if( devHandle == NULL ) { 58 | printf("Couldn't open U6. Please connect one and try again.\n"); 59 | exit(-1); 60 | } 61 | 62 | // Builds the ConfigU6 command 63 | buildConfigU6Bytes(sendBuffer); 64 | 65 | // Write the command to the device. 66 | // LJUSB_Write( handle, sendBuffer, length of sendBuffer ) 67 | r = LJUSB_Write( devHandle, sendBuffer, CONFIGU6_COMMAND_LENGTH ); 68 | 69 | if( r != CONFIGU6_COMMAND_LENGTH ) { 70 | printf("An error occurred when trying to write the buffer. The error was: %d\n", errno); 71 | // *Always* close the device when you error out. 72 | LJUSB_CloseDevice(devHandle); 73 | exit(-1); 74 | } 75 | 76 | // Read the result from the device. 77 | // LJUSB_Read( handle, recBuffer, number of bytes to read) 78 | r = LJUSB_Read( devHandle, recBuffer, CONFIGU6_RESPONSE_LENGTH ); 79 | 80 | if( r != CONFIGU6_RESPONSE_LENGTH ) { 81 | printf("An error occurred when trying to read from the U6. The error was: %d\n", errno); 82 | LJUSB_CloseDevice(devHandle); 83 | exit(-1); 84 | } 85 | 86 | // Check the command for errors 87 | if( checkResponseForErrors(recBuffer) != 0 ){ 88 | LJUSB_CloseDevice(devHandle); 89 | exit(-1); 90 | } 91 | 92 | // Parse the response into something useful 93 | parseConfigU6Bytes(recBuffer); 94 | 95 | //Close the device. 96 | LJUSB_CloseDevice(devHandle); 97 | 98 | return 0; 99 | } 100 | 101 | /* ------------- LabJack Related Helper Functions Definitions ------------- */ 102 | 103 | // Uses information from section 5.2.2 of the U6 User's Guide to make a ConfigU6 104 | // packet. 105 | // http://labjack.com/support/u6/users-guide/5.2.2 106 | void buildConfigU6Bytes(BYTE * sendBuffer) { 107 | int i; // For loops 108 | int checksum = 0; 109 | 110 | // Build up the bytes 111 | //sendBuffer[0] = Checksum8 112 | sendBuffer[1] = 0xF8; 113 | sendBuffer[2] = 0x0A; 114 | sendBuffer[3] = 0x08; 115 | //sendBuffer[4] = Checksum16 (LSB) 116 | //sendBuffer[5] = Checksum16 (MSB) 117 | 118 | // We just want to read, so we set the WriteMask to zero, and zero out the 119 | // rest of the bytes. 120 | sendBuffer[6] = 0; 121 | for( i = 7; i < CONFIGU6_COMMAND_LENGTH; i++){ 122 | sendBuffer[i] = 0; 123 | } 124 | 125 | // Calculate and set the checksum16 126 | checksum = calculateChecksum16(sendBuffer, CONFIGU6_COMMAND_LENGTH); 127 | sendBuffer[4] = (BYTE)( checksum & 0xff ); 128 | sendBuffer[5] = (BYTE)( (checksum / 256) & 0xff ); 129 | 130 | // Calculate and set the checksum8 131 | sendBuffer[0] = calculateChecksum8(sendBuffer); 132 | 133 | // The bytes have been set, and the checksum calculated. We are ready to 134 | // write to the U6. 135 | } 136 | 137 | // Checks the response for any errors. 138 | int checkResponseForErrors(BYTE * recBuffer) { 139 | if(recBuffer[0] == 0xB8 && recBuffer[1] == 0xB8) { 140 | // If the packet is [ 0xB8, 0xB8 ], that's a bad checksum. 141 | printf("The U6 detected a bad checksum. Double check your checksum calculations and try again.\n"); 142 | return -1; 143 | } 144 | else if (recBuffer[1] != 0xF8 || recBuffer[2] != 0x10 || recBuffer[3] != 0x08) { 145 | // Make sure the command bytes match what we expect. 146 | printf("Got the wrong command bytes back from the U6.\n"); 147 | return -1; 148 | } 149 | 150 | // Calculate the checksums. 151 | int checksum16 = calculateChecksum16(recBuffer, CONFIGU6_RESPONSE_LENGTH); 152 | BYTE checksum8 = calculateChecksum8(recBuffer); 153 | 154 | if ( checksum8 != recBuffer[0] || recBuffer[4] != (BYTE)( checksum16 & 0xff ) || recBuffer[5] != (BYTE)( (checksum16 / 256) & 0xff ) ) { 155 | // Check the checksum 156 | 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] ); 157 | return -1; 158 | } 159 | else if ( recBuffer[6] != 0 ) { 160 | // Check the error code in the packet. See section 5.3 of the U6 161 | // User's Guide for errorcode descriptions. 162 | printf("Command returned with an errorcode = %d\n", recBuffer[6]); 163 | return -1; 164 | } 165 | 166 | return 0; 167 | 168 | } 169 | 170 | // Parses the ConfigU6 packet into something useful. 171 | void parseConfigU6Bytes(BYTE * recBuffer){ 172 | printf("Results of ConfigU6:\n"); 173 | printf(" FirmwareVersion = %d.%02d\n", recBuffer[10], recBuffer[9]); 174 | printf(" BootloaderVersion = %d.%02d\n", recBuffer[12], recBuffer[11]); 175 | printf(" HardwareVersion = %d.%02d\n", recBuffer[14], recBuffer[13]); 176 | printf(" SerialNumber = %d\n", makeInt(recBuffer, 15)); 177 | printf(" ProductID = %d\n", makeShort(recBuffer, 19)); 178 | printf(" LocalID = %d\n", recBuffer[21]); 179 | printf(" VersionInfo = %d\n", recBuffer[37]); 180 | 181 | if( recBuffer[37] == 4 ){ 182 | printf(" DeviceName = U6\n"); 183 | } 184 | else if(recBuffer[37] == 12) { 185 | printf(" DeviceName = U6-Pro\n"); 186 | } 187 | 188 | } 189 | 190 | 191 | /* ---------------- Buffer Helper Functions Definitions ---------------- */ 192 | 193 | // Takes a buffer and an offset, and turns into an 32-bit integer 194 | int makeInt(BYTE * buffer, int offset){ 195 | return (buffer[offset+3] << 24) + (buffer[offset+2] << 16) + (buffer[offset+1] << 8) + buffer[offset]; 196 | } 197 | 198 | // Takes a buffer and an offset, and turns into an 16-bit integer 199 | int makeShort(BYTE * buffer, int offset) { 200 | return (buffer[offset+1] << 8) + buffer[offset]; 201 | } 202 | 203 | // Calculates the checksum8 204 | BYTE calculateChecksum8(BYTE* buffer){ 205 | int i; // For loops 206 | int temp; // For holding a value while we working. 207 | int checksum = 0; 208 | 209 | for( i = 1; i < 6; i++){ 210 | checksum += buffer[i]; 211 | } 212 | 213 | temp = checksum/256; 214 | checksum = ( checksum - 256 * temp ) + temp; 215 | temp = checksum/256; 216 | 217 | return (BYTE)( ( checksum - 256 * temp ) + temp ); 218 | } 219 | 220 | // Calculates the checksum16 221 | int calculateChecksum16(BYTE* buffer, int len){ 222 | int i; 223 | int checksum = 0; 224 | 225 | for( i = 6; i < len; i++){ 226 | checksum += buffer[i]; 227 | } 228 | 229 | return checksum; 230 | } 231 | -------------------------------------------------------------------------------- /examples/UE9/ue9BasicCommConfig.c: -------------------------------------------------------------------------------- 1 | /* 2 | An example that shows a minimal use of Exodriver without the use of functions 3 | hidden in header files. 4 | 5 | You can compile this example with the following command: 6 | $ g++ -lm -llabjackusb ue9BasicCommConfig.c 7 | 8 | It is also included in the Makefile. 9 | */ 10 | 11 | /* Includes */ 12 | #include 13 | #include 14 | #include 15 | #include "labjackusb.h" 16 | 17 | // Defines how long the command is 18 | #define COMMCONFIG_COMMAND_LENGTH 38 19 | 20 | // Defines how long the response is 21 | #define COMMCONFIG_RESPONSE_LENGTH 38 22 | 23 | /* Buffer Helper Functions Protypes */ 24 | // Takes a buffer and an offset, and turns it into a 32-bit integer 25 | int makeInt(BYTE * buffer, int offset); 26 | 27 | // Takes a buffer and an offset, and turns it into a 16-bit integer 28 | int makeShort(BYTE * buffer, int offset); 29 | 30 | // Takes a buffer and calculates the checksum8 of it. 31 | BYTE calculateChecksum8(BYTE* buffer); 32 | 33 | // Takes a buffer and length, and calculates the checksum16 of the buffer. 34 | int calculateChecksum16(BYTE* buffer, int len); 35 | 36 | /* LabJack Related Helper Functions Protoypes */ 37 | 38 | // Demonstrates how to build the CommConfig packet. 39 | void buildCommConfigBytes(BYTE * sendBuffer); 40 | 41 | // Demonstrates how to check a response for errors. 42 | int checkResponseForErrors(BYTE * recBuffer); 43 | 44 | // Demonstrates how to parse the response of CommConfig. 45 | void parseCommConfigBytes(BYTE * recBuffer); 46 | 47 | int main() { 48 | // Setup the variables we will need. 49 | int r = 0; // For checking return values 50 | HANDLE devHandle = 0; 51 | BYTE sendBuffer[COMMCONFIG_COMMAND_LENGTH], recBuffer[COMMCONFIG_RESPONSE_LENGTH]; 52 | 53 | // Open the UE9 54 | devHandle = LJUSB_OpenDevice(1, 0, UE9_PRODUCT_ID); 55 | 56 | if( devHandle == NULL ) { 57 | printf("Couldn't open UE9. Please connect one and try again.\n"); 58 | exit(-1); 59 | } 60 | 61 | // Builds the CommConfig command 62 | buildCommConfigBytes(sendBuffer); 63 | 64 | // Write the command to the device. 65 | // LJUSB_Write( handle, sendBuffer, length of sendBuffer ) 66 | r = LJUSB_Write( devHandle, sendBuffer, COMMCONFIG_COMMAND_LENGTH ); 67 | 68 | if( r != COMMCONFIG_COMMAND_LENGTH ) { 69 | printf("An error occurred when trying to write the buffer. The error was: %d\n", errno); 70 | // *Always* close the device when you error out. 71 | LJUSB_CloseDevice(devHandle); 72 | exit(-1); 73 | } 74 | 75 | // Read the result from the device. 76 | // LJUSB_Read( handle, recBuffer, number of bytes to read) 77 | r = LJUSB_Read( devHandle, recBuffer, COMMCONFIG_RESPONSE_LENGTH ); 78 | 79 | if( r != COMMCONFIG_RESPONSE_LENGTH ) { 80 | printf("An error occurred when trying to read from the UE9. The error was: %d\n", errno); 81 | LJUSB_CloseDevice(devHandle); 82 | exit(-1); 83 | } 84 | 85 | // Check the command for errors 86 | if( checkResponseForErrors(recBuffer) != 0 ){ 87 | LJUSB_CloseDevice(devHandle); 88 | exit(-1); 89 | } 90 | 91 | // Parse the response into something useful 92 | parseCommConfigBytes(recBuffer); 93 | 94 | //Close the device. 95 | LJUSB_CloseDevice(devHandle); 96 | 97 | return 0; 98 | } 99 | 100 | /* ------------- LabJack Related Helper Functions Definitions ------------- */ 101 | 102 | // Uses information from section 5.2.1 of the UE9 User's Guide to make a CommConfig 103 | // packet. 104 | // http://labjack.com/support/ue9/users-guide/5.2.1 105 | void buildCommConfigBytes(BYTE * sendBuffer) { 106 | int i; // For loops 107 | int checksum = 0; 108 | 109 | // Build up the bytes 110 | //sendBuffer[0] = Checksum8 111 | sendBuffer[1] = 0x78; 112 | sendBuffer[2] = 0x10; 113 | sendBuffer[3] = 0x01; 114 | //sendBuffer[4] = Checksum16 (LSB) 115 | //sendBuffer[5] = Checksum16 (MSB) 116 | 117 | // We just want to read, so we set the WriteMask to zero, and zero out the 118 | // rest of the bytes. 119 | sendBuffer[6] = 0; 120 | for( i = 7; i < COMMCONFIG_COMMAND_LENGTH; i++){ 121 | sendBuffer[i] = 0; 122 | } 123 | 124 | // Calculate and set the checksum16 125 | checksum = calculateChecksum16(sendBuffer, COMMCONFIG_COMMAND_LENGTH); 126 | sendBuffer[4] = (BYTE)( checksum & 0xff ); 127 | sendBuffer[5] = (BYTE)( (checksum / 256) & 0xff ); 128 | 129 | // Calculate and set the checksum8 130 | sendBuffer[0] = calculateChecksum8(sendBuffer); 131 | 132 | // The bytes have been set, and the checksum calculated. We are ready to 133 | // write to the UE9. 134 | } 135 | 136 | // Checks the response for any errors. 137 | int checkResponseForErrors(BYTE * recBuffer) { 138 | if(recBuffer[0] == 0xB8 && recBuffer[1] == 0xB8) { 139 | // If the packet is [ 0xB8, 0xB8 ], that's a bad checksum. 140 | printf("The UE9 detected a bad checksum. Double check your checksum calculations and try again.\n"); 141 | return -1; 142 | } 143 | else if (recBuffer[1] != 0x78 || recBuffer[2] != 0x10 || recBuffer[3] != 0x01) { 144 | // Make sure the command bytes match what we expect. 145 | printf("Got the wrong command bytes back from the UE9.\n"); 146 | return -1; 147 | } 148 | // Normally, we would check byte 6 for errorcodes. CommConfig is an 149 | // exception to that rule. 150 | 151 | // Calculate the checksums. 152 | int checksum16 = calculateChecksum16(recBuffer, COMMCONFIG_RESPONSE_LENGTH); 153 | BYTE checksum8 = calculateChecksum8(recBuffer); 154 | 155 | if ( checksum8 != recBuffer[0] || recBuffer[4] != (BYTE)( checksum16 & 0xff ) || recBuffer[5] != (BYTE)( (checksum16 / 256) & 0xff ) ) { 156 | // Check the checksum 157 | 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] ); 158 | return -1; 159 | } 160 | 161 | return 0; 162 | 163 | } 164 | 165 | // Parses the CommConfig packet into something useful. 166 | void parseCommConfigBytes(BYTE * recBuffer){ 167 | printf("Results of CommConfig:\n"); 168 | printf(" LocalID = %d\n", recBuffer[8]); 169 | printf(" PowerLevel = %d\n", recBuffer[9]); 170 | printf(" IPAddress = %d.%d.%d.%d\n", recBuffer[13], recBuffer[12], recBuffer[11], recBuffer[10] ); 171 | printf(" Gateway = %d.%d.%d.%d\n", recBuffer[17], recBuffer[16], recBuffer[15], recBuffer[14] ); 172 | printf(" Subnet = %d.%d.%d.%d\n", recBuffer[21], recBuffer[20], recBuffer[19], recBuffer[18] ); 173 | printf(" PortA = %d\n", makeShort(recBuffer, 22)); 174 | printf(" PortB = %d\n", makeShort(recBuffer, 24)); 175 | printf(" DHCPEnabled = %d\n", recBuffer[26]); 176 | printf(" ProductID = %d\n", recBuffer[27]); 177 | printf(" MACAddress = %02X:%02X:%02X:%02X:%02X:%02X\n", recBuffer[33], recBuffer[32], recBuffer[31], recBuffer[30], recBuffer[29], recBuffer[28]); 178 | 179 | BYTE serialBytes[4]; 180 | serialBytes[0] = recBuffer[28]; 181 | serialBytes[1] = recBuffer[29]; 182 | serialBytes[2] = recBuffer[30]; 183 | serialBytes[3] = 0x10; 184 | printf(" SerialNumber = %d\n", makeInt(serialBytes, 0)); 185 | 186 | printf(" HardwareVersion = %d.%02d\n", recBuffer[35], recBuffer[34]); 187 | printf(" FirmwareVersion = %d.%02d\n", recBuffer[37], recBuffer[36]); 188 | } 189 | 190 | 191 | /* ---------------- Buffer Helper Functions Definitions ---------------- */ 192 | 193 | // Takes a buffer and an offset, and turns into an 32-bit integer 194 | int makeInt(BYTE * buffer, int offset){ 195 | return (buffer[offset+3] << 24) + (buffer[offset+2] << 16) + (buffer[offset+1] << 8) + buffer[offset]; 196 | } 197 | 198 | // Takes a buffer and an offset, and turns into an 16-bit integer 199 | int makeShort(BYTE * buffer, int offset) { 200 | return (buffer[offset+1] << 8) + buffer[offset]; 201 | } 202 | 203 | // Calculates the checksum8 204 | BYTE calculateChecksum8(BYTE* buffer){ 205 | int i; // For loops 206 | int temp; // For holding a value while we working. 207 | int checksum = 0; 208 | 209 | for( i = 1; i < 6; i++){ 210 | checksum += buffer[i]; 211 | } 212 | 213 | temp = checksum/256; 214 | checksum = ( checksum - 256 * temp ) + temp; 215 | temp = checksum/256; 216 | 217 | return (BYTE)( ( checksum - 256 * temp ) + temp ); 218 | } 219 | 220 | // Calculates the checksum16 221 | int calculateChecksum16(BYTE* buffer, int len){ 222 | int i; 223 | int checksum = 0; 224 | 225 | for( i = 6; i < len; i++){ 226 | checksum += buffer[i]; 227 | } 228 | 229 | return checksum; 230 | } 231 | -------------------------------------------------------------------------------- /examples/UE9/ue9LJTDAC.c: -------------------------------------------------------------------------------- 1 | //Author: LabJack 2 | //June 23, 2009 3 | //Communicates with an LJTick-DAC using low level functions. The LJTDAC should 4 | //be plugged into FIO0/FIO1 for this example. 5 | //Tested with UE9 Comm firmware V1.43 and Control firmware V1.84. 6 | 7 | #include "ue9.h" 8 | #include 9 | 10 | int checkI2CErrorcode(uint8 errorcode); 11 | int LJTDAC_example(HANDLE hDevice, ue9TdacCalibrationInfo *caliInfo); 12 | 13 | const uint8 SCLPinNum = 0; 14 | 15 | int main(int argc, char **argv) 16 | { 17 | HANDLE hDevice; 18 | ue9TdacCalibrationInfo caliInfo; 19 | 20 | //Opening first found UE9 over USB 21 | if( (hDevice = openUSBConnection(-1)) == NULL ) 22 | goto done; 23 | 24 | //Getting calibration information from LJTDAC 25 | if( getTdacCalibrationInfo(hDevice, &caliInfo, SCLPinNum) < 0 ) 26 | goto close; 27 | 28 | LJTDAC_example(hDevice, &caliInfo); 29 | 30 | close: 31 | closeUSBConnection(hDevice); 32 | done: 33 | return 0; 34 | } 35 | 36 | 37 | int checkI2CErrorcode(uint8 errorcode) 38 | { 39 | if( errorcode != 0 ) 40 | { 41 | printf("I2C error : received errorcode %d in response\n", errorcode); 42 | return -1; 43 | } 44 | return 0; 45 | } 46 | 47 | 48 | int LJTDAC_example( HANDLE hDevice, ue9TdacCalibrationInfo *caliInfo ) 49 | { 50 | uint8 options, speedAdjust, sdaPinNum, sclPinNum; 51 | uint8 address, numBytesToSend, numBytesToReceive, errorcode; 52 | uint8 bytesCommand[5], bytesResponse[64], ackArray[4]; 53 | uint16 binaryVoltage; 54 | int i, err; 55 | 56 | err = 0; 57 | 58 | //Setting up parts I2C command that will remain the same throughout this example 59 | options = 0; //I2COptions : 0 60 | speedAdjust = 0; //SpeedAdjust : 0 (for max communication speed of about 130 kHz) 61 | sdaPinNum = SCLPinNum + 1; //SDAPinNum : FIO1 connected to pin DIOB 62 | sclPinNum = SCLPinNum; //SCLPinNum : FIO0 connected to pin DIOA 63 | 64 | 65 | /* Set DACA to 1.2 volts. */ 66 | 67 | //Setting up I2C command 68 | //Make note that the I2C command can only update 1 DAC channel at a time. 69 | address = (uint8)(0x24); //Address : h0x24 is the address for DAC 70 | numBytesToSend = 3; //NumI2CByteToSend : 3 bytes to specify DACA and the value 71 | numBytesToReceive = 0; //NumI2CBytesToReceive : 0 since we are only setting the value of the DAC 72 | bytesCommand[0] = (uint8)(0x30); //LJTDAC command byte : h0x30 (DACA) 73 | getTdacBinVoltCalibrated(caliInfo, 0, 1.2, &binaryVoltage); 74 | bytesCommand[1] = (uint8)(binaryVoltage/256); //value (high) 75 | bytesCommand[2] = (uint8)(binaryVoltage & (0x00FF)); //value (low) 76 | 77 | //Performing I2C low-level call 78 | err = I2C(hDevice, options, speedAdjust, sdaPinNum, sclPinNum, address, numBytesToSend, numBytesToReceive, bytesCommand, &errorcode, ackArray, bytesResponse); 79 | 80 | if( checkI2CErrorcode(errorcode) == -1 || err == -1 ) 81 | return -1; 82 | 83 | printf("DACA set to 1.2 volts\n\n"); 84 | 85 | 86 | /* Set DACB to 2.3 volts. */ 87 | 88 | //Setting up I2C command 89 | address = (uint8)(0x24); //Address : h0x24 is the address for DAC 90 | numBytesToSend = 3; //NumI2CByteToSend : 3 bytes to specify DACB and the value 91 | numBytesToReceive = 0; //NumI2CBytesToReceive : 0 since we are only setting the value of the DAC 92 | bytesCommand[0] = (uint8)(0x31); //LJTDAC command byte : h0x31 (DACB) 93 | getTdacBinVoltCalibrated(caliInfo, 1, 2.3, &binaryVoltage); 94 | bytesCommand[1] = (uint8)(binaryVoltage/256); //value (high) 95 | bytesCommand[2] = (uint8)(binaryVoltage & (0x00FF)); //value (low) 96 | 97 | //Performing I2C low-level call 98 | err = I2C(hDevice, options, speedAdjust, sdaPinNum, sclPinNum, address, numBytesToSend, numBytesToReceive, bytesCommand, &errorcode, ackArray, bytesResponse); 99 | 100 | if( checkI2CErrorcode(errorcode) == -1 || err == -1 ) 101 | return -1; 102 | 103 | printf("DACB set to 2.3 volts\n\n"); 104 | 105 | 106 | /* More advanced operations. */ 107 | 108 | /* Display LJTDAC calibration constants. Code for getting the calibration constants is in the 109 | * getLJTDACCalibrationInfo function in the ue9.c file. */ 110 | printf("DACA Slope = %.1f bits/volt\n", caliInfo->ccConstants[0]); 111 | printf("DACA Offset = %.1f bits\n", caliInfo->ccConstants[1]); 112 | printf("DACB Slope = %.1f bits/volt\n", caliInfo->ccConstants[2]); 113 | printf("DACB Offset = %.1f bits\n\n", caliInfo->ccConstants[3]); 114 | 115 | 116 | /* Read the serial number. */ 117 | 118 | //Setting up I2C command 119 | address = (uint8)(0xA0); //Address : h0xA0 is the address for EEPROM 120 | numBytesToSend = 1; //NumI2CByteToSend : 1 byte for the EEPROM address 121 | numBytesToReceive = 4; //NumI2CBytesToReceive : getting 4 bytes starting at EEPROM address specified in I2CByte0 122 | bytesCommand[0] = 96; //I2CByte0 : Memory Address, starting at address 96 (Serial Number) 123 | 124 | //Performing I2C low-level call 125 | err = I2C(hDevice, options, speedAdjust, sdaPinNum, sclPinNum, address, numBytesToSend, numBytesToReceive, bytesCommand, &errorcode, ackArray, bytesResponse); 126 | 127 | if( checkI2CErrorcode(errorcode) == -1 || err == -1 ) 128 | return -1; 129 | 130 | printf("LJTDAC Serial Number = %u\n\n", (bytesResponse[0] + bytesResponse[1]*256 + bytesResponse[2]*65536 + bytesResponse[3]*16777216)); 131 | 132 | 133 | /* User memory example. We will read the memory, update a few elements, 134 | * and write the memory. The user memory is just stored as bytes, so almost 135 | * any information can be put in there such as integers, doubles, or strings. */ 136 | 137 | /* Read the user memory */ 138 | 139 | //Setting up I2C command 140 | address = (uint8)(0xA0); //Address : h0xA0 is the address for EEPROM 141 | numBytesToSend = 1; //NumI2CByteToSend : 1 byte for the EEPROM address 142 | numBytesToReceive = 64; //NumI2CBytesToReceive : getting 64 bytes starting at EEPROM address specified in I2CByte0 143 | bytesCommand[0] = 0; //I2CByte0 : Memory Address, starting at address 0 (User Area) 144 | 145 | //Performing I2C low-level call 146 | err = I2C(hDevice, options, speedAdjust, sdaPinNum, sclPinNum, address, numBytesToSend, numBytesToReceive, bytesCommand, &errorcode, ackArray, bytesResponse); 147 | 148 | if( checkI2CErrorcode(errorcode) == -1 || err == -1 ) 149 | return -1; 150 | 151 | //Display the first 4 elements. 152 | printf("Read User Mem [0-3] = %d, %d, %d, %d\n", bytesResponse[0], bytesResponse[1], bytesResponse[2], bytesResponse[3]); 153 | 154 | 155 | /* Create 4 new pseudo-random numbers to write. We will update the first 156 | * 4 elements of user memory, but the rest will be unchanged. */ 157 | 158 | //Setting up I2C command 159 | address = (uint8)(0xA0); //Address : h0xA0 is the address for EEPROM 160 | numBytesToSend = 5; //NumI2CByteToSend : 1 byte for the EEPROM address and the rest for the bytes to write 161 | numBytesToReceive = 0; //NumI2CBytesToReceive : 0 since we are only writing to memory 162 | bytesCommand[0] = 0; //I2CByte0 : Memory Address, starting at address 0 (User Area) 163 | srand((unsigned int)getTickCount()); 164 | for( i = 1; i < 5; i++ ) 165 | bytesCommand[i] = (uint8)(255*((float)rand()/RAND_MAX));; //I2CByte : byte in user memory 166 | 167 | printf("Write User Mem [0-3] = %d, %d, %d, %d\n", bytesCommand[1], bytesCommand[2], bytesCommand[3], bytesCommand[4]); 168 | 169 | //Performing I2C low-level call 170 | err = I2C(hDevice, options, speedAdjust, sdaPinNum, sclPinNum, address, numBytesToSend, numBytesToReceive, bytesCommand, &errorcode, ackArray, bytesResponse); 171 | 172 | if( checkI2CErrorcode(errorcode) == -1 || err == -1 ) 173 | return -1; 174 | 175 | //Delay for 2 ms to allow the EEPROM to finish writing. 176 | //Re-read the user memory. 177 | usleep(2000); 178 | 179 | //Setting up I2C command 180 | address = (uint8)(0xA0); //Address : h0xA0 is the address for EEPROM 181 | numBytesToSend = 1; //NumI2CByteToSend : 1 byte for the EEPROM address 182 | numBytesToReceive = 64; //NumI2CBytesToReceive : getting 64 bytes starting at EEPROM address specified in I2CByte0 183 | bytesCommand[0] = 0; //I2CByte0 : Memory Address, starting at address 0 (User Area) 184 | 185 | //Performing I2C low-level call 186 | err = I2C(hDevice, options, speedAdjust, sdaPinNum, sclPinNum, address, numBytesToSend, numBytesToReceive, bytesCommand, &errorcode, ackArray, bytesResponse); 187 | 188 | if( checkI2CErrorcode(errorcode) == -1 || err == -1 ) 189 | return -1; 190 | 191 | //Display the first 4 elements. 192 | printf("Read User Mem [0-3] = %d, %d, %d, %d\n", bytesResponse[0], bytesResponse[1], bytesResponse[2], bytesResponse[3]); 193 | 194 | return err; 195 | } 196 | -------------------------------------------------------------------------------- /INSTALL.Linux: -------------------------------------------------------------------------------- 1 | Exodriver (liblabjackusb) Library Installation Instructions 2 | ============================================================ 3 | 4 | 5 | Table of Contents 6 | ----------------- 7 | 8 | Linux Requirements 9 | 10 | About These Instructions 11 | 12 | liblabjackusb Library Script Installation 13 | 14 | Install Without Root 15 | 16 | Compiling and Running the Example Programs 17 | 18 | Machines Using VirtualBox 19 | 20 | liblabjackusb Library Manual Installation 21 | 22 | LabJackPython and the Exodriver on Ubuntu 10.04 23 | 24 | Uninstalling the Old U3 and UE9 Driver 25 | 26 | 27 | Linux Requirements 28 | ------------------ 29 | 30 | 1. GNU C compiler (gcc). 31 | For example in Ubuntu, run the following shell command to get it if needed: 32 | $ sudo apt-get install build-essential 33 | 34 | 2. The libusb-1.0 library and development files. Download the source here: 35 | http://libusb.info 36 | 37 | 3. Linux kernel 2.6.28 or higher. To use older 2.6.x kernels, you must upgrade 38 | your firmware. These are the required firmware versions when using older 39 | 2.6 kernels: 40 | 41 | * U3 with hardware version 1.30 or higher - Firmware 1.18 and higher 42 | * U3 with hardware version less than 1.30 - Only kernel 2.6.28 and higher 43 | supported. Unsupported on older kernels. 44 | * U6 - Firmware 0.81 and greater 45 | * UE9 - Comm Firmware 1.49 and greater 46 | 47 | 4. Uninstall any old U3 and UE9 kernel-module based drivers. The old driver 48 | and custom kernel modules conflict with the current liblabjackusb library. 49 | See the "Uninstalling the Old U3 and UE9 Driver" section for more 50 | information. 51 | 52 | 53 | About These Instructions 54 | ------------------------ 55 | All lines that start with a dollar sign ($) are commands and need to be run 56 | from a terminal. For example, the Terminal application in Ubuntu version 10.04 57 | is usually accessed through Applications -> Accessories -> Terminal. 58 | 59 | 60 | liblabjackusb Library Script Installation 61 | ----------------------------------------- 62 | 63 | In the exodriver/ directory, run the following command: 64 | 65 | $ sudo ./install.sh 66 | 67 | This script will attempt to build, install, and make any necessary system 68 | configurations so that the user that runs it will be able to use LabJack 69 | devices. 70 | 71 | For information on allowing multiple users to use LabJack devices, see the 72 | "Permissions" section under "liblabjackusb Library Manual Installation". 73 | 74 | For more information, read the section titled liblabjackusb Library Manual 75 | Installation later in this file. 76 | 77 | 78 | Install Without Root 79 | -------------------- 80 | 81 | To install without root / sudo access, invoke `make install` with: 82 | - PREFIX set to the desired installation directory 83 | - LINK_SO set to true 84 | - RUN_LDCONFIG set to false 85 | 86 | For example: 87 | 88 | $ cd libjabjack/ 89 | $ make 90 | $ make install PREFIX=myprefix LINK_SO=1 RUN_LDCONFIG=0 91 | 92 | Note: when installing without root and setting up LabJackPython, the 93 | LabJackPython.py source file will need to be modified to properly load the 94 | liblabjackusb library. Change the line in the _loadLinuxSo() function 95 | From: 96 | l = ctypes.CDLL("liblabjackusb.so", use_errno=True) 97 | To: 98 | l = ctypes.CDLL("new absolute path for liblabjackusb.so", use_errno=True) 99 | 100 | 101 | Compiling and Running the Example Programs 102 | ------------------------------------------ 103 | 104 | The example code/programs use the liblabjackusb library and the labjackusb.h 105 | header files in the liblabjackusb/ directory. 106 | 107 | The examples are located in the U3, U6, and UE9 subdirectories in the examples/ 108 | directory. To compile the programs go to your device's directory and run 109 | 110 | $ cd examples/U6/ 111 | $ make 112 | 113 | Run one of example programs like this: 114 | 115 | $ ./u6BasicConfigU6 116 | 117 | 118 | Machines Using VirtualBox 119 | ------------------------- 120 | Customers using Oracle's VirtualBox software should add themselves to the 121 | vboxusers group, either through their distribution's GUI interface or through 122 | the command: sudo usermod -a -G vboxusers USERNAME 123 | 124 | 125 | liblabjackusb Library Manual Installation 126 | ----------------------------------------- 127 | For Ubuntu 10.04, see the section titled "Up and running with LabJackPython 128 | and the Exodriver on Ubuntu 10.04" later in this document. 129 | 130 | In the liblabjackusb/ directory, run the following commands to compile and 131 | install the library. 132 | 133 | $ cd liblabjackusb/ 134 | $ make 135 | $ sudo make install 136 | 137 | Programs that use liblabjackusb will need to access the USB device bus at 138 | /dev/bus/usb/, without root permission. On Debian-based distributions, we 139 | provide udev rules that allow all users to access LabJack devices. 140 | 141 | To Install The udev Rules: 142 | 143 | To install the udev rules, run the following command from the root 144 | directory of this package: 145 | 146 | $ sudo cp 90-labjack.rules /lib/udev/rules.d 147 | 148 | Next, reload the udev rules. For instructions, see the section "To Reload the 149 | udev Rules" below. 150 | 151 | To Set Restrictive Permissions: 152 | 153 | The current udev rules in 90-labjack.rules give LabJack device access to all 154 | users. If you need to restrict permissions, alter 90-labjack.rules or install 155 | custom rules to /etc/udev/rules.d/, which takes priority over 156 | /lib/udev/rules.d/. For example, to restrict usage to members of the adm group: 157 | 158 | $ sudo cat > /etc/udev/rules.d/90-labjack.rules << EOF 159 | SUBSYSTEM!="usb_device", ACTION!="add", GOTO="labjack_rules_end" 160 | 161 | # LabJack Vendor ID 162 | ATTRS{idVendor}=="0cd5", MODE="0664", GROUP="adm" 163 | 164 | LABEL="labjack_rules_end" 165 | 166 | Next, reload the udev rules. For instructions, see the section "To Reload the 167 | udev Rules" below. Also, notice that the MODE is 0664, which is the only 168 | difference between what's installed as /lib/udev/rules.d/90-labjack.rules by 169 | default. For more information about writing udev rules, see "man udev". 170 | 171 | To Reload the udev Rules: 172 | 173 | To reload the udev rules, the following command works on most systems: 174 | 175 | $ sudo udevadm control --reload-rules 176 | 177 | Older vesions of udevadm (e.g., the version included in Ubuntu 8.04) use an 178 | underscore instead of a dash: "--reload_rules" instead of "--reload-rules": 179 | 180 | $ sudo udevadm control --reload_rules 181 | 182 | On Debian-based distributions, the above two commands are sufficient. If 183 | your distribution does not have udevadm, restart udev or restart your 184 | computer. On a Fedora machine run: 185 | 186 | $ sudo /etc/init.d/udev-post reload 187 | 188 | 189 | LabJackPython and the Exodriver on Ubuntu 10.04 190 | ----------------------------------------------- 191 | 192 | As we detailed in May 2010 (updated with the "liblabjackusb Library Manual 193 | Installation" section's steps): 194 | 195 | http://labjack.com/blog/running-labjackpython-and-exodriver-ubuntu-1004 196 | 197 | Ubuntu 10.04 comes with a binary release of libusb-1.0, so building the 198 | Exodriver is easier than ever. Install the dependencies with apt-get, 199 | checkout the Exodriver source code, and build it. Here are the complete 200 | steps, along with a handful of steps at the end that build LabJackPython 201 | (http://labjack.com/support/labjackpython) which is our Python module 202 | that works well with the Exodriver: 203 | 204 | $ sudo apt-get install build-essential 205 | $ sudo apt-get install libusb-1.0-0-dev 206 | $ sudo apt-get install git-core 207 | $ git clone git://github.com/labjack/exodriver.git 208 | $ cd exodriver/ 209 | $ sudo ./install.sh 210 | $ cd .. 211 | $ git clone git://github.com/labjack/LabJackPython.git 212 | $ cd LabJackPython/ 213 | $ sudo python setup.py install 214 | $ python 215 | >>> import u3 216 | >>> d = u3.U3() 217 | >>> d.configU3() 218 | 219 | 220 | Uninstalling the Old U3 and UE9 Driver 221 | -------------------------------------- 222 | 223 | The old U3 and UE9 driver used custom kernel modules, and will conflict with 224 | with the current liblabjackusb library. To uninstall the old driver please 225 | unload and delete the U3 and/or UE9 kernel modules, delete the liblabjackusb.so 226 | library and remove any scripts or udev rules you may have been using to load 227 | the kernel module's device nodes. The following commands, or similar depending 228 | on the directories you copied files to, should help prepare your system for the 229 | new liblabjackusb 2.0 library: 230 | 231 | $ rmmod labjacku3 232 | $ rm labjacku3.ko /lib/modules/`uname -r`/kernel/drivers/usb/misc/labjacku3.ko 233 | $ depmod -a 234 | $ rm /usr/lib/liblabjackusb.so 235 | 236 | These commands remove the udev rules we provided on the forums: 237 | 238 | $ rm /etc/udev/rules.d/10-labjack.rules 239 | $ sudo udevadm control --reload-rules 240 | -------------------------------------------------------------------------------- /examples/U3/u3BasicConfigU3.c: -------------------------------------------------------------------------------- 1 | /* 2 | An example that shows a minimal use of Exodriver without the use of functions 3 | hidden in header files. 4 | 5 | You can compile this example with the following command: 6 | $ g++ -lm -llabjackusb u3BasicConfigU3.c 7 | 8 | It is also included in the Makefile. 9 | 10 | */ 11 | 12 | /* Includes */ 13 | #include 14 | #include 15 | #include 16 | #include "labjackusb.h" 17 | 18 | // Defines how long the command is 19 | #define CONFIGU3_COMMAND_LENGTH 26 20 | 21 | // Defines how long the response is 22 | #define CONFIGU3_RESPONSE_LENGTH 38 23 | 24 | /* Buffer Helper Functions Protypes */ 25 | // Takes a buffer and an offset, and turns it into a 32-bit integer 26 | int makeInt(BYTE * buffer, int offset); 27 | 28 | // Takes a buffer and an offset, and turns it into a 16-bit integer 29 | int makeShort(BYTE * buffer, int offset); 30 | 31 | // Takes a buffer and calculates the checksum8 of it. 32 | BYTE calculateChecksum8(BYTE* buffer); 33 | 34 | // Takes a buffer and length, and calculates the checksum16 of the buffer. 35 | int calculateChecksum16(BYTE* buffer, int len); 36 | 37 | /* LabJack Related Helper Functions Protoypes */ 38 | 39 | // Demonstrates how to build the ConfigU3 packet. 40 | void buildConfigU3Bytes(BYTE * sendBuffer); 41 | 42 | // Demonstrates how to check a response for errors. 43 | int checkResponseForErrors(BYTE * recBuffer); 44 | 45 | // Demonstrates how to parse the response of ConfigU3. 46 | void parseConfigU3Bytes(BYTE * recBuffer); 47 | 48 | int main() { 49 | // Setup the variables we will need. 50 | int r = 0; // For checking return values 51 | HANDLE devHandle = 0; 52 | BYTE sendBuffer[CONFIGU3_COMMAND_LENGTH], recBuffer[CONFIGU3_RESPONSE_LENGTH]; 53 | 54 | // Open the U3 55 | devHandle = LJUSB_OpenDevice(1, 0, U3_PRODUCT_ID); 56 | 57 | if( devHandle == NULL ) { 58 | printf("Couldn't open U3. Please connect one and try again.\n"); 59 | exit(-1); 60 | } 61 | 62 | // Builds the ConfigU3 command 63 | buildConfigU3Bytes(sendBuffer); 64 | 65 | // Write the command to the device. 66 | // LJUSB_Write( handle, sendBuffer, length of sendBuffer ) 67 | r = LJUSB_Write( devHandle, sendBuffer, CONFIGU3_COMMAND_LENGTH ); 68 | 69 | if( r != CONFIGU3_COMMAND_LENGTH ) { 70 | printf("An error occurred when trying to write the buffer. The error was: %d\n", errno); 71 | // *Always* close the device when you error out. 72 | LJUSB_CloseDevice(devHandle); 73 | exit(-1); 74 | } 75 | 76 | // Read the result from the device. 77 | // LJUSB_Read( handle, recBuffer, number of bytes to read) 78 | r = LJUSB_Read( devHandle, recBuffer, CONFIGU3_RESPONSE_LENGTH ); 79 | 80 | if( r != CONFIGU3_RESPONSE_LENGTH ) { 81 | printf("An error occurred when trying to read from the U3. The error was: %d\n", errno); 82 | LJUSB_CloseDevice(devHandle); 83 | exit(-1); 84 | } 85 | 86 | // Check the command for errors 87 | if( checkResponseForErrors(recBuffer) != 0 ){ 88 | LJUSB_CloseDevice(devHandle); 89 | exit(-1); 90 | } 91 | 92 | // Parse the response into something useful 93 | parseConfigU3Bytes(recBuffer); 94 | 95 | //Close the device. 96 | LJUSB_CloseDevice(devHandle); 97 | 98 | return 0; 99 | } 100 | 101 | /* ------------- LabJack Related Helper Functions Definitions ------------- */ 102 | 103 | // Uses information from section 5.2.2 of the U3 User's Guide to make a ConfigU3 104 | // packet. 105 | // http://labjack.com/support/u3/users-guide/5.2.2 106 | void buildConfigU3Bytes(BYTE * sendBuffer) { 107 | int i; // For loops 108 | int checksum = 0; 109 | 110 | // Build up the bytes 111 | //sendBuffer[0] = Checksum8 112 | sendBuffer[1] = 0xF8; 113 | sendBuffer[2] = 0x0A; 114 | sendBuffer[3] = 0x08; 115 | //sendBuffer[4] = Checksum16 (LSB) 116 | //sendBuffer[5] = Checksum16 (MSB) 117 | 118 | // We just want to read, so we set the WriteMask to zero, and zero out the 119 | // rest of the bytes. 120 | sendBuffer[6] = 0; 121 | for( i = 7; i < CONFIGU3_COMMAND_LENGTH; i++){ 122 | sendBuffer[i] = 0; 123 | } 124 | 125 | // Calculate and set the checksum16 126 | checksum = calculateChecksum16(sendBuffer, CONFIGU3_COMMAND_LENGTH); 127 | sendBuffer[4] = (BYTE)( checksum & 0xff ); 128 | sendBuffer[5] = (BYTE)( (checksum / 256) & 0xff ); 129 | 130 | // Calculate and set the checksum8 131 | sendBuffer[0] = calculateChecksum8(sendBuffer); 132 | 133 | // The bytes have been set, and the checksum calculated. We are ready to 134 | // write to the U3. 135 | } 136 | 137 | // Checks the response for any errors. 138 | int checkResponseForErrors(BYTE * recBuffer) { 139 | if(recBuffer[0] == 0xB8 && recBuffer[1] == 0xB8) { 140 | // If the packet is [ 0xB8, 0xB8 ], that's a bad checksum. 141 | printf("The U3 detected a bad checksum. Double check your checksum calculations and try again.\n"); 142 | return -1; 143 | } 144 | else if (recBuffer[1] != 0xF8 || recBuffer[2] != 0x10 || recBuffer[3] != 0x08) { 145 | // Make sure the command bytes match what we expect. 146 | printf("Got the wrong command bytes back from the U3.\n"); 147 | return -1; 148 | } 149 | 150 | // Calculate the checksums. 151 | int checksum16 = calculateChecksum16(recBuffer, CONFIGU3_RESPONSE_LENGTH); 152 | BYTE checksum8 = calculateChecksum8(recBuffer); 153 | 154 | if ( checksum8 != recBuffer[0] || recBuffer[4] != (BYTE)( checksum16 & 0xff ) || recBuffer[5] != (BYTE)( (checksum16 / 256) & 0xff ) ) { 155 | // Check the checksum 156 | 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] ); 157 | return -1; 158 | } 159 | else if ( recBuffer[6] != 0 ) { 160 | // Check the error code in the packet. See section 5.3 of the U3 161 | // User's Guide for errorcode descriptions. 162 | printf("Command returned with an errorcode = %d\n", recBuffer[6]); 163 | return -1; 164 | } 165 | 166 | return 0; 167 | 168 | } 169 | 170 | // Parses the ConfigU3 packet into something useful. 171 | void parseConfigU3Bytes(BYTE * recBuffer){ 172 | printf("Results of ConfigU3:\n"); 173 | printf(" FirmwareVersion = %d.%02d\n", recBuffer[10], recBuffer[9]); 174 | printf(" BootloaderVersion = %d.%02d\n", recBuffer[12], recBuffer[11]); 175 | printf(" HardwareVersion = %d.%02d\n", recBuffer[14], recBuffer[13]); 176 | printf(" SerialNumber = %d\n", makeInt(recBuffer, 15)); 177 | printf(" ProductID = %d\n", makeShort(recBuffer, 19)); 178 | printf(" LocalID = %d\n", recBuffer[21]); 179 | printf(" TimerCounterMask = %d\n", recBuffer[22]); 180 | printf(" FIOAnalog = %d\n", recBuffer[23]); 181 | printf(" FIODireciton = %d\n", recBuffer[24]); 182 | printf(" FIOState = %d\n", recBuffer[25]); 183 | printf(" EIOAnalog = %d\n", recBuffer[26]); 184 | printf(" EIODirection = %d\n", recBuffer[27]); 185 | printf(" EIOState = %d\n", recBuffer[28]); 186 | printf(" CIODirection = %d\n", recBuffer[29]); 187 | printf(" CIOState = %d\n", recBuffer[30]); 188 | printf(" DAC1Enable = %d\n", recBuffer[31]); 189 | printf(" DAC0 = %d\n", recBuffer[32]); 190 | printf(" DAC1 = %d\n", recBuffer[33]); 191 | printf(" TimerClockConfig = %d\n", recBuffer[34]); 192 | printf(" TimerClockDivisor = %d\n", recBuffer[35]); 193 | printf(" CompatibilityOptions = %d\n", recBuffer[36]); 194 | printf(" VersionInfo = %d\n", recBuffer[37]); 195 | 196 | if( recBuffer[37] == 0 ){ 197 | printf(" DeviceName = U3A\n"); 198 | } 199 | else if(recBuffer[37] == 1) { 200 | printf(" DeviceName = U3B\n"); 201 | } 202 | else if(recBuffer[37] == 2) { 203 | printf(" DeviceName = U3-LV\n"); 204 | } 205 | else if(recBuffer[37] == 18) { 206 | printf(" DeviceName = U3-HV\n"); 207 | } 208 | 209 | } 210 | 211 | 212 | /* ---------------- Buffer Helper Functions Definitions ---------------- */ 213 | 214 | // Takes a buffer and an offset, and turns into an 32-bit integer 215 | int makeInt(BYTE * buffer, int offset){ 216 | return (buffer[offset+3] << 24) + (buffer[offset+2] << 16) + (buffer[offset+1] << 8) + buffer[offset]; 217 | } 218 | 219 | // Takes a buffer and an offset, and turns into an 16-bit integer 220 | int makeShort(BYTE * buffer, int offset) { 221 | return (buffer[offset+1] << 8) + buffer[offset]; 222 | } 223 | 224 | // Calculates the checksum8 225 | BYTE calculateChecksum8(BYTE* buffer){ 226 | int i; // For loops 227 | int temp; // For holding a value while we working. 228 | int checksum = 0; 229 | 230 | for( i = 1; i < 6; i++){ 231 | checksum += buffer[i]; 232 | } 233 | 234 | temp = checksum/256; 235 | checksum = ( checksum - 256 * temp ) + temp; 236 | temp = checksum/256; 237 | 238 | return (BYTE)( ( checksum - 256 * temp ) + temp ); 239 | } 240 | 241 | // Calculates the checksum16 242 | int calculateChecksum16(BYTE* buffer, int len){ 243 | int i; 244 | int checksum = 0; 245 | 246 | for( i = 6; i < len; i++){ 247 | checksum += buffer[i]; 248 | } 249 | 250 | return checksum; 251 | } 252 | -------------------------------------------------------------------------------- /examples/UE9/ue9EthernetExample.c: -------------------------------------------------------------------------------- 1 | /* 2 | An example that shows how to use sockets to talk with the UE9. You may notice 3 | that the code is VERY similar to ue9BasicCommConfig.c. The only difference is 4 | using socket calls instead of calls to the Exodriver. 5 | 6 | You can compile this example with the following command: 7 | $ g++ -o ue9EthernetExample ue9EthernetExample.c 8 | 9 | To run it: 10 | $ ./ue9EthernetExample 11 | 12 | It is also included in the Makefile. 13 | */ 14 | 15 | //Because that is what an unsigned char is. 16 | typedef unsigned char BYTE; 17 | 18 | /* Includes */ 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | 28 | // Defines how long the command is 29 | #define COMMCONFIG_COMMAND_LENGTH 38 30 | 31 | // Defines how long the response is 32 | #define COMMCONFIG_RESPONSE_LENGTH 38 33 | 34 | /* Buffer Helper Functions Protypes */ 35 | // Takes a buffer and an offset, and turns it into a 32-bit integer 36 | int makeInt(BYTE * buffer, int offset); 37 | 38 | // Takes a buffer and an offset, and turns it into a 16-bit integer 39 | int makeShort(BYTE * buffer, int offset); 40 | 41 | // Takes a buffer and calculates the checksum8 of it. 42 | BYTE calculateChecksum8(BYTE* buffer); 43 | 44 | // Takes a buffer and length, and calculates the checksum16 of the buffer. 45 | int calculateChecksum16(BYTE* buffer, int len); 46 | 47 | /* LabJack Related Helper Functions Protoypes */ 48 | 49 | // Demonstrates how to build the CommConfig packet. 50 | void buildCommConfigBytes(BYTE * sendBuffer); 51 | 52 | // Demonstrates how to check a response for errors. 53 | int checkResponseForErrors(BYTE * recBuffer); 54 | 55 | // Demonstrates how to parse the response of CommConfig. 56 | void parseCommConfigBytes(BYTE * recBuffer); 57 | 58 | int main(int argc, char *argv[]) { 59 | // Setup the variables we will need. 60 | int r = 0; // For checking return values 61 | int devHandle = 0; 62 | BYTE sendBuffer[COMMCONFIG_COMMAND_LENGTH], recBuffer[COMMCONFIG_RESPONSE_LENGTH]; 63 | struct addrinfo hints, *res; 64 | 65 | if(argc < 2) { 66 | fprintf(stderr,"Usage: %s \n", argv[0]); 67 | exit(-1); 68 | } 69 | 70 | memset(&hints, 0, sizeof hints); 71 | hints.ai_family = AF_UNSPEC; 72 | hints.ai_socktype = SOCK_STREAM; 73 | printf("Getting IP Info... "); 74 | r = getaddrinfo(argv[1], "52360", &hints, &res); 75 | if( r != 0 ){ 76 | perror("Couldn't parse address info. Error: "); 77 | exit(-1); 78 | } 79 | printf("Done\n"); 80 | 81 | printf("Getting socket FD... "); 82 | // Open the UE9, through a socket. 83 | devHandle = socket(AF_INET, SOCK_STREAM, 0); 84 | if( devHandle < 0 ) { 85 | perror("Couldn't open socket."); 86 | exit(-1); 87 | } 88 | printf("Done\n"); 89 | 90 | printf("Connecting (time out after a minute)... "); 91 | fflush(stdout); 92 | r = connect(devHandle, res->ai_addr, res->ai_addrlen); 93 | if( r < 0 ){ 94 | perror("\nCouldn't connect to UE9. The error was"); 95 | close(devHandle); 96 | exit(-1); 97 | } 98 | printf("Done\n"); 99 | 100 | // Builds the CommConfig command 101 | buildCommConfigBytes(sendBuffer); 102 | 103 | // Write the command to the device. 104 | // LJUSB_Write( handle, sendBuffer, length of sendBuffer ) 105 | r = write( devHandle, sendBuffer, COMMCONFIG_COMMAND_LENGTH ); 106 | 107 | if( r != COMMCONFIG_COMMAND_LENGTH ) { 108 | printf("An error occurred when trying to write the buffer. The error was: %d\n", errno); 109 | // *Always* close the device when you error out. 110 | close(devHandle); 111 | exit(-1); 112 | } 113 | 114 | // Read the result from the device. 115 | // LJUSB_Read( handle, recBuffer, number of bytes to read) 116 | r = read( devHandle, recBuffer, COMMCONFIG_RESPONSE_LENGTH ); 117 | 118 | if( r != COMMCONFIG_RESPONSE_LENGTH ) { 119 | printf("An error occurred when trying to read from the UE9. The error was: %d\n", errno); 120 | close(devHandle); 121 | exit(-1); 122 | } 123 | 124 | // Check the command for errors 125 | if( checkResponseForErrors(recBuffer) != 0 ){ 126 | close(devHandle); 127 | exit(-1); 128 | } 129 | 130 | // Parse the response into something useful 131 | parseCommConfigBytes(recBuffer); 132 | 133 | //Close the device. 134 | close(devHandle); 135 | 136 | return 0; 137 | } 138 | 139 | /* ------------- LabJack Related Helper Functions Definitions ------------- */ 140 | 141 | // Uses information from section 5.2.1 of the UE9 User's Guide to make a CommConfig 142 | // packet. 143 | // http://labjack.com/support/ue9/users-guide/5.2.1 144 | void buildCommConfigBytes(BYTE * sendBuffer) { 145 | int i; // For loops 146 | int checksum = 0; 147 | 148 | // Build up the bytes 149 | //sendBuffer[0] = Checksum8 150 | sendBuffer[1] = 0x78; 151 | sendBuffer[2] = 0x10; 152 | sendBuffer[3] = 0x01; 153 | //sendBuffer[4] = Checksum16 (LSB) 154 | //sendBuffer[5] = Checksum16 (MSB) 155 | 156 | // We just want to read, so we set the WriteMask to zero, and zero out the 157 | // rest of the bytes. 158 | sendBuffer[6] = 0; 159 | for( i = 7; i < COMMCONFIG_COMMAND_LENGTH; i++){ 160 | sendBuffer[i] = 0; 161 | } 162 | 163 | // Calculate and set the checksum16 164 | checksum = calculateChecksum16(sendBuffer, COMMCONFIG_COMMAND_LENGTH); 165 | sendBuffer[4] = (BYTE)( checksum & 0xff ); 166 | sendBuffer[5] = (BYTE)( (checksum / 256) & 0xff ); 167 | 168 | // Calculate and set the checksum8 169 | sendBuffer[0] = calculateChecksum8(sendBuffer); 170 | 171 | // The bytes have been set, and the checksum calculated. We are ready to 172 | // write to the UE9. 173 | } 174 | 175 | // Checks the response for any errors. 176 | int checkResponseForErrors(BYTE * recBuffer) { 177 | if(recBuffer[0] == 0xB8 && recBuffer[1] == 0xB8) { 178 | // If the packet is [ 0xB8, 0xB8 ], that's a bad checksum. 179 | printf("The UE9 detected a bad checksum. Double check your checksum calculations and try again.\n"); 180 | return -1; 181 | } 182 | else if (recBuffer[1] == 0x78 && recBuffer[2] == 0x10 && recBuffer[2] == 0x01) { 183 | // Make sure the command bytes match what we expect. 184 | printf("Got the wrong command bytes back from the UE9.\n"); 185 | return -1; 186 | } 187 | // Normally, we would check byte 6 for errorcodes. CommConfig is an 188 | // exception to that rule. 189 | 190 | // Calculate the checksums. 191 | int checksum16 = calculateChecksum16(recBuffer, COMMCONFIG_RESPONSE_LENGTH); 192 | BYTE checksum8 = calculateChecksum8(recBuffer); 193 | 194 | if ( checksum8 != recBuffer[0] || recBuffer[4] != (BYTE)( checksum16 & 0xff ) || recBuffer[5] != (BYTE)( (checksum16 / 256) & 0xff ) ) { 195 | // Check the checksum 196 | 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] ); 197 | return -1; 198 | } 199 | 200 | return 0; 201 | 202 | } 203 | 204 | // Parses the CommConfig packet into something useful. 205 | void parseCommConfigBytes(BYTE * recBuffer){ 206 | printf("Results of CommConfig:\n"); 207 | printf(" LocalID = %d\n", recBuffer[8]); 208 | printf(" PowerLevel = %d\n", recBuffer[9]); 209 | printf(" IPAddress = %d.%d.%d.%d\n", recBuffer[13], recBuffer[12], recBuffer[11], recBuffer[10] ); 210 | printf(" Gateway = %d.%d.%d.%d\n", recBuffer[17], recBuffer[16], recBuffer[15], recBuffer[14] ); 211 | printf(" Subnet = %d.%d.%d.%d\n", recBuffer[21], recBuffer[20], recBuffer[19], recBuffer[18] ); 212 | printf(" PortA = %d\n", makeShort(recBuffer, 22)); 213 | printf(" PortB = %d\n", makeShort(recBuffer, 24)); 214 | printf(" DHCPEnabled = %d\n", recBuffer[26]); 215 | printf(" ProductID = %d\n", recBuffer[27]); 216 | printf(" MACAddress = %02X:%02X:%02X:%02X:%02X:%02X\n", recBuffer[33], recBuffer[32], recBuffer[31], recBuffer[30], recBuffer[29], recBuffer[28]); 217 | 218 | BYTE serialBytes[4]; 219 | serialBytes[0] = recBuffer[28]; 220 | serialBytes[1] = recBuffer[29]; 221 | serialBytes[2] = recBuffer[30]; 222 | serialBytes[3] = 0x10; 223 | printf(" SerialNumber = %d\n", makeInt(serialBytes, 0)); 224 | 225 | printf(" HardwareVersion = %d.%02d\n", recBuffer[35], recBuffer[34]); 226 | printf(" FirmwareVersion = %d.%02d\n", recBuffer[37], recBuffer[36]); 227 | } 228 | 229 | 230 | /* ---------------- Buffer Helper Functions Definitions ---------------- */ 231 | 232 | // Takes a buffer and an offset, and turns into an 32-bit integer 233 | int makeInt(BYTE * buffer, int offset){ 234 | return (buffer[offset+3] << 24) + (buffer[offset+2] << 16) + (buffer[offset+1] << 8) + buffer[offset]; 235 | } 236 | 237 | // Takes a buffer and an offset, and turns into an 16-bit integer 238 | int makeShort(BYTE * buffer, int offset) { 239 | return (buffer[offset+1] << 8) + buffer[offset]; 240 | } 241 | 242 | // Calculates the checksum8 243 | BYTE calculateChecksum8(BYTE* buffer){ 244 | int i; // For loops 245 | int temp; // For holding a value while we working. 246 | int checksum = 0; 247 | 248 | for( i = 1; i < 6; i++){ 249 | checksum += buffer[i]; 250 | } 251 | 252 | temp = checksum/256; 253 | checksum = ( checksum - 256 * temp ) + temp; 254 | temp = checksum/256; 255 | 256 | return (BYTE)( ( checksum - 256 * temp ) + temp ); 257 | } 258 | 259 | // Calculates the checksum16 260 | int calculateChecksum16(BYTE* buffer, int len){ 261 | int i; 262 | int checksum = 0; 263 | 264 | for( i = 6; i < len; i++){ 265 | checksum += buffer[i]; 266 | } 267 | 268 | return checksum; 269 | } -------------------------------------------------------------------------------- /examples/U6/u6allio.c: -------------------------------------------------------------------------------- 1 | //Author : LabJack 2 | //April 8, 2016 3 | //This example demonstrates how to write and read some or all analog I/O. 4 | //By default, it records the time for 1000 iterations and divides by 1000, 5 | //to allow measurement of the basic command/response communication times. These 6 | //times should be comparable to the Windows command/response communication 7 | //times documented in Section 3.1 of the U6 User's Guide. 8 | 9 | #include 10 | #include "u6.h" 11 | 12 | const int numIterations = 1000; //Number of Feedback calls that will be performed. 13 | const uint8 numChannels = 8; //Number of AIN channels, 0-14. 14 | const uint8 settlingFactor = 0; //0=Auto, 1=20us, 2=50us, 3=100us, 4=200us, 5=500us, 6=1ms, 7=2ms, 8=5ms, 9=10ms. 15 | const uint8 gainIndex = 0; //0=x1 (+-10V), 1=x10 (+-1V), 2=x100 (+-0.1V), 3=x1000 (+-0.01mV), 15=autorange. 16 | const uint8 resolution = 1; //0=default, 1-8 for high-speed ADC, 9-12 for high-res ADC on U6-Pro. 17 | const uint8 differential = 0; //Indicates whether to do differential readings. 1=true, 0=false. 18 | 19 | int allIO(HANDLE hDevice, u6CalibrationInfo *caliInfo); 20 | 21 | int main(int argc, char **argv) 22 | { 23 | HANDLE hDevice; 24 | u6CalibrationInfo caliInfo; 25 | 26 | //Opening first found U6 over USB 27 | if( (hDevice = openUSBConnection(-1)) == NULL ) 28 | goto done; 29 | 30 | //Getting calibration information from U6 31 | if( getCalibrationInfo(hDevice, &caliInfo) < 0 ) 32 | goto close; 33 | 34 | allIO(hDevice, &caliInfo); 35 | 36 | close: 37 | closeUSBConnection(hDevice); 38 | done: 39 | return 0; 40 | } 41 | 42 | //Calls the Feedback low-level command numIterations times and calculates the 43 | //time per iteration. 44 | int allIO(HANDLE hDevice, u6CalibrationInfo *caliInfo) 45 | { 46 | uint8 *sendBuff, *recBuff; 47 | uint16 checksumTotal, bits16; 48 | uint32 bits32; 49 | 50 | int sendChars, recChars, i, j, sendSize, recSize; 51 | double valueAIN[14]; 52 | long time; 53 | int ret = 0; 54 | 55 | for( i = 0; i < 14; i++ ) 56 | valueAIN[i] = 9999; 57 | 58 | //Setting up a Feedback command that will set CIO0-3 as input, and setting 59 | //DAC0 voltage 60 | sendBuff = (uint8 *)malloc(18*sizeof(uint8)); //Creating an array of size 18 61 | recBuff = (uint8 *)malloc(10*sizeof(uint8)); //Creating an array of size 10 62 | 63 | sendBuff[1] = (uint8)(0xF8); //Command byte 64 | sendBuff[2] = 6; //Number of data words (.5 word for echo, 5.5 65 | //words for IOTypes and data) 66 | sendBuff[3] = (uint8)(0x00); //Extended command number 67 | 68 | sendBuff[6] = 0; //Echo 69 | sendBuff[7] = 29; //IOType is PortDirWrite 70 | sendBuff[8] = 0; //FIO Writemask 71 | sendBuff[9] = 0; //EIO Writemask 72 | sendBuff[10] = 15; //CIO Writemask 73 | sendBuff[11] = 0; //FIO Direction 74 | sendBuff[12] = 0; //EIO Direction 75 | sendBuff[13] = 0; //CIO Direction 76 | 77 | //Setting DAC0 with 2.5 volt output 78 | sendBuff[14] = 38; //IOType is DAC0(16-bit) 79 | 80 | //Value is 2.5 volts (in binary) 81 | getDacBinVoltCalibrated16Bit(caliInfo, 0, 2.5, &bits16); 82 | sendBuff[15] = (uint8)(bits16&255); 83 | sendBuff[16] = (uint8)(bits16/256); 84 | 85 | sendBuff[17] = 0; //extra padding byte 86 | 87 | extendedChecksum(sendBuff, 18); 88 | 89 | //Sending command to U6 90 | if( (sendChars = LJUSB_Write(hDevice, sendBuff, 18)) < 18 ) 91 | { 92 | if(sendChars == 0) 93 | printf("Feedback (CIO input) error : write failed\n"); 94 | else 95 | printf("Feedback (CIO input) error : did not write all of the buffer\n"); 96 | ret = -1; 97 | goto cleanmem; 98 | } 99 | 100 | //Reading response from U6 101 | if( (recChars = LJUSB_Read(hDevice, recBuff, 10)) < 10 ) 102 | { 103 | if( recChars == 0 ) 104 | { 105 | printf("Feedback (CIO input) error : read failed\n"); 106 | ret = -1; 107 | goto cleanmem; 108 | } 109 | else 110 | printf("Feedback (CIO input) error : did not read all of the buffer\n"); 111 | } 112 | 113 | checksumTotal = extendedChecksum16(recBuff, 10); 114 | if( (uint8)((checksumTotal / 256) & 0xff) != recBuff[5] ) 115 | { 116 | printf("Feedback (CIO input) error : read buffer has bad checksum16(MSB)\n"); 117 | ret = -1; 118 | goto cleanmem; 119 | } 120 | 121 | if( (uint8)(checksumTotal & 0xff) != recBuff[4] ) 122 | { 123 | printf("Feedback (CIO input) error : read buffer has bad checksum16(LBS)\n"); 124 | ret = -1; 125 | goto cleanmem; 126 | } 127 | 128 | if( extendedChecksum8(recBuff) != recBuff[0] ) 129 | { 130 | printf("Feedback (CIO input) error : read buffer has bad checksum8\n"); 131 | ret = -1; 132 | goto cleanmem; 133 | } 134 | 135 | if( recBuff[1] != (uint8)(0xF8) || recBuff[3] != (uint8)(0x00) ) 136 | { 137 | printf("Feedback (CIO input) error : read buffer has wrong command bytes \n"); 138 | ret = -1; 139 | goto cleanmem; 140 | } 141 | 142 | if( recBuff[6] != 0 ) 143 | { 144 | printf("Feedback (CIO input) error : received errorcode %d for frame %d in Feedback response. \n", recBuff[6], recBuff[7]); 145 | ret = -1; 146 | goto cleanmem; 147 | } 148 | 149 | free(sendBuff); 150 | free(recBuff); 151 | 152 | //Setting up Feedback command that will run numIterations times 153 | if( ((sendSize = 7+numChannels*4) % 2) != 0 ) 154 | sendSize++; //Need an extra byte 155 | sendBuff = (uint8 *)malloc(sendSize*sizeof(uint8)); //Creating an array of size sendSize 156 | 157 | if( ((recSize = 9+numChannels*3) % 2) != 0 ) 158 | recSize++; //Need an extra byte 159 | recBuff = (uint8 *)malloc(recSize*sizeof(uint8)); //Creating an array of size recSize 160 | 161 | sendBuff[1] = (uint8)(0xF8); //Command byte 162 | sendBuff[2] = (sendSize - 6)/2; //Number of data words 163 | sendBuff[3] = (uint8)(0x00); //Extended command number 164 | 165 | sendBuff[6] = 0; //Echo 166 | 167 | sendBuff[sendSize - 1] = 0; //Setting last byte to zero in case it is the extra padding byte 168 | 169 | //Setting AIN read commands 170 | for( j = 0; j < numChannels; j++ ) 171 | { 172 | sendBuff[7 + j*4] = 2; //IOType is AIN24 173 | 174 | //Positive Channel (bits 0 - 4), LongSettling (bit 6) and QuickSample (bit 7) 175 | sendBuff[8 + j*4] = j; //Positive Channel 176 | sendBuff[9 + j*4] = (uint8)(resolution&15) + (uint8)((gainIndex&15)*16); //ResolutionIndex (Bits 0-3), GainIndex (Bits 4-7) 177 | sendBuff[10 + j*4] = (uint8)(settlingFactor&7); //SettlingFactor (Bits 0-2) 178 | if( j%2 == 0 ) 179 | sendBuff[10 + j*4] += (uint8)((differential&1)*128); //Differential (Bits 7) 180 | } 181 | 182 | extendedChecksum(sendBuff, sendSize); 183 | 184 | time = getTickCount(); 185 | 186 | for( i = 0; i < numIterations; i++ ) 187 | { 188 | //Sending command to U6 189 | if( (sendChars = LJUSB_Write(hDevice, sendBuff, sendSize)) < sendSize ) 190 | { 191 | if(sendChars == 0) 192 | printf("Feedback error (Iteration %d): write failed\n", i); 193 | else 194 | printf("Feedback error (Iteration %d): did not write all of the buffer\n", i); 195 | ret = -1; 196 | goto cleanmem; 197 | } 198 | 199 | //Reading response from U6 200 | if( (recChars = LJUSB_Read(hDevice, recBuff, recSize)) < recSize ) 201 | { 202 | if( recChars == 0 ) 203 | { 204 | printf("Feedback error (Iteration %d): read failed\n", i); 205 | ret = -1; 206 | goto cleanmem; 207 | } 208 | } 209 | 210 | checksumTotal = extendedChecksum16(recBuff, recChars); 211 | if( (uint8)((checksumTotal / 256) & 0xff) != recBuff[5] ) 212 | { 213 | printf("Feedback error (Iteration %d): read buffer has bad checksum16(MSB)\n", i); 214 | ret = -1; 215 | goto cleanmem; 216 | } 217 | 218 | if( (uint8)(checksumTotal & 0xff) != recBuff[4] ) 219 | { 220 | printf("Feedback error (Iteration %d): read buffer has bad checksum16(LBS)\n", i); 221 | ret = -1; 222 | goto cleanmem; 223 | } 224 | 225 | if( extendedChecksum8(recBuff) != recBuff[0] ) 226 | { 227 | printf("Feedback error (Iteration %d): read buffer has bad checksum8\n", i); 228 | ret = -1; 229 | goto cleanmem; 230 | } 231 | 232 | if( recBuff[1] != (uint8)(0xF8) || recBuff[3] != (uint8)(0x00) ) 233 | { 234 | printf("Feedback error (Iteration %d): read buffer has wrong command bytes \n", i); 235 | ret = -1; 236 | goto cleanmem; 237 | } 238 | 239 | if( recBuff[6] != 0 ) 240 | { 241 | printf("Feedback error (Iteration %d): received errorcode %d for frame %d in Feedback response. \n", i, recBuff[6], recBuff[7]); 242 | ret = -1; 243 | goto cleanmem; 244 | } 245 | 246 | if( recChars != recSize ) 247 | { 248 | printf("Feedback error (Iteration %d): received packet if %d size when expecting %d\n", i, recChars, recSize); 249 | ret = -1; 250 | goto cleanmem; 251 | } 252 | 253 | //Getting AIN voltages 254 | for(j = 0; j < numChannels; j++) 255 | { 256 | bits32 = recBuff[9+j*3] + recBuff[10+j*3]*256 + recBuff[11+j*3]*65536; 257 | getAinVoltCalibrated(caliInfo, resolution, gainIndex, 1, bits32, &valueAIN[j]); 258 | } 259 | } 260 | 261 | time = getTickCount() - time; 262 | printf("Milliseconds per iteration = %.3f\n", (double)time / (double)numIterations); 263 | printf("\nAIN readings from last iteration:\n"); 264 | 265 | for( j = 0; j < numChannels; j++ ) 266 | printf("%.3f\n", valueAIN[j]); 267 | 268 | cleanmem: 269 | free(sendBuff); 270 | free(recBuff); 271 | sendBuff = NULL; 272 | recBuff = NULL; 273 | 274 | return ret; 275 | } 276 | -------------------------------------------------------------------------------- /examples/U6/u6LJTDAC.c: -------------------------------------------------------------------------------- 1 | //Author: LabJack 2 | //April 5, 2011 3 | //Communicates with an LJTick-DAC using low level functions. The LJTDAC should 4 | //be plugged into FIO2/FIO3 for this example. 5 | 6 | #include "u6.h" 7 | #include 8 | 9 | int configIO_example(HANDLE hDevice); 10 | int checkI2CErrorcode(uint8 errorcode); 11 | int tdac_example(HANDLE hDevice, u6TdacCalibrationInfo *caliInfo); 12 | 13 | int main(int argc, char **argv) 14 | { 15 | HANDLE hDevice; 16 | u6TdacCalibrationInfo caliInfo; 17 | 18 | //Opening first found U6 over USB 19 | if( (hDevice = openUSBConnection(-1)) == NULL ) 20 | goto done; 21 | 22 | if( configIO_example(hDevice) != 0 ) 23 | goto close; 24 | 25 | //Getting calibration information from LJTDAC 26 | if( getTdacCalibrationInfo(hDevice, &caliInfo, 2) < 0 ) 27 | goto close; 28 | 29 | tdac_example(hDevice, &caliInfo); 30 | 31 | close: 32 | closeUSBConnection(hDevice); 33 | done: 34 | return 0; 35 | } 36 | 37 | 38 | //Sends a ConfigIO low-level command to turn off timers/counters 39 | int configIO_example(HANDLE hDevice) 40 | { 41 | uint8 sendBuff[16], recBuff[16]; 42 | uint16 checksumTotal; 43 | int sendChars, recChars, i; 44 | 45 | sendBuff[1] = (uint8)(0xF8); //Command byte 46 | sendBuff[2] = (uint8)(0x03); //Number of data words 47 | sendBuff[3] = (uint8)(0x0B); //Extended command number 48 | 49 | sendBuff[6] = 1; //Writemask : Setting writemask for TimerCounterConfig (bit 0) 50 | 51 | sendBuff[7] = 0; //NumberTimersEnabled : Setting to zero to disable all timers. 52 | sendBuff[8] = 0; //CounterEnable: Setting bit 0 and bit 1 to zero to disable both counters 53 | sendBuff[9] = 0; //TimerCounterPinOffset 54 | 55 | for( i = 10; i < 16; i++ ) 56 | sendBuff[i] = 0; //Reserved 57 | extendedChecksum(sendBuff, 16); 58 | 59 | //Sending command to U6 60 | if( (sendChars = LJUSB_Write(hDevice, sendBuff, 16)) < 16 ) 61 | { 62 | if( sendChars == 0 ) 63 | printf("ConfigIO error : write failed\n"); 64 | else 65 | printf("ConfigIO error : did not write all of the buffer\n"); 66 | return -1; 67 | } 68 | 69 | //Reading response from U6 70 | if( (recChars = LJUSB_Read(hDevice, recBuff, 16)) < 16 ) 71 | { 72 | if( recChars == 0 ) 73 | printf("ConfigIO error : read failed\n"); 74 | else 75 | printf("ConfigIO error : did not read all of the buffer\n"); 76 | return -1; 77 | } 78 | 79 | checksumTotal = extendedChecksum16(recBuff, 15); 80 | if( (uint8)((checksumTotal / 256 ) & 0xff) != recBuff[5] ) 81 | { 82 | printf("ConfigIO error : read buffer has bad checksum16(MSB)\n"); 83 | return -1; 84 | } 85 | 86 | if( (uint8)(checksumTotal & 0xff) != recBuff[4] ) 87 | { 88 | printf("ConfigIO error : read buffer has bad checksum16(LBS)\n"); 89 | return -1; 90 | } 91 | 92 | if( extendedChecksum8(recBuff) != recBuff[0] ) 93 | { 94 | printf("ConfigIO error : read buffer has bad checksum8\n"); 95 | return -1; 96 | } 97 | 98 | if( recBuff[1] != (uint8)(0xF8) || recBuff[2] != (uint8)(0x05) || recBuff[3] != (uint8)(0x0B) ) 99 | { 100 | printf("ConfigIO error : read buffer has wrong command bytes\n"); 101 | return -1; 102 | } 103 | 104 | if( recBuff[6] != 0 ) 105 | { 106 | printf("ConfigIO error : read buffer received errorcode %d\n", recBuff[6]); 107 | return -1; 108 | } 109 | 110 | if( recBuff[8] != 0 ) 111 | { 112 | printf("ConfigIO error : NumberTimersEnabled was not set to 0\n"); 113 | return -1; 114 | } 115 | 116 | if( recBuff[9] != 0 ) 117 | { 118 | printf("ConfigIO error : CounterEnable was not set to 0\n"); 119 | return -1; 120 | } 121 | 122 | return 0; 123 | } 124 | 125 | int checkI2CErrorcode(uint8 errorcode) 126 | { 127 | if( errorcode != 0 ) 128 | { 129 | printf("I2C error : received errorcode %d in response\n", errorcode); 130 | return -1; 131 | } 132 | return 0; 133 | } 134 | 135 | 136 | int tdac_example(HANDLE hDevice, u6TdacCalibrationInfo *caliInfo) 137 | { 138 | int err; 139 | uint8 options, speedAdjust, sdaPinNum, sclPinNum, address, numBytesToSend, numBytesToReceive, errorcode; 140 | uint16 binaryVoltage; 141 | uint8 bytesCommand[5]; 142 | uint8 bytesResponse[64]; 143 | uint8 ackArray[4]; 144 | int i; 145 | 146 | err = 0; 147 | 148 | //Setting up parts I2C command that will remain the same throughout this example 149 | options = 0; //I2COptions : 0 150 | speedAdjust = 0; //SpeedAdjust : 0 (for max communication speed of about 130 kHz) 151 | sdaPinNum = 3; //SDAPinNum : FIO3 connected to pin DIOB 152 | sclPinNum = 2; //SCLPinNum : FIO2 connected to pin DIOA 153 | 154 | 155 | /* Set DACA to 1.2 volts. */ 156 | 157 | //Setting up I2C command 158 | //Make note that the I2C command can only update 1 DAC channel at a time. 159 | address = (uint8)(0x24); //Address : h0x24 is the address for DAC 160 | numBytesToSend = 3; //NumI2CByteToSend : 3 bytes to specify DACA and the value 161 | numBytesToReceive = 0; //NumI2CBytesToReceive : 0 since we are only setting the value of the DAC 162 | bytesCommand[0] = (uint8)(0x30); //LJTDAC command byte : h0x30 (DACA) 163 | 164 | getTdacBinVoltCalibrated(caliInfo, 0, 1.2, &binaryVoltage); 165 | bytesCommand[1] = (uint8)(binaryVoltage/256); //value (high) 166 | bytesCommand[2] = (uint8)(binaryVoltage & (0x00FF)); //value (low) 167 | 168 | //Performing I2C low-level call 169 | err = I2C(hDevice, options, speedAdjust, sdaPinNum, sclPinNum, address, numBytesToSend, numBytesToReceive, bytesCommand, &errorcode, ackArray, bytesResponse); 170 | 171 | if( checkI2CErrorcode(errorcode) == -1 || err == -1 ) 172 | return -1; 173 | 174 | printf("DACA set to 1.2 volts\n\n"); 175 | 176 | 177 | /* Set DACB to 2.3 volts. */ 178 | 179 | //Setting up I2C command 180 | address = (uint8)(0x24); //Address : h0x24 is the address for DAC 181 | numBytesToSend = 3; //NumI2CByteToSend : 3 bytes to specify DACB and the value 182 | numBytesToReceive = 0; //NumI2CBytesToReceive : 0 since we are only setting the value of the DAC 183 | bytesCommand[0] = (uint8)(0x31); //LJTDAC command byte : h0x31 (DACB) 184 | getTdacBinVoltCalibrated(caliInfo, 1, 2.3, &binaryVoltage); 185 | bytesCommand[1] = (uint8)(binaryVoltage/256); //value (high) 186 | bytesCommand[2] = (uint8)(binaryVoltage & (0x00FF)); //value (low) 187 | 188 | //Performing I2C low-level call 189 | err = I2C(hDevice, options, speedAdjust, sdaPinNum, sclPinNum, address, numBytesToSend, numBytesToReceive, bytesCommand, &errorcode, ackArray, bytesResponse); 190 | 191 | if( checkI2CErrorcode(errorcode) == -1 || err == -1 ) 192 | return -1; 193 | 194 | printf("DACB set to 2.3 volts\n\n"); 195 | 196 | 197 | /* More advanced operations. */ 198 | 199 | /* Display LJTDAC calibration constants. Code for getting the calibration constants is in the 200 | * getLJTDACCalibrationInfo function in the u6.c file. */ 201 | printf("DACA Slope = %.1f bits/volt\n", caliInfo->ccConstants[0]); 202 | printf("DACA Offset = %.1f bits\n", caliInfo->ccConstants[1]); 203 | printf("DACB Slope = %.1f bits/volt\n", caliInfo->ccConstants[2]); 204 | printf("DACB Offset = %.1f bits\n\n", caliInfo->ccConstants[3]); 205 | 206 | 207 | /* Read the serial number. */ 208 | 209 | //Setting up I2C command 210 | address = (uint8)(0xA0); //Address : h0xA0 is the address for EEPROM 211 | numBytesToSend = 1; //NumI2CByteToSend : 1 byte for the EEPROM address 212 | numBytesToReceive = 4; //NumI2CBytesToReceive : getting 4 bytes starting at EEPROM address specified in I2CByte0 213 | bytesCommand[0] = 96; //I2CByte0 : Memory Address (starting at address 96 (Serial Number) 214 | 215 | //Performing I2C low-level call 216 | err = I2C(hDevice, options, speedAdjust, sdaPinNum, sclPinNum, address, numBytesToSend, numBytesToReceive, bytesCommand, &errorcode, ackArray, bytesResponse); 217 | 218 | if( checkI2CErrorcode(errorcode) == -1 || err == -1 ) 219 | return -1; 220 | 221 | printf("LJTDAC Serial Number = %u\n\n", (bytesResponse[0] + bytesResponse[1]*256 + bytesResponse[2]*65536 + bytesResponse[3]*16777216)); 222 | 223 | 224 | /* User memory example. We will read the memory, update a few elements, 225 | * and write the memory. The user memory is just stored as bytes, so almost 226 | * any information can be put in there such as integers, doubles, or strings. */ 227 | 228 | /* Read the user memory : need to perform 2 I2C calls since command/response packets can only be 64 bytes in size */ 229 | 230 | //Setting up 1st I2C command 231 | address = (uint8)(0xA0); //Address : h0xA0 is the address for EEPROM 232 | numBytesToSend = 1; //NumI2CByteToSend : 1 byte for the EEPROM address 233 | numBytesToReceive = 52; //NumI2CBytesToReceive : getting 52 bytes starting at EEPROM address specified in I2CByte0 234 | bytesCommand[0] = 0; //I2CByte0 : Memory Address, starting at address 0 (User Area) 235 | 236 | //Performing I2C low-level call 237 | err = I2C(hDevice, options, speedAdjust, sdaPinNum, sclPinNum, address, numBytesToSend, numBytesToReceive, bytesCommand, &errorcode, ackArray, bytesResponse); 238 | 239 | if( checkI2CErrorcode(errorcode) == -1 || err == -1 ) 240 | return -1; 241 | 242 | //Setting up 2nd I2C command 243 | numBytesToReceive = 12; //NumI2CBytesToReceive : getting 12 bytes starting at EEPROM address specified in I2CByte0 244 | bytesCommand[0] = 52; //I2CByte0 : Memory Address, starting at address 52 (User Area) 245 | 246 | //Performing I2C low-level call 247 | err = I2C(hDevice, options, speedAdjust, sdaPinNum, sclPinNum, address, numBytesToSend, numBytesToReceive, bytesCommand, &errorcode, ackArray, bytesResponse + 52); 248 | 249 | if( checkI2CErrorcode(errorcode) == -1 || err == -1 ) 250 | return -1; 251 | 252 | //Display the first 4 elements. 253 | printf("Read User Mem [0-3] = %d, %d, %d, %d\n", bytesResponse[0], bytesResponse[1], bytesResponse[2], bytesResponse[3]); 254 | 255 | 256 | /* Create 4 new pseudo-random numbers to write. We will update the first 257 | * 4 elements of user memory, but the rest will be unchanged. */ 258 | 259 | //Setting up I2C command 260 | address = (uint8)(0xA0); //Address : h0xA0 is the address for EEPROM 261 | numBytesToSend = 5; //NumI2CByteToSend : 1 byte for the EEPROM address and the rest for the bytes to write 262 | numBytesToReceive = 0; //NumI2CBytesToReceive : 0 since we are only writing to memory 263 | bytesCommand[0] = 0; //I2CByte0 : Memory Address, starting at address 0 (User Area) 264 | srand((unsigned int)getTickCount()); 265 | for( i = 1; i < 5; i++ ) 266 | bytesCommand[i] = (uint8)(255*((float)rand()/RAND_MAX));; //I2CByte : byte in user memory 267 | 268 | printf("Write User Mem [0-3] = %d, %d, %d, %d\n", bytesCommand[1], bytesCommand[2], bytesCommand[3], bytesCommand[4]); 269 | 270 | //Performing I2C low-level call 271 | err = I2C(hDevice, options, speedAdjust, sdaPinNum, sclPinNum, address, numBytesToSend, numBytesToReceive, bytesCommand, &errorcode, ackArray, bytesResponse); 272 | 273 | if( checkI2CErrorcode(errorcode) == -1 || err == -1 ) 274 | return -1; 275 | 276 | //Delay for 2 ms to allow the EEPROM to finish writing. 277 | //Re-read the user memory. 278 | usleep(2000); 279 | 280 | //Setting up 1st I2C command 281 | address = (uint8)(0xA0); //Address : h0xA0 is the address for EEPROM 282 | numBytesToSend = 1; //NumI2CByteToSend : 1 byte for the EEPROM address 283 | numBytesToReceive = 52; //NumI2CBytesToReceive : getting 52 bytes starting at EEPROM address specified in I2CByte0 284 | bytesCommand[0] = 0; //I2CByte0 : Memory Address, starting at address 0 (User Area) 285 | 286 | //Performing I2C low-level call 287 | err = I2C(hDevice, options, speedAdjust, sdaPinNum, sclPinNum, address, numBytesToSend, numBytesToReceive, bytesCommand, &errorcode, ackArray, bytesResponse); 288 | 289 | if( checkI2CErrorcode(errorcode) == -1 || err == -1 ) 290 | return -1; 291 | 292 | //Setting up 2nd I2C command 293 | numBytesToReceive = 12; //NumI2CBytesToReceive : getting 12 bytes starting at EEPROM address specified in I2CByte0 294 | bytesCommand[0] = 52; //I2CByte0 : Memory Address, starting at address 52 (User Area) 295 | 296 | //Performing I2C low-level call 297 | err = I2C(hDevice, options, speedAdjust, sdaPinNum, sclPinNum, address, numBytesToSend, numBytesToReceive, bytesCommand, &errorcode, ackArray, bytesResponse + 52); 298 | 299 | if( checkI2CErrorcode(errorcode) == -1 || err == -1 ) 300 | return -1; 301 | 302 | //Display the first 4 elements. 303 | printf("Read User Mem [0-3] = %d, %d, %d, %d\n", bytesResponse[0], bytesResponse[1], bytesResponse[2], bytesResponse[3]); 304 | 305 | return err; 306 | } 307 | -------------------------------------------------------------------------------- /examples/U3/u3allio.c: -------------------------------------------------------------------------------- 1 | //Author : LabJack 2 | //December 27, 2011 3 | //This example demonstrates how to write and read some or all analog and digital 4 | //I/O. It records the time for 1000 iterations and divides by 1000, to allow 5 | //measurement of the basic command/response communication times. These times 6 | //should be comparable to the Windows command/response communication times 7 | //documented in Section 3.1 of the U3 User's Guide. 8 | 9 | #include 10 | #include "u3.h" 11 | 12 | 13 | const uint8 numChannels = 8; //Number of AIN channels, 0-16. 14 | const uint8 quickSample = 1; //Set to TRUE for quick AIN sampling. 15 | const uint8 longSettling = 0; //Set to TRUE for extra AIN settling time. 16 | 17 | int configAllIO(HANDLE hDevice, int *isDAC1Enabled); 18 | int allIO(HANDLE hDevice, u3CalibrationInfo *caliInfo, int isDAC1Enabled); 19 | 20 | int main(int argc, char **argv) 21 | { 22 | HANDLE hDevice; 23 | u3CalibrationInfo caliInfo; 24 | int dac1Enabled; 25 | 26 | //Opening first found U3 over USB 27 | if( (hDevice = openUSBConnection(-1)) == NULL ) 28 | goto done; 29 | 30 | //Getting calibration information from U3 31 | if( getCalibrationInfo(hDevice, &caliInfo) < 0 ) 32 | goto close; 33 | 34 | if( configAllIO(hDevice, &dac1Enabled) < 0 ) 35 | goto close;; 36 | 37 | allIO(hDevice, &caliInfo, dac1Enabled); 38 | 39 | close: 40 | closeUSBConnection(hDevice); 41 | done: 42 | return 0; 43 | } 44 | 45 | //Sends a ConfigIO low-level command that will set desired lines as analog, and 46 | //all else as digital. 47 | int configAllIO(HANDLE hDevice, int *isDAC1Enabled) 48 | { 49 | uint8 sendBuff[12], recBuff[12]; 50 | uint16 checksumTotal, FIOEIOAnalog; 51 | int sendChars, recChars; 52 | 53 | sendBuff[1] = (uint8)(0xF8); //Command byte 54 | sendBuff[2] = (uint8)(0x03); //Number of data words 55 | sendBuff[3] = (uint8)(0x0B); //Extended command number 56 | 57 | sendBuff[6] = 13; //Writemask : Setting writemask for TimerCounterConfig (bit 0), 58 | // FIOAnalog (bit 2) and EIOAnalog (bit 3) 59 | 60 | sendBuff[7] = 0; //Reserved 61 | sendBuff[8] = 64; //TimerCounterConfig: disable timer and counter, set 62 | // TimerCounterPinOffset to 4 (bits 4-7) 63 | sendBuff[9] = 0; //DAC1 enable : not enabling, though could already be enabled 64 | 65 | sendBuff[10] = 0; 66 | 67 | FIOEIOAnalog = pow(2.0, numChannels)-1; 68 | sendBuff[10] = (FIOEIOAnalog & 0xFF); //FIOAnalog 69 | sendBuff[11] = FIOEIOAnalog / 256; //EIOAnalog 70 | extendedChecksum(sendBuff, 12); 71 | 72 | //Sending command to U3 73 | if( (sendChars = LJUSB_Write(hDevice, sendBuff, 12)) < 12 ) 74 | { 75 | if( sendChars == 0 ) 76 | printf("ConfigIO error : write failed\n"); 77 | else 78 | printf("ConfigIO error : did not write all of the buffer\n"); 79 | return -1; 80 | } 81 | 82 | //Reading response from U3 83 | if( (recChars = LJUSB_Read(hDevice, recBuff, 12)) < 12 ) 84 | { 85 | if( recChars == 0 ) 86 | printf("ConfigIO error : read failed\n"); 87 | else 88 | printf("ConfigIO error : did not read all of the buffer\n"); 89 | return -1; 90 | } 91 | 92 | checksumTotal = extendedChecksum16(recBuff, 12); 93 | if( (uint8)((checksumTotal / 256) & 0xFF) != recBuff[5] ) 94 | { 95 | printf("ConfigIO error : read buffer has bad checksum16(MSB)\n"); 96 | return -1; 97 | } 98 | 99 | if( (uint8)(checksumTotal & 0xFF) != recBuff[4] ) 100 | { 101 | printf("ConfigIO error : read buffer has bad checksum16(LBS)\n"); 102 | return -1; 103 | } 104 | 105 | if( extendedChecksum8(recBuff) != recBuff[0] ) 106 | { 107 | printf("ConfigIO error : read buffer has bad checksum8\n"); 108 | return -1; 109 | } 110 | 111 | if( recBuff[1] != (uint8)(0xF8) || recBuff[2] != (uint8)(0x03) || recBuff[3] != (uint8)(0x0B) ) 112 | { 113 | printf("ConfigIO error : read buffer has wrong command bytes\n"); 114 | return -1; 115 | } 116 | 117 | if( recBuff[6] != 0 ) 118 | { 119 | printf("ConfigIO error : read buffer received errorcode %d\n", recBuff[6]); 120 | return -1; 121 | } 122 | 123 | if( recBuff[10] != (FIOEIOAnalog&(0xFF)) && recBuff[10] != ((FIOEIOAnalog&(0xFF))|(0x0F)) ) 124 | { 125 | printf("ConfigIO error : FIOAnalog did not set correctly"); 126 | return -1; 127 | } 128 | 129 | if( recBuff[11] != FIOEIOAnalog/256 ) 130 | { 131 | printf("ConfigIO error : EIOAnalog did not set correctly"); 132 | return -1; 133 | } 134 | 135 | *isDAC1Enabled = (int)recBuff[9]; 136 | 137 | return 0; 138 | } 139 | 140 | //Calls a Feedback low-level command 1000 times. 141 | int allIO(HANDLE hDevice, u3CalibrationInfo *caliInfo, int isDAC1Enabled) 142 | { 143 | uint8 *sendBuff, *recBuff; 144 | uint16 checksumTotal, ainBytes; 145 | int sendChars, recChars, sendSize, recSize; 146 | int valueDIPort, ret, i, j; 147 | double valueAIN[16]; 148 | long time, numIterations; 149 | double hardwareVersion; 150 | 151 | ret = 0; 152 | hardwareVersion = caliInfo->hardwareVersion; 153 | 154 | for( i = 0; i < 16; i++ ) 155 | valueAIN[i] = 9999; 156 | valueDIPort = 0; 157 | numIterations = 1000; //Number of iterations (how many times Feedback will 158 | //be called) 159 | 160 | //Setting up a Feedback command that will set CIO0-3 as input 161 | sendBuff = (uint8 *)malloc(14*sizeof(uint8)); //Creating an array of size 14 162 | recBuff = (uint8 *)malloc(10*sizeof(uint8)); //Creating an array of size 10 163 | 164 | sendBuff[1] = (uint8)(0xF8); //Command byte 165 | sendBuff[2] = 4; //Number of data words (.5 word for echo, 3.5 words for 166 | // IOTypes and data) 167 | sendBuff[3] = (uint8)(0x00); //Extended command number 168 | 169 | sendBuff[6] = 0; //Echo 170 | sendBuff[7] = 29; //IOType is PortDirWrite 171 | sendBuff[8] = 0; //Writemask (for FIO) 172 | sendBuff[9] = 0; //Writemask (for EIO) 173 | sendBuff[10] = 15; //Writemask (for CIO) 174 | sendBuff[11] = 0; //Direction (for FIO) 175 | sendBuff[12] = 0; //Direction (for EIO) 176 | sendBuff[13] = 0; //Direction (for CIO) 177 | 178 | extendedChecksum(sendBuff, 14); 179 | 180 | //Sending command to U3 181 | if( (sendChars = LJUSB_Write(hDevice, sendBuff, 14)) < 14 ) 182 | { 183 | if( sendChars == 0 ) 184 | printf("Feedback (CIO input) error : write failed\n"); 185 | else 186 | printf("Feedback (CIO input) error : did not write all of the buffer\n"); 187 | ret = -1; 188 | goto cleanmem; 189 | } 190 | 191 | //Reading response from U3 192 | if( (recChars = LJUSB_Read(hDevice, recBuff, 10)) < 10 ) 193 | { 194 | if( recChars == 0 ) 195 | { 196 | printf("Feedback (CIO input) error : read failed\n"); 197 | ret = -1; 198 | goto cleanmem; 199 | } 200 | else 201 | printf("Feedback (CIO input) error : did not read all of the buffer\n"); 202 | } 203 | 204 | checksumTotal = extendedChecksum16(recBuff, 10); 205 | if( (uint8)((checksumTotal / 256) & 0xFF) != recBuff[5] ) 206 | { 207 | printf("Feedback (CIO input) error : read buffer has bad checksum16(MSB)\n"); 208 | ret = -1; 209 | goto cleanmem; 210 | } 211 | 212 | if( (uint8)(checksumTotal & 0xFF) != recBuff[4] ) 213 | { 214 | printf("Feedback (CIO input) error : read buffer has bad checksum16(LBS)\n"); 215 | ret = -1; 216 | goto cleanmem; 217 | } 218 | 219 | if( extendedChecksum8(recBuff) != recBuff[0] ) 220 | { 221 | printf("Feedback (CIO input) error : read buffer has bad checksum8\n"); 222 | ret = -1; 223 | goto cleanmem; 224 | } 225 | 226 | if( recBuff[1] != (uint8)(0xF8) || recBuff[3] != (uint8)(0x00) ) 227 | { 228 | printf("Feedback (CIO input) error : read buffer has wrong command bytes \n"); 229 | ret = -1; 230 | goto cleanmem; 231 | } 232 | 233 | if( recBuff[6] != 0 ) 234 | { 235 | printf("Feedback (CIO input) error : received errorcode %d for frame %d in Feedback response. \n", recBuff[6], recBuff[7]); 236 | ret = -1; 237 | goto cleanmem; 238 | } 239 | 240 | free(sendBuff); 241 | free(recBuff); 242 | 243 | //Setting up Feedback command that will run 1000 times 244 | if( ((sendSize = 7+2+1+numChannels*3) % 2) != 0 ) 245 | sendSize++; 246 | //Creating an array of size sendSize 247 | sendBuff = (uint8 *)malloc(sendSize*sizeof(uint8)); 248 | 249 | if( ((recSize = 9+3+numChannels*2) % 2) != 0 ) 250 | recSize++; 251 | //Creating an array of size recSize 252 | recBuff = (uint8 *)malloc(recSize*sizeof(uint8)); 253 | 254 | sendBuff[1] = (uint8)(0xF8); //Command byte 255 | sendBuff[2] = (sendSize - 6)/2; //Number of data words 256 | sendBuff[3] = (uint8)(0x00); //Extended command number 257 | 258 | sendBuff[6] = 0; //Echo 259 | 260 | //Setting DAC0 with 2.5 volt output 261 | sendBuff[7] = 34; //IOType is DAC0 262 | 263 | //Value is 2.5 volts (in binary) 264 | getDacBinVoltCalibrated(caliInfo, 0, 2.5, &sendBuff[8]); 265 | 266 | sendBuff[9] = 26; //IOType is PortStateRead 267 | 268 | //Setting AIN read commands 269 | for( j = 0; j < numChannels; j++ ) 270 | { 271 | sendBuff[10 + j*3] = 1; //IOType is AIN 272 | 273 | //Positive Channel (bits 0 - 4), LongSettling (bit 6) and QuickSample (bit 7) 274 | sendBuff[11 + j*3] = j + (longSettling&(0x01))*64 + (quickSample&(0x01))*128; 275 | sendBuff[12 + j*3] = 31; //Negative Channel is single-ended 276 | } 277 | 278 | if( (sendSize % 2) != 0 ) 279 | sendBuff[sendSize - 1] = 0; 280 | 281 | extendedChecksum(sendBuff, sendSize); 282 | 283 | time = getTickCount(); 284 | 285 | for( i = 0; i < numIterations; i++ ) 286 | { 287 | //Sending command to U3 288 | if( (sendChars = LJUSB_Write(hDevice, sendBuff, sendSize)) < sendSize ) 289 | { 290 | if( sendChars == 0 ) 291 | printf("Feedback error (Iteration %d): write failed\n", i); 292 | else 293 | printf("Feedback error (Iteration %d): did not write all of the buffer\n", i); 294 | ret = -1; 295 | goto cleanmem; 296 | } 297 | 298 | //Reading response from U3 299 | if( (recChars = LJUSB_Read(hDevice, recBuff, recSize)) < recSize ) 300 | { 301 | if( recChars == 0 ) 302 | { 303 | printf("Feedback error (Iteration %d): read failed\n", i); 304 | ret = -1; 305 | goto cleanmem; 306 | } 307 | else 308 | printf("Feedback error (Iteration %d): did not read all of the expected buffer\n", i); 309 | } 310 | 311 | checksumTotal = extendedChecksum16(recBuff, recChars); 312 | if( (uint8)((checksumTotal / 256) & 0xFF) != recBuff[5] ) 313 | { 314 | printf("Feedback error (Iteration %d): read buffer has bad checksum16(MSB)\n", i); 315 | ret = -1; 316 | goto cleanmem; 317 | } 318 | 319 | if( (uint8)(checksumTotal & 0xFF) != recBuff[4] ) 320 | { 321 | printf("Feedback error (Iteration %d): read buffer has bad checksum16(LBS)\n", i); 322 | ret = -1; 323 | goto cleanmem; 324 | } 325 | 326 | if( extendedChecksum8(recBuff) != recBuff[0] ) 327 | { 328 | printf("Feedback error (Iteration %d): read buffer has bad checksum8\n", i); 329 | ret = -1; 330 | goto cleanmem; 331 | } 332 | 333 | if( recBuff[1] != (uint8)(0xF8) || recBuff[3] != (uint8)(0x00) ) 334 | { 335 | printf("Feedback error (Iteration %d): read buffer has wrong command bytes \n", i); 336 | ret = -1; 337 | goto cleanmem; 338 | } 339 | 340 | if( recBuff[6] != 0 ) 341 | { 342 | printf("Feedback error (Iteration %d): received errorcode %d for frame %d in Feedback response. \n", i, recBuff[6], recBuff[7]); 343 | ret = -1; 344 | goto cleanmem; 345 | } 346 | 347 | if( recChars != recSize ) 348 | { 349 | ret = -1; 350 | goto cleanmem; 351 | } 352 | 353 | //Getting CIO digital states 354 | valueDIPort = recBuff[11]; 355 | 356 | //Getting AIN voltages 357 | for( j = 0; j < numChannels; j++ ) 358 | { 359 | ainBytes = recBuff[12+j*2] + recBuff[13+j*2]*256; 360 | if( hardwareVersion >= 1.30 ) 361 | getAinVoltCalibrated_hw130(caliInfo, j, 31, ainBytes, &valueAIN[j]); 362 | else 363 | getAinVoltCalibrated(caliInfo, isDAC1Enabled, 31, ainBytes, &valueAIN[j]); 364 | } 365 | } 366 | 367 | time = getTickCount() - time; 368 | printf("Milliseconds per iteration = %.3f\n", (double)time / (double)numIterations); 369 | printf("\nDigital Input = %d\n", valueDIPort); 370 | printf("\nAIN readings from last iteration:\n"); 371 | 372 | for( j = 0; j < numChannels; j++ ) 373 | printf("%.3f\n", valueAIN[j]); 374 | 375 | cleanmem: 376 | free(sendBuff); 377 | free(recBuff); 378 | sendBuff = NULL; 379 | recBuff = NULL; 380 | 381 | return ret; 382 | } 383 | -------------------------------------------------------------------------------- /examples/U3/u3LJTDAC.c: -------------------------------------------------------------------------------- 1 | //Author: LabJack 2 | //December 27, 2011 3 | //Communicates with an LJTick-DAC using low level functions. The LJTDAC should 4 | //be plugged into FIO4/FIO5 for this example. 5 | //Tested with U3 firmware V1.44, and requires hardware version 1.21 or greater. 6 | 7 | #include "u3.h" 8 | #include 9 | 10 | int configIO_example(HANDLE hDevice); 11 | int checkI2CErrorcode(uint8 errorcode); 12 | int LJTDAC_example(HANDLE hDevice, u3TdacCalibrationInfo *caliInfo); 13 | 14 | int main(int argc, char **argv) 15 | { 16 | HANDLE hDevice; 17 | u3TdacCalibrationInfo caliInfo; 18 | 19 | //Opening first found U3 over USB 20 | if( (hDevice = openUSBConnection(-1)) == NULL ) 21 | goto done; 22 | 23 | if( configIO_example(hDevice) != 0 ) 24 | goto close; 25 | 26 | //Getting calibration information from LJTDAC 27 | if( getTdacCalibrationInfo(hDevice, &caliInfo, 4) < 0 ) 28 | goto close; 29 | 30 | LJTDAC_example(hDevice, &caliInfo); 31 | 32 | close: 33 | closeUSBConnection(hDevice); 34 | done: 35 | return 0; 36 | } 37 | 38 | 39 | //Sends a ConfigIO low-level command that configures the FIO4 and FIO5 lines to 40 | //digital. 41 | int configIO_example(HANDLE hDevice) 42 | { 43 | uint8 sendBuff[12], recBuff[12]; 44 | uint16 checksumTotal; 45 | int sendChars, recChars; 46 | 47 | sendBuff[1] = (uint8)(0xF8); //Command byte 48 | sendBuff[2] = (uint8)(0x03); //Number of data words 49 | sendBuff[3] = (uint8)(0x0B); //Extended command number 50 | 51 | sendBuff[6] = 7; //Writemask : Setting writemask for TimerCounterConfig (bit 0), 52 | // DAC1Enable (bit 1) and FIOAnalog (bit 2) 53 | 54 | sendBuff[7] = 0; //Reserved 55 | sendBuff[8] = 64; //TimerCounterConfig : disable timers and counters. set 56 | // TimerCounterPinOffset to 4 (bits 4-7) 57 | sendBuff[9] = 0; //DAC1 enable : disabling 58 | sendBuff[10] = 0; //FIOAnalog : setting FIO channels to digital 59 | sendBuff[11] = 0; //EIOAnalog : Not setting anything 60 | extendedChecksum(sendBuff, 12); 61 | 62 | //Sending command to U3 63 | if( (sendChars = LJUSB_Write(hDevice, sendBuff, 12)) < 12 ) 64 | { 65 | if( sendChars == 0 ) 66 | printf("ConfigIO error : write failed\n"); 67 | else 68 | printf("ConfigIO error : did not write all of the buffer\n"); 69 | return -1; 70 | } 71 | 72 | //Reading response from U3 73 | if( (recChars = LJUSB_Read(hDevice, recBuff, 12)) < 12 ) 74 | { 75 | if( recChars == 0 ) 76 | printf("ConfigIO error : read failed\n"); 77 | else 78 | printf("ConfigIO error : did not read all of the buffer\n"); 79 | return -1; 80 | } 81 | 82 | checksumTotal = extendedChecksum16(recBuff, 12); 83 | if( (uint8)((checksumTotal / 256 ) & 0xFF) != recBuff[5] ) 84 | { 85 | printf("ConfigIO error : read buffer has bad checksum16(MSB)\n"); 86 | return -1; 87 | } 88 | 89 | if( (uint8)(checksumTotal & 0xFF) != recBuff[4] ) 90 | { 91 | printf("ConfigIO error : read buffer has bad checksum16(LBS)\n"); 92 | return -1; 93 | } 94 | 95 | if( extendedChecksum8(recBuff) != recBuff[0] ) 96 | { 97 | printf("ConfigIO error : read buffer has bad checksum8\n"); 98 | return -1; 99 | } 100 | 101 | if( recBuff[1] != (uint8)(0xF8) || recBuff[2] != (uint8)(0x03) || recBuff[3] != (uint8)(0x0B) ) 102 | { 103 | printf("ConfigIO error : read buffer has wrong command bytes\n"); 104 | return -1; 105 | } 106 | 107 | if( recBuff[6] != 0 ) 108 | { 109 | printf("ConfigIO error : read buffer received errorcode %d\n", recBuff[6]); 110 | return -1; 111 | } 112 | 113 | if( recBuff[8] != 64 ) 114 | { 115 | printf("ConfigIO error : TimerCounterConfig did not get set correctly\n"); 116 | return -1; 117 | } 118 | 119 | if( recBuff[10] != 0 && recBuff[10] != (uint8)(0x0F) ) 120 | { 121 | printf("ConfigIO error : FIOAnalog did not set correctly\n"); 122 | return -1; 123 | } 124 | 125 | return 0; 126 | } 127 | 128 | 129 | int checkI2CErrorcode(uint8 errorcode) 130 | { 131 | if(errorcode != 0) 132 | { 133 | printf("I2C error : received errorcode %d in response\n", errorcode); 134 | return -1; 135 | } 136 | return 0; 137 | } 138 | 139 | 140 | int LJTDAC_example(HANDLE hDevice, u3TdacCalibrationInfo *caliInfo) 141 | { 142 | uint8 options, speedAdjust, sdaPinNum, sclPinNum; 143 | uint8 address, numBytesToSend, numBytesToReceive, errorcode; 144 | uint8 bytesCommand[5], bytesResponse[64], ackArray[4]; 145 | uint16 binaryVoltage; 146 | int err, i; 147 | 148 | err = 0; 149 | 150 | //Setting up parts I2C command that will remain the same throughout this 151 | //example 152 | options = 0; //I2COptions : 0 153 | speedAdjust = 0; //SpeedAdjust : 0 (for max communication speed of about 154 | //130 kHz) 155 | sdaPinNum = 5; //SDAPinNum : FIO5 connected to pin DIOB 156 | sclPinNum = 4; //SCLPinNum : FIO4 connected to pin DIOA 157 | 158 | 159 | /* Set DACA to 1.2 volts. */ 160 | 161 | //Setting up I2C command 162 | //Make note that the I2C command can only update 1 DAC channel at a time. 163 | address = (uint8)(0x24); //Address : h0x24 is the address for DAC 164 | numBytesToSend = 3; //NumI2CByteToSend : 3 bytes to specify DACA and the 165 | //value 166 | numBytesToReceive = 0; //NumI2CBytesToReceive : 0 since we are only setting 167 | //the value of the DAC 168 | bytesCommand[0] = (uint8)(0x30); //LJTDAC command byte : h0x30 (DACA) 169 | getTdacBinVoltCalibrated(caliInfo, 0, 1.2, &binaryVoltage); 170 | bytesCommand[1] = (uint8)(binaryVoltage/256); //value (high) 171 | bytesCommand[2] = (uint8)(binaryVoltage & (0x00FF)); //value (low) 172 | 173 | //Performing I2C low-level call 174 | err = I2C(hDevice, options, speedAdjust, sdaPinNum, sclPinNum, address, numBytesToSend, numBytesToReceive, bytesCommand, &errorcode, ackArray, bytesResponse); 175 | 176 | if( checkI2CErrorcode(errorcode) == -1 || err == -1 ) 177 | return -1; 178 | 179 | printf("DACA set to 1.2 volts\n\n"); 180 | 181 | 182 | /* Set DACB to 2.3 volts. */ 183 | 184 | //Setting up I2C command 185 | address = (uint8)(0x24); //Address : h0x24 is the address for DAC 186 | numBytesToSend = 3; //NumI2CByteToSend : 3 bytes to specify DACB and the 187 | //value 188 | numBytesToReceive = 0; //NumI2CBytesToReceive : 0 since we are only setting 189 | //the value of the DAC 190 | bytesCommand[0] = (uint8)(0x31); //LJTDAC command byte : h0x31 (DACB) 191 | getTdacBinVoltCalibrated(caliInfo, 1, 2.3, &binaryVoltage); 192 | bytesCommand[1] = (uint8)(binaryVoltage/256); //value (high) 193 | bytesCommand[2] = (uint8)(binaryVoltage & (0x00FF)); //value (low) 194 | 195 | //Performing I2C low-level call 196 | err = I2C(hDevice, options, speedAdjust, sdaPinNum, sclPinNum, address, numBytesToSend, numBytesToReceive, bytesCommand, &errorcode, ackArray, bytesResponse); 197 | 198 | if( checkI2CErrorcode(errorcode) == -1 || err == -1 ) 199 | return -1; 200 | 201 | printf("DACB set to 2.3 volts\n\n"); 202 | 203 | 204 | /* More advanced operations. */ 205 | 206 | /* Display LJTDAC calibration constants. Code for getting the calibration 207 | * constants is in the getLJTDACCalibrationInfo function in the u3.c file. 208 | */ 209 | printf("DACA Slope = %.1f bits/volt\n", caliInfo->ccConstants[0]); 210 | printf("DACA Offset = %.1f bits\n", caliInfo->ccConstants[1]); 211 | printf("DACB Slope = %.1f bits/volt\n", caliInfo->ccConstants[2]); 212 | printf("DACB Offset = %.1f bits\n\n", caliInfo->ccConstants[3]); 213 | 214 | 215 | /* Read the serial number. */ 216 | 217 | //Setting up I2C command 218 | address = (uint8)(0xA0); //Address : h0xA0 is the address for EEPROM 219 | numBytesToSend = 1; //NumI2CByteToSend : 1 byte for the EEPROM address 220 | numBytesToReceive = 4; //NumI2CBytesToReceive : getting 4 bytes starting at 221 | //EEPROM address specified in I2CByte0 222 | bytesCommand[0] = 96; //I2CByte0 : Memory Address, starting at address 96 223 | //(Serial Number) 224 | 225 | //Performing I2C low-level call 226 | err = I2C(hDevice, options, speedAdjust, sdaPinNum, sclPinNum, address, numBytesToSend, numBytesToReceive, bytesCommand, &errorcode, ackArray, bytesResponse); 227 | 228 | if( checkI2CErrorcode(errorcode) == -1 || err == -1 ) 229 | return -1; 230 | 231 | printf("LJTDAC Serial Number = %u\n\n", (bytesResponse[0] + bytesResponse[1]*256 + bytesResponse[2]*65536 + bytesResponse[3]*16777216)); 232 | 233 | 234 | /* User memory example. We will read the memory, update a few elements, and 235 | * write the memory. The user memory is just stored as bytes, so almost any 236 | * information can be put in there such as integers, doubles, or strings. 237 | */ 238 | 239 | /* Read the user memory : need to perform 2 I2C calls since command/response 240 | packets can only be 64 bytes in size */ 241 | 242 | //Setting up 1st I2C command 243 | address = (uint8)(0xA0); //Address : h0xA0 is the address for EEPROM 244 | numBytesToSend = 1; //NumI2CByteToSend : 1 byte for the EEPROM address 245 | numBytesToReceive = 52; //NumI2CBytesToReceive : getting 52 bytes starting 246 | //at EEPROM address specified in I2CByte0 247 | bytesCommand[0] = 0; //I2CByte0 : Memory Address, starting at address 0 248 | //(User Area) 249 | 250 | //Performing I2C low-level call 251 | err = I2C(hDevice, options, speedAdjust, sdaPinNum, sclPinNum, address, numBytesToSend, numBytesToReceive, bytesCommand, &errorcode, ackArray, bytesResponse); 252 | 253 | if( checkI2CErrorcode(errorcode) == -1 || err == -1 ) 254 | return -1; 255 | 256 | //Setting up 2nd I2C command 257 | numBytesToReceive = 12; //NumI2CBytesToReceive : getting 12 bytes starting 258 | //at EEPROM address specified in I2CByte0 259 | bytesCommand[0] = 52; //I2CByte0 : Memory Address, starting at address 52 260 | //(User Area) 261 | 262 | //Performing I2C low-level call 263 | err = I2C(hDevice, options, speedAdjust, sdaPinNum, sclPinNum, address, numBytesToSend, numBytesToReceive, bytesCommand, &errorcode, ackArray, bytesResponse + 52); 264 | 265 | if( checkI2CErrorcode(errorcode) == -1 || err == -1 ) 266 | return -1; 267 | 268 | //Display the first 4 elements. 269 | printf("Read User Mem [0-3] = %d, %d, %d, %d\n", bytesResponse[0], bytesResponse[1], bytesResponse[2], bytesResponse[3]); 270 | 271 | 272 | /* Create 4 new pseudo-random numbers to write. We will update the first 273 | * 4 elements of user memory, but the rest will be unchanged. */ 274 | 275 | //Setting up I2C command 276 | address = (uint8)(0xA0); //Address : h0xA0 is the address for EEPROM 277 | numBytesToSend = 5; //NumI2CByteToSend : 1 byte for the EEPROM address and 278 | //the rest for the bytes to write 279 | numBytesToReceive = 0; //NumI2CBytesToReceive : 0 since we are only writing to memory 280 | bytesCommand[0] = 0; //I2CByte0 : Memory Address, starting at address 0 281 | //(User Area) 282 | srand((unsigned int)getTickCount()); 283 | for(i = 1; i < 5; i++) 284 | { 285 | //I2CByte : byte in user memory 286 | bytesCommand[i] = (uint8)(255 * ((float)rand()/RAND_MAX)); 287 | } 288 | 289 | printf("Write User Mem [0-3] = %d, %d, %d, %d\n", bytesCommand[1], bytesCommand[2], bytesCommand[3], bytesCommand[4]); 290 | 291 | //Performing I2C low-level call 292 | err = I2C(hDevice, options, speedAdjust, sdaPinNum, sclPinNum, address, numBytesToSend, numBytesToReceive, bytesCommand, &errorcode, ackArray, bytesResponse); 293 | 294 | if( checkI2CErrorcode(errorcode) == -1 || err == -1 ) 295 | return -1; 296 | 297 | //Delay for 2 ms to allow the EEPROM to finish writing. 298 | //Re-read the user memory. 299 | usleep(2000); 300 | 301 | //Setting up 1st I2C command 302 | address = (uint8)(0xA0); //Address : h0xA0 is the address for EEPROM 303 | numBytesToSend = 1; //NumI2CByteToSend : 1 byte for the EEPROM address 304 | numBytesToReceive = 52; //NumI2CBytesToReceive : getting 52 bytes starting 305 | //at EEPROM address specified in I2CByte0 306 | bytesCommand[0] = 0; //I2CByte0 : Memory Address, starting at address 0 307 | //(User Area) 308 | 309 | //Performing I2C low-level call 310 | err = I2C(hDevice, options, speedAdjust, sdaPinNum, sclPinNum, address, numBytesToSend, numBytesToReceive, bytesCommand, &errorcode, ackArray, bytesResponse); 311 | 312 | if( checkI2CErrorcode(errorcode) == -1 || err == -1 ) 313 | return -1; 314 | 315 | //Setting up 2nd I2C command 316 | numBytesToReceive = 12; //NumI2CBytesToReceive : getting 12 bytes starting 317 | //at EEPROM address specified in I2CByte0 318 | bytesCommand[0] = 52; //I2CByte0 : Memory Address, starting at address 52 319 | //(User Area) 320 | 321 | //Performing I2C low-level call 322 | err = I2C(hDevice, options, speedAdjust, sdaPinNum, sclPinNum, address, numBytesToSend, numBytesToReceive, bytesCommand, &errorcode, ackArray, bytesResponse + 52); 323 | 324 | if( checkI2CErrorcode(errorcode) == -1 || err == -1 ) 325 | return -1; 326 | 327 | //Display the first 4 elements. 328 | printf("Read User Mem [0-3] = %d, %d, %d, %d\n", bytesResponse[0], bytesResponse[1], bytesResponse[2], bytesResponse[3]); 329 | 330 | return err; 331 | } 332 | --------------------------------------------------------------------------------