Why is KbCheck in Psychtoolbox not registering keyboard input? - matlab

I'm trying to run a programme coded in Psychtoolbox-3 that should register a keypress. But when I run it, even just this section from the command window, it doesn't respond to the E, P keys (or any) and I have to stop the operation using Ctrl-C. I have tried changing it to {e, p} (which are the names I found using KbName('KeyNames')), but it doesn't work.
The same code works on my supervisor's computer - I am using a Mac with OS 11.1.
KbName('UnifyKeyNames');
keyresp = KbName({'E','P'});
key = 0;
while ~key
[key,tkey] = CheckKeyPress(keyresp);
end
The CheckKeyPress is this function (and it works - gives output 0):
function [key,tkey] = CheckKeyPress(whichkeys)
if nargin < 1 || isempty(whichkeys)
whichkeys = 1:256;
end
key = 0;
[iskeydown,tkey,keys] = KbCheck(-1);
if any(keys(whichkeys))
key = find(keys(whichkeys),1);
end
end
I have also tried looking at PsychHID('Devices') and my keyboard is there (and no other keyboards).
Thanks for any help!

Solved! It was a simple mac problem :)
After I tried KbQueueCreate and got an error message I found the same one on another thread - the only problem is I had to allow Matlab to access keyboard input on my laptop.
Settings - Security and Privacy - Input Monitoring

It is always a big pain in MacOs. I use this code:
close all
clear all
clc
ListenChar(0);
Devices=PsychHID('Devices');
keyboardsIDs = [];
for iiD = 1:numel(Devices)
try
KbQueueCreate(Devices(iiD).index);
KbQueueStart(Devices(iiD).index);
keyboardsIDs(end+1,1) = Devices(iiD).index;
end
end
stopScript = 0;
while ~stopScript
for iiD = 1:numel(keyboardsIDs)
[keyIsDown, firstPress]=KbQueueCheck(keyboardsIDs(iiD));
if keyIsDown
keyID = find(firstPress)
disp(keyID)
if any(keyID ==20), stopScript =1; end
end
end
end
for iiD = 1:numel(keyboardsIDs)
KbQueueStop(keyboardsIDs(iiD));
end
ListenChar();
UPDATE
This is a bit dirty workaround, but it will works in any situation.
Press 'q' to exit the loop

Related

Receive Mail if matlab is in debugging mode

I'd like to receive an email when Matlab is in debugging mode, so I tried the following:
timerTic=4; % how often the timer checks
timerHandle = timer();
timerHandle.startDelay = timerTic;
timerHandle.Period = timerTic;
timerHandle.ExecutionMode = 'fixedRate';
timerHandle.TasksToExecute = inf;
timerHandle.TimerFcn = #CheckDebugMode;
j=0;
while t==0
j=j+1;
end
where the funcion is:
function CheckDebugMode( ~ )
% Check if Matlab is in Debug mode
if feature('IsDebugMode')
sendSSLmail('mymail#mycountry','Matlab is in debug mode','Matlab is in debug mode')
end
t doesn't exist so that an error occurs and Matlab enters in debug mode (dbstop if error is active).
feature('IsDebugMode') is equal to 1, but I receive no mail.
It's the first time I work with objects in Matlab, so I'm pretty sure the code is in someway wrong.
Maybe someone can help me?
Thanks in advance
Do you start your timer?
start(timerHandle)
edit I haven't tested this but I suspect you have problems with your function handle and the function itself. The timer passes arguments to your function, so you need to accept then in your code:
function CheckDebugMode( varargin )
or stop then from being passed:
timerHandle.TimerFcn = #(~,~)CheckDebugMode

While debugging with an input from the keyboard, I want to able to skip the execution of a few lines of code in MATLAB

Currently I have this excerpt of code I am trying to debug:
if (white_flag == 1)
keyboard;
imshow(rl_img);
N = N+1;
times(times_index,1) = index;
while(white_flag == 1)
imshow(rl_img);
index = index+1;
%%% If statement for when the loop has run out
if (index >= frames)
break
end
%%% Initial Image Pre-Processing
rl_img = ones(mod_height,width);
pre_rl_img = medfilt2(vreader.read(index));
for i = 1:mod_height
for j = 1:width
rl_img(i,j) = pre_rl_img(i,j);
end
end
white_flag = detect_white( rl_img, white_flag );
end
times(times_index,2) = index;
times_index = times_index+1;
else
index = index+ 1;
end
Now, as you can see, the debug keyboard input call keybaord is on the second line. While this allows me to efficiently see each step of the execution of my program, I do not understand how to skip over the part below:
for i = 1:mod_height
for j = 1:width
rl_img(i,j) = pre_rl_img(i,j);
end
end
This is a rather sizable picture(rl_img), so waiting for keyboard input while I scrawl through the code manually wastes a lot of time. Can someone please tell me how to skip the user input execution of these lines of code while I debug the program?
Please do not hesitate to ask me any questions that can clarify this problem. Thank you for all your answers!
The answer is quite straightforward:
you set a breakpoint after the lengthy loop,
when you decide to run automatically all the rest of the loop up to the breakpoint you just set, press [F5] (Continue).
This assumes that you debug your code in the normal MATLAB IDE.
If I understand your problem correctly, you don't want to step through each loop iteration.
You can either follow CST-Link's advice or you can avoid creating additional breakpoints by placing your cursor somewhere after the loop
and clicking
on the editor's debug panel.

