Hi,
Our lab is measuring EEG using a Measurement Computing USB1208FS DAQ. We recently have begun converting our lab from MacOSX to Linux due to the direction PTB is heading. However, in doing so, we’ve encountered an issue with the DAQ and communications with PTB on the Linux machines.
We’re using a Linux machine with the following specs:
Dell Precision Compact 3240 (2021)
Memory: 16 GB
Processor: 3.6 GHz NVIDIA Quadro Pro P400 2GB
Running with Ubuntu 18.04
PTB version: 3.0.17
Matlab version: 2020b.
We’re using custom code from Steve Luck’s lab (below called “seDAQ” to initialize the DAQ, which we have been using for years to communicate with the DAQ. However, this code was only ever designed for Mac and PC. We’ve tried to adopt the code to initialize the DAQ for Linux but always get hung up at the same place (see bolded line below).
In trying to communicate with the DAQ, we’ve been able to successfully get to the line of code where it uses the PTB function “DaqDConfigPort”, but it always freezes on the step where it tries to call “PsychHID” and initialize the USB port for the DAQ.
We’ve been able to run “PsychHIDDAQS” or “devices = PsychHID(‘Devices’);” and extract most of the information (though on Linux we fail to get the correct serial and product numbers, despite being able to do so on Mac). However, when we get to the step:
"err=PsychHID(‘SetReport’,daq,2,reportId,report); % Configure digital port."
We always encounter the same error no matter which of the DAQ functions or PsychHID functions we use. They always get hung up on the port configuration. We’ve tried different reportId and report settings and multiple “commonsense” approaches (turning the machine on and off, trying on Mac then trying on Linux, making sure things are plugged in, restarting Matlab, etc.).
The error message is always:
INTERNAL PSYCHTOOLBOX ERROR
error: PsychError_system
general description: Error reported by a system call
specific description: HIDLIB Failed to open USB device!
module name: PsychHID
subfunction call: SetReport
file name: Common/PsychHID/PsychHIDHelpers.c
function name: PsychHIDGetDeviceRecordPtrFromIndex
line number: 249
We have not been able to find a way to get past this step. I (the lead on troubleshooting this problem) do not know enough about C code either to resolve this error.
Any help would be greatly appreciated!
////// seDAQ.m ////////
classdef seDAQ < handle
% returns DAQ object/struct containing information to send out event codes
% to data acquisition device.
%
properties
isPresent = false; % whether the DAQ device is present or not
deviceNum = NaN; % number-pointer to DAQ device
lastCode = NaN; % value of last eventCode that was successfully sent out
end % properties
properties(Hidden = true, Constant = true)
RESP = 'resp'; %
EVENT = 'event';
EVENT_PORT = 0; % value to send eventCode out of event port
RESP_PORT = 1; % value to send eventCode out of response port
CONFIG_OUTPUT = 0; % value to designate if port as output
CONFIG_INPUT = 1; % value to designate if port as input
RESET_EVENTCODE = 0; % arbitrary number for resets
TIME_DELAY = 0.010; % (secs) time duration to leave event codes on after sending them out
EVENT_CODE_LIMIT = 255; % max event code
end
properties(Hidden = true)
pcIO; % input/output (IO) object to send event codes on PCs
BIOSEMI = 'Biosemi';
BRAINPRODUCTS = 'BrainProducts';
end
methods
function obj = seDAQ()
if ismac
obj.deviceNum = DaqDeviceIndex();
obj.isPresent = ~isempty(obj.deviceNum);
if(obj.isPresent)
configPorts(obj); % Basic DAQ-device Setup %
end
elseif ispc
buttonname=questdlg('Please select data acquisition system:','DAQ?',obj.BIOSEMI, obj.BRAINPRODUCTS, obj.BIOSEMI);
switch buttonname
case obj.BIOSEMI
obj.deviceNum = hex2dec('2050');
case obj.BRAINPRODUCTS
obj.deviceNum = hex2dec('2030');
end
obj.pcIO = io64();
obj.isPresent = ~io64(obj.pcIO);
end
end % daq constructor method
function configPorts(obj)
display(sprintf('Configuring ports %d and %d as output ports', obj.EVENT_PORT, obj.RESP_PORT));
DaqDConfigPort(obj.deviceNum, obj.EVENT_PORT, obj.CONFIG_OUTPUT); % configure as output port
DaqDConfigPort(obj.deviceNum, obj.RESP_PORT, obj.CONFIG_OUTPUT); % configure as output port
end % configPorts method
function sendEventCode(obj, eventCode)
% SENDEVENTCODE Sends event/response eventCode out to DAQ device.
% CODE must be an integer 1-254
if(obj.isPresent && (0 < eventCode < obj.EVENT_CODE_LIMIT))
if ismac
DaqDOut(obj.deviceNum, obj.EVENT_PORT, eventCode); % Send event code
WaitSecs(obj.TIME_DELAY);
DaqDOut(obj.deviceNum, obj.EVENT_PORT, obj.RESET_EVENTCODE); % Clear event code
WaitSecs(obj.TIME_DELAY);
elseif ispc
io64(obj.pcIO, obj.deviceNum, eventCode);
WaitSecs(obj.TIME_DELAY);
io64(obj.pcIO, obj.deviceNum, obj.RESET_EVENTCODE);
WaitSecs(obj.TIME_DELAY);
end
elseif(~obj.isPresent)
fprintf('Error:\tDAQ device not present\n\tEvent code %03d not sent\n',eventCode);
elseif(~(0 < eventCode <= obj.EVENT_CODE_LIMIT))
fprintf('Warning:\tEvent code exceeds limit (%d)\n\t\tEvent code %03d not sent\n', obj.EVENT_CODE_LIMIT, eventCode);
end
end
end % methods
end