Index
RSS

Welcome Guest [ Log In | Register ]

2 Pages V   1 2 >  
Reply to this topicStart new topic
> Using Labjack in Matlab under OS X
Iandol
post Aug 27 2010, 08:28 AM
Post #1

Joined: 16-July 10
Posts: 46




Hi, just received our testing U3, and I can succesfully use loadlib in matlab to load the exodriver:
CODE
header='/usr/local/include/labjackusb.h';
loadlibrary('/usr/local/lib/liblabjackusb',header);
libfunctionsview liblabjackusb


I see 13 functions labelled, but realise I couldn't find any documentation apart from the header file. Is there any other documentation I missed which may help me (not being a C programmer). What I wanted to do in my first foray was the fastest possible switching of a digital I/O between low and high from Matlab (I have my U3 connected to a high speed USB hub). Does the exodriver provide the same functionality as the labjackUD (it has many more fucntions listed by matlab)?

Thanks, installing the drivers has been a beautiful experience compared to my piece-of-junk NI-6009!!!
 
Quote Post
LabJack Support
post Aug 27 2010, 09:25 AM
Post #2

Joined: 9-June 03
Posts: 7527




QUOTE (Iandol @ Aug 27 2010, 09:28 AM) *
Hi, just received our testing U3, and I can succesfully use loadlib in matlab to load the exodriver:


Great job. In our limited Matlab experience, you finished the hardest part.

QUOTE (Iandol @ Aug 27 2010, 09:28 AM) *
Does the exodriver provide the same functionality as the labjackUD (it has many more fucntions listed by matlab)?


No. The Exodriver is a thin layer around the hardware (think exoskeleton). It provides 4 primary functions: Open, Write, Read, and Close. A minimal program works something like this:

1. Open the U3 (LJUSB_OpenDevice)
2. Write a command to the U3 (LJUSB_Write)
3. Read the response (LJUSB_Read)
4. Repeat 2 and 3
5. Close when done (LJUSB_CloseDevice)

You use Section 5 of the U3 User's Guide to build the commands the U3 expects. There are lots of examples of how to do this C in and Python. The Exodriver examples has the C code. There's a u3.h that implements the UD driver "e-" functions. This is the difference between the Exodriver and the UD driver. The UD driver has those functions built-in, the Exodriver has implementations in user application code. If you know how you may be able to call eDO from u3.h if you build u3.c as a library and load it into Matlab. We've never done this, so we don't know if it would work. In your case, it sounds easier to us to just send the bytes your self rather than rely on the C code.

To know what bytes to write to the U3, we recommend grabbing a copy of LabJackPython. It is a great way to see the bytes coming and going to the U3. To set FIO4 to be output high and then output low:
CODE
>>> import u3
>>> d = u3.U3()
>>> d.debug = True
>>> d.getFeedback( u3.BitDirWrite(4, 1), u3.BitStateWrite(4, 1) )
Sent:  [0x1d, 0xf8, 0x3, 0x0, 0x20, 0x1, 0x0, 0xd, 0x84, 0xb, 0x84, 0x0]
Response:  [0xfa, 0xf8, 0x2, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0]
[None, None]
>>> d.getFeedback( u3.BitDirWrite(4, 1), u3.BitStateWrite(4, 0) )
Sent:  [0x9c, 0xf8, 0x3, 0x0, 0xa0, 0x0, 0x0, 0xd, 0x84, 0xb, 0x4, 0x0]
Response:  [0xfa, 0xf8, 0x2, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0]
[None, None]


In the code above, we're sending a feedback command which is documented in Section 5.2.5 of the U3 User's Guide. In the feedback command, we're sending BitDirWrite to set FIO4 to output, and BitStateWrite to set FIO4's state to high.

So to set FIO4 to output high from Matlab, all you would have to do is have a function that calls LJUSB_Write() with these bytes:

CODE
Sent:  [0x1d, 0xf8, 0x3, 0x0, 0x20, 0x1, 0x0, 0xd, 0x84, 0xb, 0x84, 0x0]


And then call LJUSB_Read() to read 10 bytes, which you can ignore since they don't tell you much.

