Mgl has some functions to handle digital I/O with a National Instruments card (e.g. NI USB 6501) that can be used to read and write digital I/O signals. These can be useful to synch to an MR scanner or control an external eye tracker. These functions all live in the directory:
These need to be compiled specially, in mgl 2.0 by running (earlier versions, just go mex by hand):
You will need to have downloaded the National Instruments drivers (see next section) to compile and use these functions.
Note that these functions are now compatible with both 32-bit and 64-bit Matlab even though the NI software (NI-DAQmx Base is not actually 64-bit compliant on Mac). See here for more details.
You can use a National Instruments card for digital I/O with mgl by doing the following:
- Download NI-DAQmx Base. You should use the latest version, as of this writing 3.6.0. You may need to make a free account with NI.
- Make sure that the device (NI USB-6501) has up-to-date firmware, by running FWUpdate (included in Ni-DAQmx Base/bin)
- Restart matlab if you have already run readDigPort (the program has to reinit the driver)
- Documentation is installed and should be available from:
- Follow the instructions above to compile mglDigIO and related functions.
- You should connect your input and output digital lines to the proper port and lines on your NI card that you want. Note that by default mglDigIO is set up to read from port 2 and write to port 1 of your NI card (but you can configure this when you run the mglDigiO('init') command. You should reference your manual for the pinouts on the board you use. For the NI-6501 see here.
- Run mglDigIO('init') and you should see the following:
>> mglDigIO('init') No matching processes belonging to you were found (mglStandaloneDigIO) Initializing NI device with digin port: Dev1/port2 digout port: Dev1/port1. End with mglDigIO('quit'). (mglStandaloneDigIO) Successfully initialized NI device (mglStandaloneDigIO) New connection made: 0 (mglPrivateDigIO) DigIO is running.
- You should be able to read digin events using the digin command (note the first time it will report if any of the lines are high, but not report anything for ports that are low).
>> mglDigIO('digin') ans = type: [1 1 1 1 1 1 1 1] line: [0 1 2 3 4 5 6 7] when: [934383.731613 934383.731624 934383.731625 934383.731626 934383.731626 934383.731628 934383.731629 934383.731629]
availability: mgl 2.0 Mac OS X only
purpose: This is a mac specific command that is used to control a NI digital IO board. It has been tested with the NI USB 6501. It runs as a thread (on 64-bit runs a separate process and communicates via a socket: see below) that reads digital port 2 and logs any change in state (either up or down). It can also be used to set digital lines on port 1 at a time of your choosing. It is used by the task code if you set mglEditScreenParams to use digin. It is the preferred way of dealing with digital I/O since it keeps excellent timing. Note that if you are trying to read events up to about 250Hz (e.g. a square wave of 250Hz), you should be able to read all events without fail. Faster than that at around 500Hz you will likely start dropping events (this is likely due to how fast the NI-DAQ mxBase driver can pool the device). To use this function, you will need to compile it using mglMake('digin'); Here are thte commands it accepts:
|1:'init'||Init the digIO thread. You need to run this before anything else will work. You can optional specify input and output ports which default to 1 and 2 respectively: mglDigIO('init',inputPortNum,outputPortNum); You can call init with different port numbers to reset what ports you want to listen/write to/from without calling quit inbetween.|
|2:'digin'||Returns all changes on the input digital port|
|3:'digout'||Set the output digital port a time of your choosing. This takes 2 other values. The time in seconds that you want the digital port to be set. And the value you want it to be set too. Time can be either an absolute time returned by mglGetSecs or it can be relative to now if it is a negative value: mglDigIO('digout',-5,0) → Sets the output port to 0 five secs from now.|
|4:'list'||Lists status and all pending digout events|
|0:'quit'||Closes the nidaq ports, after this you won't be able to run other commands. Note that this does not shutdown the digIO thread. The reason for this is that the NIDAQ library is not thread safe, so you can only call its functions from one thread, so to be able to keep starting and stopping reading from the card, the thread is set to continue to run, and quit simply shuts down the nidaq tasks and stops logging events. After you call quit, you can use init again to restart reading/writing. If you need to shutdown the thread, use 'shutdown'|
|-1:'shutdown'||Quits the digIO thread if it is running, after this you won't be able to run other commands. If you plan on starting and stopping digIO collection, you should use init and quit rather than shutdown|
purpose: write an ouput to the National Instruments board. portNum defaults to 2, to write from Dev1/port2. The first time you read it needs to open the port to the NI device which can take some time. Subsequent calls will be faster. Note that you can only open one port at a time, so if you need to read from two different ports it will always be closing and reopening the ports which will cause a performance hit (consider rewriting the code to keep multiple ports open if you need this). Also, if you want to switch between reading and writing on a single port, you will need to manually close the port in between read/write calls by setting portNum = -1 (see below). portNum can also be set to:
|-1||closes any open port|
|-2||displays which port (if any) is open.|
Note that in the distribution, writeDigPort is not compiled. It always returns 0. To use it to read your NI card, you will need to mex readDigPort.c, this requires you to install the NI-DAQmx Base Frameworks.
purpose: read the National Instruments board digital input. portNum defaults to 1, to read from Dev1/port1. The first time you read it needs to open the port to the NI device which can take some time. Subsequent calls will be faster. Note that you can only open one port at a time, so if you need to read from two different ports it will always be closing and reopening the ports which will cause a performance hit (consider rewriting the code to keep multiple ports open if you need this). Also, if you want to switch between reading and writing on a single port, you will need to manually close the port in between read/write calls by setting portNum = -1 (see below). portNum can also be set to:
|-1||closes any open port|
|-2||displays which port (if any) is open.|
Note that: in the distribution, readDigPort is not compiled. It always returns 0. To use it to read your NI card, you will need to mex readDigPort.c, this requires you to install the NI-DAQmx Base Frameworks.
The NI-DAQmx Base library is currently (4/20/2013) available only for 32-bit (Note that version 3.6 will run on a 64 bit platform, but you can't create 64 applications). To get around this on 64-bit Matlab, we run a separate function called mglStandaloneDigIO and communicate with that function through a socket. This is all done in the background for you so there is nothing that you have to do if you use mglDigIO.
The way it works is as follows. When you init, by doing mglDigIO('init') the function mglStandaloneDigIO is started. This function will connect to the NI card and answer commands through a socket (named .mglDigIO in your home directory). The function mglDigIO when called to get digin events or set digout events connects through the socket and communicates with mglStandaloneDigIO. This function will continue to run until you quit matlab or run mglDigIO('shutdown'). If you need to shut this function down from outside matlab, you can do from a command line:
Measurement Computing makes a USB based digital I/O device with a 64 bit library for Mac which potentially could be a replacement for National Instruments which does not have a 64-bit library. However, we found that the driver needs to have c# support through the Mono Framework and were not able to find a way to make this compatible with Matlab through a Mex file. For reference, the driver can be downloaded from here.