Closing MATLAB GUI application programmatically without using error()

I am trying to make it so the application/gui closes completely if the user clicks cancel or exit of an input dialog. The tag of my gui is called window however using close(handles.window); leads to the program looping through once and then (after the user clicks cancel or exit again) reaching the close(handles.window); line which, of course, leads to an Invalid figure handle error.
Is there any method to close the application without the need for producing an error and not closing the entire MATLAB environment (like quit and exit). The error() is my temporary fix which works but I don't want the application to seem like it has crashed.
I have tried close all but that has no effect. It's worth noting that the application does reach inside the if statement if the user clicks cancel or exit.
I have also tried setting a variable and having the close commands outside the while loop.
apa = getAvailableComPort();
apList = '';
i = 0;
for idx = 1:numel(apa)
if i == 0
apList = apa(idx);
else
apList = strcat(apList, ', ', apa(idx));
end
i = i + 1;
end
prompt = {'Enter COM PORT:'};
title = 'COM PORT';
num_lines = 1;
def = apList;
COM_PORT = inputdlg(prompt,title,num_lines,def);
% Keep asking for a COM PORT number until user gives a valid one
while sum(ismember(apa, COM_PORT)) == 0 % If the COM port comes up in the available COM ports at least once
% If user clicks cancel, close the guide
if isempty(COM_PORT) == 1
error('Closing...'); % HERE IS THE PROBLEM
end
prompt = {'Invalid COM PORT'};
title = 'Invalid COM PORT';
COM_PORT = inputdlg(prompt,title,num_lines,def);
end
The function getAvailableComPort is found at http://www.mathworks.com/matlabcentral/fileexchange/9251-get-available-com-port
This entire piece of code is at the top of the gui_OpeningFcn() function.
Have you tried putting a break after the close(handles.window). The break will exit the while loop so it won't hit that line again.
if isempty(COM_PORT) == 1
close(handles.window)
break
end
This way the while loop stops after closing the window. IF you need to do more cleanup besides just closing the window then set an error flag .
%Above while loop
errorFlag = False;
if isempty(COM_PORT) == 1
close(handles.window)
errorFlag = True;
break
end
%OutSide of While loop
if errorFlag
%Do some more clean-up / return / display an error or warning
end
Also FYI, you don't need to do isempty(COM_PORT) == 1 ... isempty(COM_PORT) will return true/false without the == 1
Your requirements aren't really clear, but can't you just protect the close operation by doing
if ishandle(handle.window)
close(handle.window)
end
This will prevent the close from being attempted if the window has already been destroyed.
Why don't you use a simple return and a msgbox to inform that user has clicked on Cancel?
if isempty(COM_PORT)
uiwait(msgbox('Process has been canceled by user.', 'Closing...', 'modal'));
delete(your_figure_handle_here);
return;
end
I tried using the return statement in conjunction with close(handles.window) but received the error:
Attempt to reference field of non-structure array.
Error in ==> gui>gui_OutputFcn at 292 varargout{1} = handles.output;
So it seems just removing that line on 292 solved the issue.

Create a program solution using Matlab

How can i create a program solution using Matlab for the problem below?
The program will prompt for number of people, which will be input from keyboard, and saves it in a variable called noOfPeople. It will then prompt for the age of each person and saves them in a matrix called ages. The program will also need to check if the ages are between 0-60. If age, if above 60, the program will give an error "invalid, try again..".
This is a simple program to capture the number of people and their ages.
You should run the following from the command prompt:
y = myprogram;
function y = myprogram(~)
noOfPeople = input('No of people');
for i = 1:noOfPeople
age = input('input age between 0-60');
if (double(age)>60 || double(age<0))
error('Invalid, try again!');
end
y(i) = age;
end

Internet Connection Status using MATLAB

Is there a way to check if I'm connected to the internet using MATLAB? Is there a function that returns true if it's connected
to the internet?
A similar approach to the above:
function tf = haveInet()
tf = false;
try
address = java.net.InetAddress.getByName('www.google.de')
tf = true;
end
end
It does have the benefit of not spawning an additional process and being independent from the fact, whether a particular site may at the moment be unavailable (which might be a good or bad feature).
How about using a ping to one of Google's DNSes?
if ispc
C = evalc('!ping -n 1 8.8.8.8');
elseif isunix
C = evalc('!ping -c 1 8.8.8.8');
end
loss = regexp(C, '([0-9]*)%.*loss', 'tokens');
connected = ~isempty(loss) && str2double(loss{1}{1})==0;