It's a low-level interface, but it's very efficient, and it's explicit about what it's doing. Your application seems simple enough that you could hide the low level bytes to send in one or two functions.

Let us know how it goes. We'd like to know about more Mac OS X customers using their LabJacks with Matlab.

 
Quote Post
Iandol
post Aug 27 2010, 01:32 PM
Post #3

Joined: 16-July 10
Posts: 46




QUOTE (LabJack Support @ Aug 27 2010, 05:25 PM) *
CODE
Sent:  [0x1d, 0xf8, 0x3, 0x0, 0x20, 0x1, 0x0, 0xd, 0x84, 0xb, 0x84, 0x0]


And then call LJUSB_Read() to read 10 bytes, which you can ignore since they don't tell you much.

It's a low-level interface, but it's very efficient, and it's explicit about what it's doing. Your application seems simple enough that you could hide the low level bytes to send in one or two functions.

Let us know how it goes. We'd like to know about more Mac OS X customers using their LabJacks with Matlab.


This is wonderful stuff, I love the Python interface, so elegant to have such a robust cross-platform tool. Sadly I left the U3 at work so won't be able to play till next week, however your post is incredibly helpful. Once I get the interface set up and working (maybe delayed a bit by other lab projects!), I'll post the Matlab wrapper class to github, and will contribute it to the Psychophysics toolbox (which will have to be cross-platform with windows). As this is a perennial problem for researchers using Macs, macresearch.org may also be an interesting place to post it.
 
Quote Post
Iandol
post Aug 31 2010, 09:09 AM
Post #4

Joined: 16-July 10
Posts: 46




I'm getting an immediate Matlab crash with LJUSB_Write when I try the following:
CODE
function setFIO4(obj,val)
    high = hex2dec(['1d'; 'f8'; '03'; '00'; '20'; '01'; '00'; '0d'; '84'; '0b'; '84'; '00'])';
    low = hex2dec(['9c'; 'f8'; '03'; '00'; 'a0'; '00'; '00'; '0d'; '84'; '0b'; '04'; '00'])';
    highPtr=libpointer('uint8Ptr',high);
    lowPtr=libpointer('uint8Ptr',low);
    if ~exist('val','var')
        val = 0;
    end
    if val == 1
        out = calllib('liblabjackusb', 'LJUSB_Write', obj.handle, highPtr, 12)
        in =  calllib('liblabjackusb', 'LJUSB_Read', obj.handle, inp, 10)
    else
        out = calllib('liblabjackusb', 'LJUSB_Write', obj.handle, lowPtr, 12)
        in =  calllib('liblabjackusb', 'LJUSB_Read', obj.handle, inp, 10)
    end    
end


According to libfunctions I must pass in a uint8Ptr.
CODE
[ulong, voidPtr, uint8Ptr] LJUSB_Write(voidPtr, uint8Ptr, ulong)


I assume I've passed values wrongly somewhere but can't figure out where!


 
Quote Post
LabJack Support
post Aug 31 2010, 11:17 AM
Post #5

Joined: 9-June 03
Posts: 7527




This section of the User's Guide on Passing a Pointer to the First Element of an Array suggests that the call to libpointer is optional. That is, you could try:

CODE
out = calllib('liblabjackusb', 'LJUSB_Write', obj.handle, high, 12)


I would double-check the obj.handle (voidPtr), too. This is returned from LJUSB_OpenDevice, right? Do you have a way to check if it's not null?
 
Quote Post
Iandol
post Sep 2 2010, 02:52 PM
Post #6

Joined: 16-July 10
Posts: 46




Right, I've removed and rebuilt both libusb and liblabjackusb, and rebooted. I can now use my class to toggle FIO4 from the matlab prompt (yay!), and sometimes when Matlab runs a script, but I'm still getting frequent crashes when running from a script. So my Write call is fine (you're right I didn't need to type cast to pointers, matlab does it for me). I'll give this a go on an old linux machine with matlab installed and see if I have instability there.

For what its worth (probably not much), libusb is the first item in the matlab crash stack; I can send you a crash log though doubt you'd be able to use it.
 
Quote Post
LabJack Support
post Sep 2 2010, 03:45 PM
Post #7

