在试验中多次按下Matlab Psychtoolbox fprintf错误

时间:2019-03-13 09:34:56

标签: matlab psychtoolbox

我有一个实验来收集按键(“ x”或“ n”)和响应时间,以响应刺激显示。如果参与者在每次尝试中按下任一按钮一次,则实验运行良好。但是,如果他们反复按键盘或按住某个键,则经常会崩溃。 (我与孩子们一起工作,即使我们不要求他们这样做,这种情况仍然经常发生)。

当其崩溃时出现的错误是:

  

未为“单元格”输入定义功能。

     

实验错误(第682行)

     

fprintf(dataFile,formatString,SJNB,Date,Age,block,trial,trialFaceLabel,trialLoadLabel,Target,keyStroke,tStart,keyTime,Correct,RT,FaceGen);

尽管它说“未为“单元格”输入定义功能(与this相关),但此功能在其他所有时间似乎都正常工作,所以我看不到它根本没有正确定义。仅当连续按下太多按键时(例如,如果按住该键),才会发生此错误。

即使每次试验有多次按键操作,我也可以进行哪些更改以确保实验可靠且不会崩溃?任何帮助,将不胜感激。

我已包含以下代码。

如果有帮助,这里还有一些其他信息:

  • 在实验试验之前,有一个练习循环,该循环的设置方式几乎相同,但有两个主要区别:1)屏幕上显示的刺激不同,以及2)未记录按键。这个循环似乎从未崩溃过。

  • 崩溃后,按键响应将打印到命令行。

  • 我看过其他类似的帖子,例如this发布,但据我所知,我编写的按键循环也应该在按下某个按键后立即退出-因此我不确定为什么我的按键循环无法以同样的方式工作。

下面的代码全部包含在实验循环中。它正在做什么: 1)搜索按键 2)根据按键计算响应时间 3)如果响应不正确则发出蜂鸣声 4)打印到文件(这刚好在试验结束之前)(这是错误所引用的行)

            %searching for keypress
            timedout = false;
            pressed = 0;
            %while pressed < 1;

            while ~timedout && ~pressed

                [keyIsDown, keyTime, keyCode] = KbCheck;

                if keyIsDown && ((keyTime-tStart) < max_stimulus_shown)
                    keyStroke = KbName(keyCode);
                    if any(strcmpi(keyStroke,leftKey)) || any(strcmpi(keyStroke,rightKey)) %|| any(strcmpi(keyStroke,exitKey))
                        pressed = 1;
                        WaitSecs(remainer-(keyTime-stimulus_shown));
                        break;
                    elseif any(strcmpi(keyStroke,exitKey))
                    disp('*** Experiment terminated ***');
                        break;
                        sca;
                    end
                elseif ((keyTime-tStart) > max_stimulus_shown)
                keyStroke = 'None';
                timedout = true;
                RT = 0;
                Correct = 0;
                pressed = 2; % 2 = not pressed
                KbQueueStop(); 
                end
            end 

            %calculate response times
            if pressed == 1 && (~timedout)
            RT = round((keyTime-tStart)*1000); % RT in ms
            if any(strcmpi(keyStroke,leftKey)) % pressed left (X)
                if any(strcmpi(Target, 'X')) % target was an X
                    Correct = 1;
                else % target was X, but pressed right (N)
                    Correct = 0;
                end
            elseif any(strcmpi(keyStroke,rightKey)) % they pressed right 
                if any(strcmpi(Target, 'N')) % target was an N
                    Correct = 1;
                else % target was N, but pressed right
                    Correct = 0;
                end
            elseif any(strcmpi(keyStroke,exitKey))
                disp('ESC');
                break;
            end
            end

            Screen('TextSize',Screen_wid, star_size);
            DrawFormattedText(Screen_wid, '.', 'center', 'center');
            WaitSecs(feedback);
            Screen('Flip', Screen_wid);

            %say when to beep                
            if Correct == 0 && ~timedout
            PsychPortAudio('Start', pahandle, repetitions, startCue, waitForDeviceStart);
            WaitSecs(remainer-beepLengthSecs);
            elseif Correct == 0 && timedout
            PsychPortAudio('Start', pahandle, repetitions, startCue, waitForDeviceStart);
            Screen('TextSize',Screen_wid, text_size);
            DrawFormattedText(Screen_wid, 'missed trial', 'center', 'center');
            Screen('Flip', Screen_wid);
            WaitSecs(beepLengthSecs+feedback);
            elseif Correct == 1
            WaitSecs(remainer+beepLengthSecs);
            end

            %WaitSecs(stimulus_shown); %stimulus shown for 0.2 seconds
            Screen('Flip', Screen_wid);

            dataFile = fopen(dataFileName, 'a');                               
            fprintf(dataFile, formatString, SJNB, Date, Age, block, trial, trialFaceLabel, trialLoadLabel, Target, keyStroke, tStart, keyTime, Correct, RT, FaceGen);
            fclose(dataFile);   

1 个答案:

答案 0 :(得分:0)

函数KbName通过Kb​​Check返回的键码矢量(key_name = KbName([21 22])或逻辑矢量)返回输入的键名字符串。

如果仅提供键/为True,则将其作为字符串返回。但是,如果同时按下多个键,则将其作为字符串的单元格数组返回。

例如,查看以下内容的输出:

% for key name consistency across operating systems
KbName('UnifyKeyNames')

% one key
KbName(21)

ans =

r

% more than one key
KbName([21 22])

ans =

  1×2 cell array

    'r'    's'

您的问题是,当同时按下多个按键(相对于按键检查循环)时,keyStroke是一个包含已按下按键的单元格数组。您似乎似乎在大多数代码中都正确处理了单元格数组,但对fprintf的调用除外,该调用需要单个字符串,而不是字符串的单元格数组。

如果要保存所有按下键的记录,可以将字符串的单元格数组转换为单个字符串,并在元素之间使用定界符,例如,在调用fprintf之前添加以下行:

if iscell(keyStroke)
    keyStroke = strjoin(keyStroke, '_');
end

但是,请记住,您可能希望更改实验的逻辑以拒绝按下两个键的试验,或者将它们与单个键的响应区别对待。当前,您以“左”键为优先,换句话说,如果参与者按了左键,而目标是“ X”,则即使也按了右键,也会将审判标记为正确。相反,如果参与者按下了左键,并且目标是“ N”,则即使同时按下了右键,试验也会被标记为错误。