Joined: 9-June 03
Posts: 7527




QUOTE (Iandol @ Sep 2 2010, 03:52 PM) *
I'll give this a go on an old linux machine with matlab installed and see if I have instability there.


There's cause for optimism. The libusb-1.0 Linux-specific code is more mature and in our experience more robust than on Mac OS X. Both of them are great, though, and generally crash-free. We're thankful for implementations on both operating systems, without which the Exodriver wouldn't exist.

QUOTE (Iandol @ Sep 2 2010, 03:52 PM) *
For what its worth (probably not much), libusb is the first item in the matlab crash stack; I can send you a crash log though doubt you'd be able to use it.


Yes, we would be happy to take a look.
 
Quote Post
Iandol
post Sep 3 2010, 07:24 AM
Post #8

Joined: 16-July 10
Posts: 46




QUOTE (LabJack Support @ Sep 2 2010, 11:45 PM) *
There's cause for optimism.


Not too much as all our production machines stil use OS X, which is the optimal OS for the Psychophysics toolbox! :p

I've attached the crashlogs for 3 representative crashes.

One other thing I noticed (this is on a high speed hub on a high speed port) when running via the command line, if I toggle FIO4 a thousand times in a tight loop and divide total time by number of switches, I get about a 1.6ms to switch between levels, and about 0.4ms doing the same on a FTDI USB -> serial. Now of course my FTDI doesn't do all the cool things the LabJack does, but just wondered as 1.6ms is higher than you have measured. I'll try the same in LabJackPython and see if it is any faster.

Thanks again for all your help!
Attached File(s)
Attached File  matlabcrash.zip ( 10.79K ) Number of downloads: 9
 
 
Quote Post
LabJack Support
post Sep 3 2010, 09:21 AM
Post #9

Joined: 9-June 03
Posts: 7527




QUOTE (Iandol @ Sep 3 2010, 08:24 AM) *
QUOTE (LabJack Support @ Sep 2 2010, 11:45 PM) *
There's cause for optimism.


Not too much as all our production machines stil use OS X


Of course. I meant optimism for tracking down the problem. Any news on Linux?

QUOTE (Iandol @ Sep 3 2010, 08:24 AM) *
I've attached the crashlogs for 3 representative crashes.


Thanks. We'll have a look.

QUOTE (Iandol @ Sep 3 2010, 08:24 AM) *
One other thing I noticed (this is on a high speed hub on a high speed port) when running via the command line, if I toggle FIO4 a thousand times in a tight loop and divide total time by number of switches, I get about a 1.6ms to switch between levels, and about 0.4ms doing the same on a FTDI USB -> serial. Now of course my FTDI doesn't do all the cool things the LabJack does, but just wondered as 1.6ms is higher than you have measured. I'll try the same in LabJackPython and see if it is any faster.


In LabJackPython we can get times consistent with Section 3.1 of the U3 User's Guide. That is, we can generally get about 0.6 ms with a hub and about 4 ms without a hub.

Here's without a hub:

CODE
>>> import u3
>>> from datetime import datetime
>>> d = u3.U3()
>>> def f():
...   t1 = datetime.now()
...   for i in range(1000):
...     d.getFIOState(4)
...   t2 = datetime.now()
...   print (t2-t1)/1000
...
>>> f()
0:00:00.004001
>>> f()
0:00:00.003999
>>> f()
0:00:00.004000


Here's after I plug in a crappy un-powered hub:

CODE
>>> d.close()
# Plug in crappy hub
>>> d = u3.U3()
>>> f()
0:00:00.001191
>>> f()
0:00:00.001191
>>> f()
0:00:00.001186


So in this case it runs at 1.2 ms, but with a good, powered hub it can go to 0.6 ms. The LabJackPython Examples/ directory has a file named u3allio.py that can measure the same thing:

CODE
$ python u3allio.py 1
Time difference:  0:00:01.171532
Time per iteration:  0:00:00.001171
Time per iteration in millis:  1.171
Latest readings:  [-8.9284480000000013]




 
Quote Post
LabJack Support
post Sep 3 2010, 10:46 AM
Post #10

Joined: 9-June 03
Posts: 7527




QUOTE (Iandol @ Sep 3 2010, 08:24 AM) *
I've attached the crashlogs for 3 representative crashes.


The first three lines of the stack trace in matlab_crash_dump.41577 are:

CODE
Stack Trace:
  [0] libusb-1.0.0.dylib:libusb_get_device~(0, 0, 0xb49031c8, 0x07606890 "9MatrixRef") + 9 bytes
  [1] liblabjackusb.dylib:LJUSB_SetupTransfer~(0, 0x3796f7b0, 12, 0) + 17 bytes
  [2] liblabjackusb.dylib:LJUSB_Write~(0, 0x3796f7b0, 12, 0x075ec2bb) + 39 bytes


The most likely cause of a crash here is an invalid handle (i.e., the first argument to all three functions).

Here are the prototypes of LJUSB_Write() and LJUSB_SetupTransfer():

CODE
unsigned long LJUSB_Write(HANDLE hDevice, BYTE *pBuff, unsigned long count)
static unsigned long LJUSB_SetupTransfer(HANDLE hDevice, BYTE *pBuff, unsigned long count, enum LJUSB_TRANSFER_OPERATION operation)


In LJUSB_SetupTransfer() we call libusb_get_device() like this:

CODE
    //First determine the device from handle.
    dev = libusb_get_device(hDevice);


and here is the prototype and code (it's very small) for libusb_get_device():

CODE
libusb_device *libusb_get_device(libusb_device_handle *dev_handle);

API_EXPORTED libusb_device *libusb_get_device(libusb_device_handle *dev_handle)
{
    return dev_handle->dev;
}


The only way I can understand that code failing is if the passed-in handle is invalid.

I can't read the stack trace well enough to know if a valid handle is passed in. The 12 in this line would match the count parameter:

CODE
  [1] liblabjackusb.dylib:LJUSB_SetupTransfer~(0, 0x3796f7b0, 12, 0) + 17 bytes


If the first 0 in that list is supposed to be the handle, then that's my guess what the problem is. Do you have a way to log/debug what the handle you pass in? (I'm sure you have no cause to believe it changes.)

The Exodriver has a function:

CODE
bool LJUSB_IsHandleValid(HANDLE hDevice);


that you might consider during debugging. Its purpose is really to detect if a LabJack has been disconnected since the last time it was called, but it could work here.
 
Quote Post
LabJack Support
post Sep 7 2010, 11:35 AM
Post #11

Joined: 9-June 03
Posts: 7527




For other Matlab users who require only 10 Hz or slower sampling, LJFuse is a very simple way to get data from your LabJack into Matlab. The process would be

CODE
fid = fopen('MyU6/connection/AIN0');
A = fscanf(fid, '%f');
fclose(fid);
 
Quote Post
Iandol
post Sep 14 2010, 02:19 AM
Post #12

Joined: 16-July 10
Posts: 46




Yes, you are absolutely spot on, it seems sometimes the handle is invalid. Now I'm not sure why it sometimes clears the handle during use, but by simply checking the handle is valid before calling a write, I don't see any more crashes. Still have to test it in Linux for C-R times, I've bought a brand new high-speed powered hub so lets see how Matlab and LabJackPython compare for command-response times (when I get time).
 
Quote Post
Iandol
post Nov 23 2010, 03:27 PM
Post #13

Joined: 16-July 10
Posts: 46




For anyone who wants it, my wrapper class to toggle FIO4 and FIO5 of the U3 in Matlab on OS X (and I assume Linux) is attached.

To use:

CODE
>> st = sendTTL %initialise new object, by default it will auto-open a connection to the U3
>> st.setFIO4(1) %set FIO4 high
>> st.toggleFIO4 %toggle this line
>> st.verbosity = 0 %don't write results to the command window
>> st.close


You can pass a structure of settings, and my constructor will ignore unknown settings:

CODE
>> st = sendTTL(struct('verbosity',0,'openNow',0,'header','/mypath/llj.h'))
>> st.open
>> st.toggleFIO4 %toggle this line
>> st.close


Attached File  sendTTL.m ( 7.33K ) Number of downloads: 33
 
Quote Post
Jamesce
post Sep 7 2012, 01:27 PM
Post #14

Joined: 7-September 12
Posts: 4




QUOTE (Iandol @ Nov 23 2010, 03:27 PM) *
For anyone who wants it, my wrapper class to toggle FIO4 and FIO5 of the U3 in Matlab on OS X (and I assume Linux) is attached.
Attached File  sendTTL.m ( 7.33K ) Number of downloads: 33


I saw your post on psychtoolbox, and I'm trying to look into the possibility of using labjack to send triggers to either a biosemi or brain products device from a mac, and I'm not familiar, at all, with I/O devices. From what I could tell, it seems like we should be able to use your code to send the trigger. Though, I wanted to double check that we would be able to send this from the parallel port on the U6, as this is how we have previously connected to the acquisition machine.

Thanks for any help you an provide in this regard.

~James


 
Quote Post
Iandol
post Sep 11 2012, 05:52 AM
Post #15

Joined: 16-July 10
Posts: 46




QUOTE (Jamesce @ Sep 7 2012, 09:27 PM) *
QUOTE (Iandol @ Nov 23 2010, 03:27 PM) *
For anyone who wants it, my wrapper class to toggle FIO4 and FIO5 of the U3 in Matlab on OS X (and I assume Linux) is attached.
Attached File  sendTTL.m ( 7.33K ) Number of downloads: 33


I saw your post on psychtoolbox, and I'm trying to look into the possibility of using labjack to send triggers to either a biosemi or brain products device from a mac, and I'm not familiar, at all, with I/O devices. From what I could tell, it seems like we should be able to use your code to send the trigger. Though, I wanted to double check that we would be able to send this from the parallel port on the U6, as this is how we have previously connected to the acquisition machine.

Thanks for any help you an provide in this regard.

~James


Yes, that should be no problem, if you know what pin you want, you can send a TTL on that pin easily, or do you need to send more than a TTL? My updated code is available here:

https://raw.github.com/iandol/opticka/maste...ation/labJack.m

You can send a TTL on any FIO, EIO or CIO pin, or you can send an 11bit strobed word on EIO and CIO which are most conveniently located on the LabJack DB15 connector. We use the strobed word from the DB15 to a Plexon omniplex DB25.

examples:
CODE
l = labJack('verbose',true);
l.timedTTL(0,500) %send a 500ms long TTL on FIO0
l.timedTTL(9,5) %send a 5ms long TTL on EIO1

l.setDIO([9,9,9]) % set FIO EIO and CIO channel 0 and 3 high

l.toggleFIO(4) % toggle FIO4 between low<>high

l.prepareStrobe(567,[],1) %send the value 567 via a strobed word on EIO and CIO
 
Quote Post
LabJack Support
post Sep 11 2012, 01:27 PM
Post #16

Joined: 9-June 03
Posts: 7527




For documentation on the DB37, DB15 and their connector pinouts, refer to these sections in the User's Guide:

http://labjack.com/support/u6/users-guide/2.11
http://labjack.com/support/u6/users-guide/2.12

For specifications on the digital I/O lines look at Appendix A:

http://labjack.com/support/u6/users-guide/appendix-a
 
Quote Post
Jamesce
post Sep 17 2012, 04:43 PM
Post #17

Joined: 7-September 12
Posts: 4




Ok. Like I said, I have no experience with I/O devices. So, I need to get an output from the labjack that is going to similar to the standard parallel port, particularly with the 8 data output lines. I found the following device, but am a bit worried about how to actually set this up and if this interface will cause delays in the signal.

Suggestions?

 
Quote Post
LabJack Support
post Sep 18 2012, 07:15 AM
Post #18

Joined: 9-June 03
Posts: 7527




QUOTE
So, I need to get an output from the labjack that is going to similar to the standard parallel port, particularly with the 8 data output lines.

What were you doing with the parallel port? Sending multiple bytes using a standard parallel port API, or using some low-level API to toggle a single bit or multiple bits?

The U3 or U6 both have enough digital I/O to do things similar to a parallel port. You would call matlab commands to change the state of various digital I/O in the sequence you need. You can do this on the order of milliseconds, but the estimated time depends on the exact sequence of I/O operations you need.
 
Quote Post
Jamesce
post Sep 18 2012, 09:09 AM
Post #19

Joined: 7-September 12
Posts: 4




We were sending a variable 8-bit code at different times throughout an experiment.

Here is some information from the eeg company:
http://www.biosemi.com/faq/trigger_signals.htm

Given that there are enough dio's, what would you recommend to do on the hardware side of things? What additional hardware might I need.

Best,
~James
 
Quote Post
LabJack Support
post Sep 18 2012, 09:44 AM
Post #20

Joined: 9-June 03
Posts: 7527




I am not real clear on what the Biosemi thing is or does, but the link does mention that it has 10k pull-ups. I suggest you take a digital I/O from the U3/U6 and try it. I would try EIO0, so connect EIO0 to one of the trigger inputs. Use the test panel in LJControlPanel (on Windows) to change the state of EIO0 and see if it causes the desired result on your device. Digital I/O have 3 states:

Input => Should result in high on your device
Output-High => Should result in high on your device
Output-Low => Should result in low on your device
 
Quote Post
Jamesce
post Sep 18 2012, 10:17 AM
Post #21

Joined: 7-September 12
Posts: 4




Sorry, but I am going to be shamelessly ignorant. How do I connect one EIO from the labjack to the db37 input of the device of interest? Really . . . I know absolutely nothing in this regard.
 
Quote Post
LabJack Support
post Sep 18 2012, 10:48 AM
Post #22

Joined: 9-June 03
Posts: 7527




You want to make a connection from EIO0 to your device pin any way you can. You also most likely want to connect GND on the LabJack to ground on your device.

On the LabJack side, EIO0 is on the DB15 connector of the U3 or U6:

http://labjack.com/support/u3/users-guide/2.11

The most common way to connect a wire to EIO0 would be to use a CB15 terminal board. Another way is to buy a DB15 cable, cut one end off, and pigtail the wires.

As for your device, if it has a DB37 connector try a google search for "db37 breakout screw-terminals" to find various options.
 
Quote Post
zim_bob
post Nov 9 2012, 11:12 AM
Post #23

Joined: 2-November 12
Posts: 4




Hi Ian,
Using your matlab code, is the TTL pulse positive logic when the line is at 0V and negative when the line is at 5V? Also, I can't seem to figure out how to read the voltage on an input line, i.e., I have a digital line in from my device that tells me when it's ready and I'm trying to read it from one of the FIOs.
Any help would be greatly appreciated!!!

~z
 
Quote Post
Iandol
post Nov 12 2012, 08:55 AM
Post #24

Joined: 16-July 10
Posts: 46




QUOTE (zim_bob @ Nov 9 2012, 06:12 PM) *
Using your matlab code, is the TTL pulse positive logic when the line is at 0V and negative when the line is at 5V? Also, I can't seem to figure out how to read the voltage on an input line, i.e., I have a digital line in from my device that tells me when it's ready and I'm trying to read it from one of the FIOs.
Any help would be greatly appreciated!!!


I only ever have grounded lines and pulse to +V so haven't written anything to pull a +V line to ground as a "signal". And you are correct, I don't have a method to read a digital line as I never need to. It should be trivial to add a method to do that, but I don't have the time to add those functions for the next couple of weeks at least, I'd be more than happy for you to make such modifications if you had the time. I will put it on my to-do for the future.
 
Quote Post
LabJack Support
post Nov 12 2012, 02:33 PM
Post #25

Joined: 9-June 03
Posts: 7527




If you want to read a single digital line take a look at this topic as it provides a quick C low-level example along with some documentation links:

http://forums.labjack.com/index.php?showtopic=5971

That should help with setting up the command and how to read the response packets/arrays. Take a look through Ian's source code to see how to write/read USB packets and calculate checksums in MATLAB.

C low-level examples are provided in the Exodriver source code and low-level documentation is in section 5 of the User's Guide.
 
Quote Post

2 Pages V   1 2 >
Reply to this topicStart new topic
1 User(s) are reading this topic (1 Guests and 0 Anonymous Users)
0 Members:
RSS